/*
 * Copyright (c) 2016, 2019, 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 java.util.Set;
import java.util.stream.Collectors;

import jdk.vm.ci.common.JVMCIError;

Access to VM configuration data.
/** * Access to VM configuration data. */
public class HotSpotVMConfigAccess {
Gets the available configuration data.
/** * Gets the available configuration data. */
public HotSpotVMConfigStore getStore() { return store; }
Gets the address of a C++ symbol.
Params:
  • name – name of C++ symbol
  • notPresent – if non-null and the symbol is not present then this value is returned
Throws:
  • JVMCIError – if the symbol is not present and notPresent == null
Returns:the address of the symbol
/** * 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 missingEntry("address", name, store.vmFlags.keySet()); } return entry; }
Gets the address of a C++ symbol.
Params:
  • name – name of C++ symbol
Throws:
Returns:the address of the symbol
/** * 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 value of a C++ constant.
Params:
  • name – name of the constant (e.g., "frame::arg_reg_save_area_bytes")
  • type – the boxed type to which the constant value will be converted
  • notPresent – if non-null and the constant is not present then this value is returned
Throws:
  • JVMCIError – if the constant is not present and notPresent == null
Returns:the constant value converted to type
/** * 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 missingEntry("constant", name, store.vmConstants.keySet()); } return type.cast(convertValue(name, type, c, null)); }
Gets the value of a C++ constant.
Params:
  • name – name of the constant (e.g., "frame::arg_reg_save_area_bytes")
  • type – the boxed type to which the constant value will be converted
Throws:
Returns:the constant value converted to type
/** * 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.
Params:
  • name – fully qualified name of the field
  • type – the boxed type to which the offset value will be converted (must be Integer or Long)
  • cppType – if non-null, the expected C++ type of the field (e.g., "HeapWord*")
  • notPresent – if non-null and the field is not present then this value is returned
Throws:
  • JVMCIError – if the field is static or not present and notPresent is null
Returns:the offset in bytes of the requested field
/** * 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) { return getFieldOffset0(name, type, notPresent, cppType, null); }
Gets the offset of a non-static C++ field.
Params:
  • name – fully qualified name of the field
  • type – the boxed type to which the offset value will be converted (must be Integer or Long)
  • notPresent – if non-null and the field is not present then this value is returned
  • outCppType – if non-null, the C++ type of the field (e.g., "HeapWord*") is returned in element 0 of this array
Throws:
  • JVMCIError – if the field is static or not present and notPresent is null
Returns:the offset in bytes of the requested field
/** * 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 notPresent if non-null and the field is not present then this value is returned * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is * returned in element 0 of this array * @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, T notPresent, String[] outCppType) { return getFieldOffset0(name, type, notPresent, null, outCppType); }
Gets the offset of a non-static C++ field.
Params:
  • name – fully qualified name of the field
  • type – the boxed type to which the offset value will be converted (must be Integer or Long)
  • cppType – if non-null, the expected C++ type of the field (e.g., "HeapWord*")
Throws:
  • JVMCIError – if the field is static or not present
Returns:the offset in bytes of the requested field
/** * 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 getFieldOffset0(name, type, null, cppType, null); }
Gets the offset of a non-static C++ field.
Params:
  • name – fully qualified name of the field
  • type – the boxed type to which the offset value will be converted (must be Integer or Long)
Throws:
  • JVMCIError – if the field is static or not present
Returns:the offset in bytes of the requested field
/** * 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 getFieldOffset0(name, type, null, null, null); } private <T> T getFieldOffset0(String name, Class<T> type, T notPresent, String inCppType, String[] outCppType) { assert type == Integer.class || type == Long.class; VMField entry = getField(name, inCppType, notPresent == null); if (entry == null) { return notPresent; } if (entry.address != 0) { throw new JVMCIError("cannot get offset of static field " + name); } if (outCppType != null) { outCppType[0] = entry.type; } return type.cast(convertValue(name, type, entry.offset, inCppType)); }
Gets the address of a static C++ field.
Params:
  • name – fully qualified name of the field
  • cppType – if non-null, the expected C++ type of the field (e.g., "HeapWord*")
  • notPresent – if non-null and the field is not present then this value is returned
Throws:
  • JVMCIError – if the field is not static or not present and notPresent is null
Returns:the address of the requested field
/** * 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) { return getFieldAddress0(name, notPresent, cppType, null); }
Gets the address of a static C++ field.
Params:
  • name – fully qualified name of the field
  • notPresent – if non-null and the field is not present then this value is returned
  • outCppType – if non-null, the C++ type of the field (e.g., "HeapWord*") is returned in element 0 of this array
Throws:
  • JVMCIError – if the field is not static or not present and notPresent is null
Returns:the address of the requested field
/** * Gets the address of a static C++ field. * * @param name fully qualified name of the field * @param notPresent if non-null and the field is not present then this value is returned * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is * returned in element 0 of this array * @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, Long notPresent, String[] outCppType) { return getFieldAddress0(name, notPresent, null, outCppType); }
Gets the address of a static C++ field.
Params:
  • name – fully qualified name of the field
  • cppType – if non-null, the expected C++ type of the field (e.g., "HeapWord*")
Throws:
  • JVMCIError – if the field is not static or not present
Returns:the address of the requested field
/** * 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 getFieldAddress0(name, null, cppType, null); } private long getFieldAddress0(String name, Long notPresent, String inCppType, String[] outCppType) { VMField entry = getField(name, inCppType, notPresent == null); if (entry == null) { return notPresent; } if (entry.address == 0) { throw new JVMCIError(name + " is not a static field"); } if (outCppType != null) { outCppType[0] = entry.type; } return entry.address; }
Gets the value of a static C++ field.
Params:
  • name – fully qualified name of the field
  • type – the boxed type to which the constant value will be converted
  • cppType – if non-null, the expected C++ type of the field (e.g., "HeapWord*")
  • notPresent – if non-null and the field is not present then this value is returned
Throws:
  • JVMCIError – if the field is not static or not present and notPresent is null
Returns:the value of the requested field
/** * 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) { return getFieldValue0(name, type, notPresent, cppType, null); }
Gets the value of a static C++ field.
Params:
  • name – fully qualified name of the field
  • type – the boxed type to which the constant value will be converted
  • cppType – if non-null, the expected C++ type of the field (e.g., "HeapWord*")
Throws:
  • JVMCIError – if the field is not static or not present
Returns:the value of the requested field
/** * 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 getFieldValue0(name, type, null, cppType, null); }
Gets the value of a static C++ field.
Params:
  • name – fully qualified name of the field
  • type – the boxed type to which the constant value will be converted
  • notPresent – if non-null and the field is not present then this value is returned
  • outCppType – if non-null, the C++ type of the field (e.g., "HeapWord*") is returned in element 0 of this array
Throws:
  • JVMCIError – if the field is not static or not present and notPresent is null
Returns:the value of the requested field
/** * 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 notPresent if non-null and the field is not present then this value is returned * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is * returned in element 0 of this array * @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, T notPresent, String[] outCppType) { return getFieldValue0(name, type, notPresent, null, outCppType); }
Gets the value of a static C++ field.
Params:
  • name – fully qualified name of the field
  • type – the boxed type to which the constant value will be converted
Throws:
  • JVMCIError – if the field is not static or not present
Returns:the value of the requested field
/** * 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 getFieldValue0(name, type, null, null, null); } private <T> T getFieldValue0(String name, Class<T> type, T notPresent, String inCppType, String[] outCppType) { VMField entry = getField(name, inCppType, notPresent == null); if (entry == null) { return notPresent; } if (entry.value == null) { throw new JVMCIError(name + " is not a static field "); } if (outCppType != null) { outCppType[0] = entry.type; } return type.cast(convertValue(name, type, entry.value, inCppType)); }
Gets a C++ field.
Params:
  • name – fully qualified name of the field
  • cppType – if non-null, the expected C++ type of the field (e.g., "HeapWord*")
  • required – specifies if the field must be present
Throws:
  • JVMCIError – if the field is not present and required == true
Returns:the field
/** * 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 missingEntry("field", name, store.vmFields.keySet()); } // 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.
Params:
  • name – name of the flag (e.g., "CompileTheWorldStartAt")
  • type – the boxed type to which the flag's value will be converted
Throws:
Returns:the flag's value converted to type or notPresent if the flag is not present
/** * 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.
Params:
  • name – name of the flag (e.g., "CompileTheWorldStartAt")
  • type – the boxed type to which the flag's value will be converted
  • notPresent – if non-null and the flag is not present then this value is returned
Throws:
  • JVMCIError – if the flag is not present and notPresent == null
Returns:the flag's value converted to type or notPresent if the flag is not present
/** * 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); Object value; String cppType; if (entry == null) { // Fall back to VM call value = store.compilerToVm.getFlagValue(name); if (value == store.compilerToVm) { if (notPresent != null) { return notPresent; } throw missingEntry("flag", name, store.vmFlags.keySet()); } else { cppType = null; } } else { value = entry.value; cppType = entry.type; } return type.cast(convertValue(name, type, value, cppType)); } private JVMCIError missingEntry(String category, String name, Set<String> keys) { throw new JVMCIError("expected VM %s not found in %s: %s%nAvailable values:%n %s", category, store, name, keys.stream().sorted().collect(Collectors.joining(System.lineSeparator() + " "))); } 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 == String.class) { if (value == null || value instanceof String) { return 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; } }