changeset 23994:ebce30b702eb

[GR-2538] reduced memory overhead of HotSpotVMConfigStore
author Doug Simon <doug.simon@oracle.com>
date Thu, 02 Feb 2017 23:58:25 +0100
parents 7b65bd0ebeb7
children 988dc143e0bf
files jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java src/share/vm/jvmci/jvmciCompilerToVM.cpp src/share/vm/jvmci/jvmciCompilerToVM.hpp src/share/vm/jvmci/vmStructs_jvmci.hpp
diffstat 8 files changed, 256 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Tue Jan 31 22:59:16 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Thu Feb 02 23:58:25 2017 +0100
@@ -631,4 +631,12 @@
      * @return the number of bytes required for deoptimization of this frame state
      */
     native int interpreterFrameSize(BytecodeFrame frame);
+
+    /**
+     * Gets the value of the VM flag named {@code name} boxed in an Object.
+     *
+     * @param name name of a VM option
+     * @return {@code null} if the named VM option doesn't exist
+     */
+    native Object getFlagValue(String name);
 }
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Tue Jan 31 22:59:16 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Thu Feb 02 23:58:25 2017 +0100
@@ -512,10 +512,6 @@
         for (Map.Entry<String, Long> e : constants.entrySet()) {
             printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
         }
-        TreeMap<String, Long> typeSizes = new TreeMap<>(store.getTypeSizes());
-        for (Map.Entry<String, Long> e : typeSizes.entrySet()) {
-            printConfigLine(vm, "[vmconfig:type size] %s = %d%n", e.getKey(), e.getValue());
-        }
         for (VMIntrinsicMethod e : store.getIntrinsics()) {
             printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
         }
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Tue Jan 31 22:59:16 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Thu Feb 02 23:58:25 2017 +0100
@@ -77,7 +77,7 @@
 
     final int arrayKlassComponentMirrorOffset = getFieldOffset("ArrayKlass::_component_mirror", Integer.class, "oop");
 
-    final int vtableEntrySize = getTypeSize("vtableEntry");
+    final int vtableEntrySize = getFieldValue("CompilerToVM::Data::sizeof_vtableEntry", Integer.class, "int");
     final int vtableEntryMethodOffset = getFieldOffset("vtableEntry::_method", Integer.class, "Method*");
 
     final int arrayU1LengthOffset = getFieldOffset("Array<int>::_length", Integer.class, "int");
@@ -149,20 +149,20 @@
     final int constMethodHasLocalVariableTable = getConstant("ConstMethod::_has_localvariable_table", Integer.class);
     final int constMethodHasExceptionTable = getConstant("ConstMethod::_has_exception_table", Integer.class);
 
-    final int exceptionTableElementSize = getTypeSize("ExceptionTableElement");
+    final int exceptionTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_ExceptionTableElement", Integer.class, "int");
     final int exceptionTableElementStartPcOffset = getFieldOffset("ExceptionTableElement::start_pc", Integer.class, "u2");
     final int exceptionTableElementEndPcOffset = getFieldOffset("ExceptionTableElement::end_pc", Integer.class, "u2");
     final int exceptionTableElementHandlerPcOffset = getFieldOffset("ExceptionTableElement::handler_pc", Integer.class, "u2");
     final int exceptionTableElementCatchTypeIndexOffset = getFieldOffset("ExceptionTableElement::catch_type_index", Integer.class, "u2");
 
-    final int localVariableTableElementSize = getTypeSize("LocalVariableTableElement");
+    final int localVariableTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_LocalVariableTableElement", Integer.class, "int");
     final int localVariableTableElementStartBciOffset = getFieldOffset("LocalVariableTableElement::start_bci", Integer.class, "u2");
     final int localVariableTableElementLengthOffset = getFieldOffset("LocalVariableTableElement::length", Integer.class, "u2");
     final int localVariableTableElementNameCpIndexOffset = getFieldOffset("LocalVariableTableElement::name_cp_index", Integer.class, "u2");
     final int localVariableTableElementDescriptorCpIndexOffset = getFieldOffset("LocalVariableTableElement::descriptor_cp_index", Integer.class, "u2");
     final int localVariableTableElementSlotOffset = getFieldOffset("LocalVariableTableElement::slot", Integer.class, "u2");
 
