| /* |
| * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package jdk.vm.ci.hotspot; |
| |
| import jdk.vm.ci.common.JVMCIError; |
| |
| /** |
| * Access to VM configuration data. |
| */ |
| public class HotSpotVMConfigAccess { |
| |
| /** |
| * Gets the available configuration data. |
| */ |
| public HotSpotVMConfigStore getStore() { |
| return store; |
| } |
| |
| /** |
| * Gets the address of a C++ symbol. |
| * |
| * @param name name of C++ symbol |
| * @param notPresent if non-null and the symbol is not present then this value is returned |
| * @return the address of the symbol |
| * @throws JVMCIError if the symbol is not present and {@code notPresent == null} |
| */ |
| public long getAddress(String name, Long notPresent) { |
| Long entry = store.vmAddresses.get(name); |
| if (entry == null) { |
| if (notPresent != null) { |
| return notPresent; |
| } |
| throw new JVMCIError("expected VM symbol not found: " + name); |
| } |
| return entry; |
| } |
| |
| /** |
| * Gets the address of a C++ symbol. |
| * |
| * @param name name of C++ symbol |
| * @return the address of the symbol |
| * @throws JVMCIError if the symbol is not present |
| */ |
| public long getAddress(String name) { |
| return getAddress(name, null); |
| } |
| |
| /** |
| * Gets the size of a C++ type. |
| * |
| * @param name name of the type |
| * @return the size in bytes of the requested field |
| * @throws JVMCIError if the field is not present and {@code notPresent} is null |
| */ |
| public int getTypeSize(String name) { |
| Long entry = store.vmTypeSizes.get(name); |
| if (entry == null) { |
| throw new JVMCIError("expected VM type not found: " + name); |
| } |
| return (int) (long) entry; |
| } |
| |
| /** |
| * Gets the value of a C++ constant. |
| * |
| * @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"}) |
| * @param type the boxed type to which the constant value will be converted |
| * @param notPresent if non-null and the constant is not present then this value is returned |
| * @return the constant value converted to {@code type} |
| * @throws JVMCIError if the constant is not present and {@code notPresent == null} |
| */ |
| public <T> T getConstant(String name, Class<T> type, T notPresent) { |
| Long c = store.vmConstants.get(name); |
| if (c == null) { |
| if (notPresent != null) { |
| return notPresent; |
| } |
| throw new JVMCIError("expected VM constant not found: " + name); |
| } |
| return type.cast(convertValue(name, type, c, null)); |
| } |
| |
| /** |
| * Gets the value of a C++ constant. |
| * |
| * @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"}) |
| * @param type the boxed type to which the constant value will be converted |
| * @return the constant value converted to {@code type} |
| * @throws JVMCIError if the constant is not present |
| */ |
| public <T> T getConstant(String name, Class<T> type) { |
| return getConstant(name, type, null); |
| } |
| |
| /** |
| * Gets the offset of a non-static C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param type the boxed type to which the offset value will be converted (must be |
| * {@link Integer} or {@link Long}) |
| * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) |
| * @param notPresent if non-null and the field is not present then this value is returned |
| * @return the offset in bytes of the requested field |
| * @throws JVMCIError if the field is static or not present and {@code notPresent} is null |
| */ |
| public <T> T getFieldOffset(String name, Class<T> type, String cppType, T notPresent) { |
| assert type == Integer.class || type == Long.class; |
| VMField entry = getField(name, cppType, notPresent == null); |
| if (entry == null) { |
| return notPresent; |
| } |
| if (entry.address != 0) { |
| throw new JVMCIError("cannot get offset of static field " + name); |
| } |
| return type.cast(convertValue(name, type, entry.offset, cppType)); |
| } |
| |
| /** |
| * Gets the offset of a non-static C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param type the boxed type to which the offset value will be converted (must be |
| * {@link Integer} or {@link Long}) |
| * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) |
| * @return the offset in bytes of the requested field |
| * @throws JVMCIError if the field is static or not present |
| */ |
| public <T> T getFieldOffset(String name, Class<T> type, String cppType) { |
| return getFieldOffset(name, type, cppType, null); |
| } |
| |
| /** |
| * Gets the offset of a non-static C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param type the boxed type to which the offset value will be converted (must be |
| * {@link Integer} or {@link Long}) |
| * @return the offset in bytes of the requested field |
| * @throws JVMCIError if the field is static or not present |
| */ |
| public <T> T getFieldOffset(String name, Class<T> type) { |
| return getFieldOffset(name, type, null, null); |
| } |
| |
| /** |
| * Gets the address of a static C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) |
| * @param notPresent if non-null and the field is not present then this value is returned |
| * @return the address of the requested field |
| * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null |
| */ |
| public long getFieldAddress(String name, String cppType, Long notPresent) { |
| VMField entry = getField(name, cppType, notPresent == null); |
| if (entry == null) { |
| return notPresent; |
| } |
| if (entry.address == 0) { |
| throw new JVMCIError(name + " is not a static field"); |
| } |
| return entry.address; |
| } |
| |
| /** |
| * Gets the address of a static C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) |
| * @return the address of the requested field |
| * @throws JVMCIError if the field is not static or not present |
| */ |
| public long getFieldAddress(String name, String cppType) { |
| return getFieldAddress(name, cppType, null); |
| } |
| |
| /** |
| * Gets the value of a static C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param type the boxed type to which the constant value will be converted |
| * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) |
| * @param notPresent if non-null and the field is not present then this value is returned |
| * @return the value of the requested field |
| * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null |
| */ |
| public <T> T getFieldValue(String name, Class<T> type, String cppType, T notPresent) { |
| VMField entry = getField(name, cppType, notPresent == null); |
| if (entry == null) { |
| return notPresent; |
| } |
| if (entry.value == null) { |
| throw new JVMCIError(name + " is not a static field"); |
| } |
| return type.cast(convertValue(name, type, entry.value, cppType)); |
| } |
| |
| /** |
| * Gets the value of a static C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param type the boxed type to which the constant value will be converted |
| * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) |
| * @return the value of the requested field |
| * @throws JVMCIError if the field is not static or not present |
| */ |
| public <T> T getFieldValue(String name, Class<T> type, String cppType) { |
| return getFieldValue(name, type, cppType, null); |
| } |
| |
| /** |
| * Gets the value of a static C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param type the boxed type to which the constant value will be converted |
| * @return the value of the requested field |
| * @throws JVMCIError if the field is not static or not present |
| */ |
| public <T> T getFieldValue(String name, Class<T> type) { |
| return getFieldValue(name, type, null, null); |
| } |
| |
| /** |
| * Gets a C++ field. |
| * |
| * @param name fully qualified name of the field |
| * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) |
| * @param required specifies if the field must be present |
| * @return the field |
| * @throws JVMCIError if the field is not present and {@code required == true} |
| */ |
| private VMField getField(String name, String cppType, boolean required) { |
| VMField entry = store.vmFields.get(name); |
| if (entry == null) { |
| if (!required) { |
| return null; |
| } |
| throw new JVMCIError("expected VM field not found: " + name); |
| } |
| |
| // Make sure the native type is still the type we expect. |
| if (cppType != null && !cppType.equals(entry.type)) { |
| throw new JVMCIError("expected type " + cppType + " but VM field " + name + " is of type " + entry.type); |
| } |
| return entry; |
| } |
| |
| /** |
| * Gets a VM flag value. |
| * |
| * @param name name of the flag (e.g., {@code "CompileTheWorldStartAt"}) |
| * @param type the boxed type to which the flag's value will be converted |
| * @return the flag's value converted to {@code type} or {@code notPresent} if the flag is not |
| * present |
| * @throws JVMCIError if the flag is not present |
| */ |
| public <T> T getFlag(String name, Class<T> type) { |
| return getFlag(name, type, null); |
| } |
| |
| /** |
| * Gets a VM flag value. |
| * |
| * @param name name of the flag (e.g., {@code "CompileTheWorldStartAt"}) |
| * @param type the boxed type to which the flag's value will be converted |
| * @param notPresent if non-null and the flag is not present then this value is returned |
| * @return the flag's value converted to {@code type} or {@code notPresent} if the flag is not |
| * present |
| * @throws JVMCIError if the flag is not present and {@code notPresent == null} |
| */ |
| public <T> T getFlag(String name, Class<T> type, T notPresent) { |
| VMFlag entry = store.vmFlags.get(name); |
| if (entry == null) { |
| if (notPresent != null) { |
| return notPresent; |
| } |
| throw new JVMCIError("expected VM flag not found: " + name); |
| } |
| return type.cast(convertValue(name, type, entry.value, entry.type)); |
| } |
| |
| private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError { |
| if (toType == Boolean.class) { |
| if (value instanceof String) { |
| return Boolean.valueOf((String) value); |
| } else if (value instanceof Boolean) { |
| return value; |
| } else if (value instanceof Long) { |
| return ((long) value) != 0; |
| } |
| } else if (toType == Byte.class) { |
| if (value instanceof Long) { |
| return (byte) (long) value; |
| } |
| } else if (toType == Integer.class) { |
| if (value instanceof Integer) { |
| return value; |
| } else if (value instanceof Long) { |
| return (int) (long) value; |
| } |
| } else if (toType == Long.class) { |
| return value; |
| } |
| |
| throw new JVMCIError("cannot convert " + name + " of type " + value.getClass().getSimpleName() + (cppType == null ? "" : " [" + cppType + "]") + " to " + toType.getSimpleName()); |
| } |
| |
| private final HotSpotVMConfigStore store; |
| |
| public HotSpotVMConfigAccess(HotSpotVMConfigStore store) { |
| this.store = store; |
| } |
| } |