-    final int constantPoolSize = getTypeSize("ConstantPool");
+    final int constantPoolSize = getFieldValue("CompilerToVM::Data::sizeof_ConstantPool", Integer.class, "int");
     final int constantPoolTagsOffset = getFieldOffset("ConstantPool::_tags", Integer.class, "Array<u1>*");
     final int constantPoolHolderOffset = getFieldOffset("ConstantPool::_pool_holder", Integer.class, "InstanceKlass*");
     final int constantPoolLengthOffset = getFieldOffset("ConstantPool::_length", Integer.class, "int");
@@ -194,7 +194,7 @@
 
     final int heapWordSize = getConstant("HeapWordSize", Integer.class);
 
-    final int symbolPointerSize = getTypeSize("Symbol*");
+    final int symbolPointerSize = getFieldValue("CompilerToVM::Data::sizeof_SymbolPointer", Integer.class, "int");
 
     final long vmSymbolsSymbols = getFieldAddress("vmSymbols::_symbols[0]", "Symbol*");
     final int vmSymbolsFirstSID = getConstant("vmSymbols::FIRST_SID", Integer.class);
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Tue Jan 31 22:59:16 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Thu Feb 02 23:58:25 2017 +0100
@@ -67,21 +67,6 @@
     }
 
     /**
-     * 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"})
@@ -291,13 +276,24 @@
      */
     public <T> T getFlag(String name, Class<T> type, T notPresent) {
         VMFlag entry = store.vmFlags.get(name);
+        Object value;
+        String cppType;
         if (entry == null) {
-            if (notPresent != null) {
-                return notPresent;
+            // Fall back to VM call
+            value = store.compilerToVm.getFlagValue(name);
+            if (value == null) {
+                if (notPresent != null) {
+                    return notPresent;
+                }
+                throw new JVMCIError("expected VM flag not found: " + name);
+            } else {
+                cppType = null;
             }
-            throw new JVMCIError("expected VM flag not found: " + name);
+        } else {
+            value = entry.value;
+            cppType = entry.type;
         }
-        return type.cast(convertValue(name, type, entry.value, entry.type));
+        return type.cast(convertValue(name, type, value, cppType));
     }
 
     private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError {
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java	Tue Jan 31 22:59:16 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java	Thu Feb 02 23:58:25 2017 +0100
@@ -47,15 +47,6 @@
     }
 
     /**
-     * Gets the C++ type sizes exposed by this object.
-     *
-     * @return an unmodifiable map from C++ type names to their sizes in bytes
-     */
-    public Map<String, Long> getTypeSizes() {
-        return Collections.unmodifiableMap(vmTypeSizes);
-    }
-
-    /**
      * Gets the C++ constants exposed by this object.
      *
      * @return an unmodifiable map from the names of C++ constants to their values
@@ -90,11 +81,11 @@
     }
 
     final HashMap<String, VMField> vmFields;
-    final HashMap<String, Long> vmTypeSizes;
     final HashMap<String, Long> vmConstants;
     final HashMap<String, Long> vmAddresses;
     final HashMap<String, VMFlag> vmFlags;
     final List<VMIntrinsicMethod> vmIntrinsics;
+    final CompilerToVM compilerToVm;
 
     /**
      * Reads the database of VM info. The return value encodes the info in a nested object array
@@ -103,7 +94,6 @@
      * <pre>
      *     info = [
      *         VMField[] vmFields,
-     *         [String name, Long size, ...] vmTypeSizes,
      *         [String name, Long value, ...] vmConstants,
      *         [String name, Long value, ...] vmAddresses,
      *         VMFlag[] vmFlags
@@ -113,25 +103,24 @@
      */
     @SuppressWarnings("try")
     HotSpotVMConfigStore(CompilerToVM compilerToVm) {
+        this.compilerToVm = compilerToVm;
         Object[] data;
         try (InitTimer t = timer("CompilerToVm readConfiguration")) {
             data = compilerToVm.readConfiguration();
         }
-        assert data.length == 6 : data.length;
+        assert data.length == 5 : data.length;
 
         // @formatter:off
         VMField[] vmFieldsInfo    = (VMField[]) data[0];
-        Object[] vmTypesSizesInfo = (Object[])  data[1];
-        Object[] vmConstantsInfo  = (Object[])  data[2];
-        Object[] vmAddressesInfo  = (Object[])  data[3];
-        VMFlag[] vmFlagsInfo      = (VMFlag[])  data[4];
+        Object[] vmConstantsInfo  = (Object[])  data[1];
+        Object[] vmAddressesInfo  = (Object[])  data[2];
+        VMFlag[] vmFlagsInfo      = (VMFlag[])  data[3];
 
         vmFields     = new HashMap<>(vmFieldsInfo.length);
-        vmTypeSizes  = new HashMap<>(vmTypesSizesInfo.length);
         vmConstants  = new HashMap<>(vmConstantsInfo.length);
         vmAddresses  = new HashMap<>(vmAddressesInfo.length);
         vmFlags      = new HashMap<>(vmFlagsInfo.length);
-        vmIntrinsics = Arrays.asList((VMIntrinsicMethod[]) data[5]);
+        vmIntrinsics = Arrays.asList((VMIntrinsicMethod[]) data[4]);
         // @formatter:on
 
         try (InitTimer t = timer("HotSpotVMConfigStore<init> fill maps")) {
@@ -139,12 +128,6 @@
                 vmFields.put(vmField.name, vmField);
             }
 
-            for (int i = 0; i < vmTypesSizesInfo.length / 2; i++) {
-                String name = (String) vmTypesSizesInfo[i * 2];
-                Long size = (Long) vmTypesSizesInfo[i * 2 + 1];
-                vmTypeSizes.put(name, size);
-            }
-
             for (int i = 0; i < vmConstantsInfo.length / 2; i++) {
                 String name = (String) vmConstantsInfo[i * 2];
                 Long value = (Long) vmConstantsInfo[i * 2 + 1];
--- a/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Tue Jan 31 22:59:16 2017 +0100
+++ b/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Thu Feb 02 23:58:25 2017 +0100
@@ -48,6 +48,7 @@
 #include "runtime/vframe.hpp"
 #include "runtime/vframe_hp.hpp"
 #include "runtime/vmStructs.hpp"
+#include "utilities/resourceHash.hpp"
 
 
 // Entry to native method implementation that transitions current thread to '_thread_in_vm'.
@@ -117,6 +118,15 @@
 
 int CompilerToVM::Data::vm_page_size;
 
+int CompilerToVM::Data::sizeof_vtableEntry = sizeof(vtableEntry);
+int CompilerToVM::Data::sizeof_ExceptionTableElement = sizeof(ExceptionTableElement);
+int CompilerToVM::Data::sizeof_LocalVariableTableElement = sizeof(LocalVariableTableElement);
+int CompilerToVM::Data::sizeof_ConstantPool = sizeof(ConstantPool);
+int CompilerToVM::Data::sizeof_SymbolPointer = sizeof(Symbol*);
+int CompilerToVM::Data::sizeof_narrowKlass = sizeof(narrowKlass);
+int CompilerToVM::Data::sizeof_arrayOopDesc = sizeof(arrayOopDesc);
+int CompilerToVM::Data::sizeof_BasicLock = sizeof(BasicLock);
+
 address CompilerToVM::Data::CodeCache_low_bound;
 address CompilerToVM::Data::CodeCache_high_bound;
 
@@ -238,13 +248,109 @@
   return vmIntrinsics;
 }
 
+/**
+ * The set of VM flags known to be used.
+ */
+#define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_intx_flag, do_uintx_flag) \
+  do_intx_flag(AllocateInstancePrefetchLines)                              \
+  do_intx_flag(AllocatePrefetchDistance)                                   \
+  do_intx_flag(AllocatePrefetchInstr)                                      \
+  do_intx_flag(AllocatePrefetchLines)                                      \
+  do_intx_flag(AllocatePrefetchStepSize)                                   \
+  do_intx_flag(AllocatePrefetchStyle)                                      \
+  do_intx_flag(BciProfileWidth)                                            \
+  do_bool_flag(BootstrapJVMCI)                                             \
+  do_bool_flag(CITime)                                                     \
+  do_bool_flag(CITimeEach)                                                 \
+  do_uintx_flag(CodeCacheSegmentSize)                                      \
+  do_intx_flag(CodeEntryAlignment)                                         \
+  do_bool_flag(CompactFields)                                              \
+  NOT_PRODUCT(do_intx_flag(CompileTheWorldStartAt))                        \
+  NOT_PRODUCT(do_intx_flag(CompileTheWorldStopAt))                         \
+  do_intx_flag(ContendedPaddingWidth)                                      \
+  do_bool_flag(DontCompileHugeMethods)                                     \
+  do_bool_flag(EnableContended)                                            \
+  do_intx_flag(FieldsAllocationStyle)                                      \
+  do_bool_flag(FoldStableValues)                                           \
+  do_bool_flag(ForceUnreachable)                                           \
+  do_intx_flag(HugeMethodLimit)                                            \
+  do_bool_flag(Inline)                                                     \
+  do_intx_flag(JVMCICounterSize)                                           \
+  do_bool_flag(JVMCIPrintProperties)                                       \
+  do_bool_flag(JVMCIUseFastLocking)                                        \
+  do_intx_flag(MethodProfileWidth)                                         \
+  do_intx_flag(ObjectAlignmentInBytes)                                     \
+  do_bool_flag(PrintInlining)                                              \
+  do_bool_flag(ReduceInitialCardMarks)                                     \
+  do_bool_flag(RestrictContended)                                          \
+  /*do_intx_flag(StackReservedPages) - JDK 9*/                             \
+  do_intx_flag(StackShadowPages)                                           \
+  do_bool_flag(TLABStats)                                                  \
+  do_uintx_flag(TLABWasteIncrement)                                        \
+  do_intx_flag(TypeProfileWidth)                                           \
+  do_bool_flag(UseAESIntrinsics)                                           \
+  do_intx_flag(UseAVX)                                                     \
+  do_bool_flag(UseBiasedLocking)                                           \
+  do_bool_flag(UseCRC32Intrinsics)                                         \
+  do_bool_flag(UseCompressedClassPointers)                                 \
+  do_bool_flag(UseCompressedOops)                                          \
+  do_bool_flag(UseConcMarkSweepGC)                                         \
+  do_bool_flag(UseCountLeadingZerosInstruction)                            \
+  do_bool_flag(UseCountTrailingZerosInstruction)                           \
+  do_bool_flag(UseG1GC)                                                    \
+  COMPILER2_PRESENT(do_bool_flag(UseMontgomeryMultiplyIntrinsic))          \
+  COMPILER2_PRESENT(do_bool_flag(UseMontgomerySquareIntrinsic))            \
+  COMPILER2_PRESENT(do_bool_flag(UseMulAddIntrinsic))                      \
+  COMPILER2_PRESENT(do_bool_flag(UseMultiplyToLenIntrinsic))               \
+  do_bool_flag(UsePopCountInstruction)                                     \
+  do_bool_flag(UseSHA1Intrinsics)                                          \
+  do_bool_flag(UseSHA256Intrinsics)                                        \
+  do_bool_flag(UseSHA512Intrinsics)                                        \
+  do_intx_flag(UseSSE)                                                     \
+  COMPILER2_PRESENT(do_bool_flag(UseSquareToLenIntrinsic))                 \
+  do_bool_flag(UseStackBanging)                                            \
+  do_bool_flag(UseTLAB)                                                    \
+  do_bool_flag(VerifyOops)                                                 \
+
+#define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0)
+#define BOXED_LONG(name, value) \
+  oop name; \
+  do { \
+    jvalue p; p.j = (jlong) (value); \
+    Handle* e = longs.get(p.j); \
+    if (e == NULL) { \
+      Handle h = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); \
+      longs.put(p.j, h); \
+      name = h(); \
+    } else { \
+      name = (*e)(); \
+    } \
+  } while (0)
+
+#define STRING(name, value) \
+  Handle name; \
+  do { \
+    if (value != NULL) { \
+      Handle* e = strings.get(value); \
+      if (e == NULL) { \
+        Handle h = java_lang_String::create_from_str(value, CHECK_NULL); \
+        strings.put(value, h); \
+        name = h(); \
+      } else { \
+        name = (*e)(); \
+      } \
+    } \
+  } while (0)
+
 C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
-#define BOXED_INT(name, value) oop name; do { jvalue p; p.j = (jint) (value); name = java_lang_boxing_object::create(T_INT, &p, CHECK_NULL);} while(0)
-#define BOXED_LONG(name, value) oop name; do { jvalue p; p.j = (jlong) (value); name = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL);} while(0)
-#define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0)
+
   ResourceMark rm;
   HandleMark hm;
 
+  // Used to canonicalize Long and String values.
+  ResourceHashtable<jlong, Handle> longs;
+  ResourceHashtable<const char*, Handle, &CompilerToVM::cstring_hash, &CompilerToVM::cstring_equals> strings;
+
   CompilerToVM::Data::initialize(CHECK_NULL);
 
   VMField::klass()->initialize(CHECK_NULL);
@@ -259,8 +365,8 @@
     size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */;
     char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1);
     sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName);
-    Handle name = java_lang_String::create_from_str(name_buf, CHECK_NULL);
-    Handle type = java_lang_String::create_from_str(vmField.typeString, CHECK_NULL);
+    STRING(name, name_buf);
+    STRING(type, vmField.typeString);
     VMField::set_name(vmFieldObj, name());
     VMField::set_type(vmFieldObj, type());
     VMField::set_offset(vmFieldObj, vmField.offset);
@@ -289,16 +395,6 @@
     vmFields->obj_at_put(i, vmFieldObj());
   }
 
-  len = VMStructs::localHotSpotVMTypes_count();
-  objArrayHandle vmTypes = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
-  for (int i = 0; i < len ; i++) {
-    VMTypeEntry vmType = VMStructs::localHotSpotVMTypes[i];
-    Handle name = java_lang_String::create_from_str(vmType.typeName, CHECK_NULL);
-    BOXED_LONG(size, vmType.size);
-    vmTypes->obj_at_put(i * 2, name());
-    vmTypes->obj_at_put(i * 2 + 1, size);
-  }
-
   int ints_len = VMStructs::localHotSpotVMIntConstants_count();
   int longs_len = VMStructs::localHotSpotVMLongConstants_count();
   len = ints_len + longs_len;
@@ -306,14 +402,14 @@
   int insert = 0;
   for (int i = 0; i < ints_len ; i++) {
     VMIntConstantEntry c = VMStructs::localHotSpotVMIntConstants[i];
-    Handle name = java_lang_String::create_from_str(c.name, CHECK_NULL);
+    STRING(name, c.name);
     BOXED_LONG(value, c.value);
     vmConstants->obj_at_put(insert++, name());
     vmConstants->obj_at_put(insert++, value);
   }
   for (int i = 0; i < longs_len ; i++) {
     VMLongConstantEntry c = VMStructs::localHotSpotVMLongConstants[i];
-    Handle name = java_lang_String::create_from_str(c.name, CHECK_NULL);
+    STRING(name, c.name);
     BOXED_LONG(value, c.value);
     vmConstants->obj_at_put(insert++, name());
     vmConstants->obj_at_put(insert++, value);
@@ -324,60 +420,94 @@
   objArrayHandle vmAddresses = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
   for (int i = 0; i < len ; i++) {
     VMAddressEntry a = VMStructs::localHotSpotVMAddresses[i];
-    Handle name = java_lang_String::create_from_str(a.name, CHECK_NULL);
+    STRING(name, a.name);
     BOXED_LONG(value, a.value);
     vmAddresses->obj_at_put(i * 2, name());
     vmAddresses->obj_at_put(i * 2 + 1, value);
   }
 
-  // The last entry is the null entry.
-  len = (int) Flag::numFlags - 1;
+#define COUNT_FLAG(ignore) +1
+#ifdef ASSERT
+#define CHECK_FLAG(type, name) { \
+	Flag* flag = Flag::find_flag(#name, strlen(#name), /*allow_locked*/ true, /* return_flag */ true); \
+	assert(flag != NULL, "No such flag named " #name); \
+  assert(flag->is_##type(), "Flag " #name " is not of type " #type); \
+}
+#else
+#define CHECK_FLAG(type, name)
+#endif
+
+#define ADD_FLAG(type, name, convert) { \
+  CHECK_FLAG(type, name) \
+	instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL); \
+  STRING(fname, #name); \
+  STRING(ftype, #type); \
+  VMFlag::set_name(vmFlagObj, fname()); \
+  VMFlag::set_type(vmFlagObj, ftype()); \
+  convert(value, name); \
+  VMFlag::set_value(vmFlagObj, value); \
+  vmFlags->obj_at_put(i++, vmFlagObj()); \
+}
+#define ADD_BOOL_FLAG(name)  ADD_FLAG(bool, name, BOXED_LONG)
+#define ADD_INTX_FLAG(name)  ADD_FLAG(intx, name, BOXED_LONG)
+#define ADD_UINTX_FLAG(name) ADD_FLAG(uintx, name, BOXED_LONG)
+
+  len = 0 + PREDEFINED_CONFIG_FLAGS(COUNT_FLAG, COUNT_FLAG, COUNT_FLAG);
   objArrayHandle vmFlags = oopFactory::new_objArray(VMFlag::klass(), len, CHECK_NULL);
-  for (int i = 0; i < len; i++) {
-    Flag* flag = &Flag::flags[i];
-    instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL);
-    Handle name = java_lang_String::create_from_str(flag->_name, CHECK_NULL);
-    Handle type = java_lang_String::create_from_str(flag->_type, CHECK_NULL);
-    VMFlag::set_name(vmFlagObj, name());
-    VMFlag::set_type(vmFlagObj, type());
-    if (flag->is_bool()) {
-      BOXED_LONG(value, flag->get_bool());
-      VMFlag::set_value(vmFlagObj, value);
-    } else if (flag->is_ccstr()) {
-      Handle value = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_NULL);
-      VMFlag::set_value(vmFlagObj, value());
-    } else if (flag->is_intx()) {
-      BOXED_LONG(value, flag->get_intx());
-      VMFlag::set_value(vmFlagObj, value);
-    } else if (flag->is_uint64_t()) {
-      BOXED_LONG(value, flag->get_uint64_t());
-      VMFlag::set_value(vmFlagObj, value);
-    } else if (flag->is_uintx()) {
-      BOXED_LONG(value, flag->get_uintx());
-      VMFlag::set_value(vmFlagObj, value);
-    } else if (flag->is_double()) {
-      BOXED_DOUBLE(value, flag->get_double());
-      VMFlag::set_value(vmFlagObj, value);
-    } else {
-      JVMCI_ERROR_NULL("VM flag %s has unsupported type %s", flag->_name, flag->_type);
-    }
-    vmFlags->obj_at_put(i, vmFlagObj());
-  }
+	int i = 0;
+  PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG)
 
   objArrayHandle vmIntrinsics = CompilerToVM::initialize_intrinsics(CHECK_NULL);
 
-  objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 6, CHECK_NULL);
+  objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 5, CHECK_NULL);
   data->obj_at_put(0, vmFields());
-  data->obj_at_put(1, vmTypes());
-  data->obj_at_put(2, vmConstants());
-  data->obj_at_put(3, vmAddresses());
-  data->obj_at_put(4, vmFlags());
-  data->obj_at_put(5, vmIntrinsics());
+  data->obj_at_put(1, vmConstants());
+  data->obj_at_put(2, vmAddresses());
+  data->obj_at_put(3, vmFlags());
+  data->obj_at_put(4, vmIntrinsics());
 
   return (jobjectArray) JNIHandles::make_local(THREAD, data);
+#undef COUNT_FLAG
+#undef ADD_FLAG
+#undef ADD_BOOL_FLAG
+#undef ADD_INTX_FLAG
+#undef ADD_UINTX_FLAG
+#undef CHECK_FLAG
+C2V_END
+
+C2V_VMENTRY(jobject, getFlagValue, (JNIEnv *, jobject, jobject name_handle))
+#define RETURN_BOXED_LONG(value) oop box; jvalue p; p.j = (jlong) (value); box = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
+#define RETURN_BOXED_DOUBLE(value) oop box; jvalue p; p.d = (jdouble) (value); box = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
+  Handle name = JNIHandles::resolve(name_handle);
+  if (name.is_null()) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+  const char* cstring = java_lang_String::as_utf8_string(name());
+  Flag* flag = Flag::find_flag(cstring, strlen(cstring), /* allow_locked */ true, /* return_flag */ true);
+  if (flag == NULL) {
+    return NULL;
+  }
+  if (flag->is_bool()) {
+    RETURN_BOXED_LONG(flag->get_bool());
+  } else if (flag->is_ccstr()) {
+    Handle value = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_NULL);
+    return JNIHandles::make_local(THREAD, value());
+  } else if (flag->is_intx()) {
+    RETURN_BOXED_LONG(flag->get_intx());
+  } else if (flag->is_uint64_t()) {
+    RETURN_BOXED_LONG(flag->get_uint64_t());
+  } else if (flag->is_uintx()) {
+    RETURN_BOXED_LONG(flag->get_uintx());
+  } else if (flag->is_double()) {
+    RETURN_BOXED_DOUBLE(flag->get_double());
+  } else {
+    JVMCI_ERROR_NULL("VM flag %s has unsupported type %s", flag->_name, flag->_type);
+  }
+C2V_END
+
 #undef BOXED_LONG
 #undef BOXED_DOUBLE
-C2V_END
+#undef STRING
 
 C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jobject jvmci_method))
   methodHandle method = CompilerToVM::asMethod(jvmci_method);
@@ -1588,7 +1718,8 @@
   {CC"flushDebugOutput",                             CC"()V",                                                                          FN_PTR(flushDebugOutput)},
   {CC"methodDataProfileDataSize",                    CC"(JI)I",                                                                        FN_PTR(methodDataProfileDataSize)},
   {CC"interpreterFrameSize",                         CC"("BYTECODE_FRAME")I",                                                          FN_PTR(interpreterFrameSize)},
-  {CC"compileToBytecode",                            CC"(" OBJECT ")V",                                                                FN_PTR(compileToBytecode)},
+  {CC"compileToBytecode",                            CC"("OBJECT")V",                                                                  FN_PTR(compileToBytecode)},
+  {CC"getFlagValue",                                 CC"("STRING")"OBJECT,                                                             FN_PTR(getFlagValue)},
 };
 
 int CompilerToVM::methods_count() {
--- a/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Tue Jan 31 22:59:16 2017 +0100
+++ b/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Thu Feb 02 23:58:25 2017 +0100
@@ -68,6 +68,15 @@
 
      static int vm_page_size;
 
+     static int sizeof_vtableEntry;
+     static int sizeof_ExceptionTableElement;
+     static int sizeof_LocalVariableTableElement;
+     static int sizeof_ConstantPool;
+     static int sizeof_SymbolPointer;
+     static int sizeof_narrowKlass;
+     static int sizeof_arrayOopDesc;
+     static int sizeof_BasicLock;
+
      static address CodeCache_low_bound;
      static address CodeCache_high_bound;
 
@@ -88,6 +97,20 @@
     }
    };
 
+  static bool cstring_equals(const char* const& s0, const char* const& s1) {
+    return strcmp(s0, s1) == 0;
+  }
+
+  static unsigned cstring_hash(const char* const& s) {
+    int h = 0;
+    const char* p = s;
+    while (*p != '\0') {
+      h = 31 * h + *p;
+      p++;
+    }
+    return h;
+  }
+
   static JNINativeMethod methods[];
 
   static objArrayHandle initialize_intrinsics(TRAPS);
--- a/src/share/vm/jvmci/vmStructs_jvmci.hpp	Tue Jan 31 22:59:16 2017 +0100
+++ b/src/share/vm/jvmci/vmStructs_jvmci.hpp	Thu Feb 02 23:58:25 2017 +0100
@@ -66,6 +66,15 @@
                                                                                                                                      \
   static_field(CompilerToVM::Data,             vm_page_size,                           int)                                          \
                                                                                                                                      \
+  static_field(CompilerToVM::Data,             sizeof_vtableEntry,                     int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_ExceptionTableElement,           int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_LocalVariableTableElement,       int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_ConstantPool,                    int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_SymbolPointer,                   int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_narrowKlass,                     int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_arrayOopDesc,                    int)                                          \
+  static_field(CompilerToVM::Data,             sizeof_BasicLock,                       int)                                          \
+                                                                                                                                     \
   static_field(CompilerToVM::Data,             CodeCache_low_bound,                    address)                                      \
   static_field(CompilerToVM::Data,             CodeCache_high_bound,                   address)                                      \
                                                                                                                                      \