changeset 23996:11f0412408cd

8173912: [JVMCI] fix memory overhead of JVMCI
author Doug Simon <doug.simon@oracle.com>
date Fri, 03 Feb 2017 21:08:05 +0100
parents 988dc143e0bf
children 9a740aa0d87b
files jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java src/share/vm/jvmci/jvmciCompilerToVM.cpp
diffstat 6 files changed, 89 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Feb 03 08:17:35 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Feb 03 21:08:05 2017 +0100
@@ -339,6 +339,7 @@
      *         [String name, Long value, ...] vmConstants,
      *         [String name, Long value, ...] vmAddresses,
      *         VMFlag[] vmFlags
+     *         VMIntrinsicMethod[] vmIntrinsics
      *     ]
      * </pre>
      *
@@ -496,18 +497,6 @@
     native String getSymbol(long metaspaceSymbol);
 
     /**
-     * Gets the name of the field at index {@code index} in the fields array of {@code type}.
-     *
-     * @throws ArrayIndexOutOfBoundsException if {@code index} is out of bounds of the fields array
-     */
-    native String getFieldName(HotSpotResolvedObjectTypeImpl holder, int index);
-
-    /**
-     * Gets the name of {@code method}.
-     */
-    native String getMethodName(HotSpotResolvedJavaMethodImpl method);
-
-    /**
      * Looks for the next Java stack frame matching an entry in {@code methods}.
      *
      * @param frame the starting point of the search, where {@code null} refers to the topmost frame
@@ -617,12 +606,6 @@
     native int methodDataProfileDataSize(long metaspaceMethodData, int position);
 
     /**
-     * Invokes non-public method {@code java.lang.invoke.LambdaForm.compileToBytecode()} on
-     * {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance).
-     */
-    native void compileToBytecode(Object lambdaForm);
-
-    /**
      * Return the amount of native stack required for the interpreter frames represented by
      * {@code frame}. This is used when emitting the stack banging code to ensure that there is
      * enough space for the frames during deoptimization.
@@ -633,10 +616,19 @@
     native int interpreterFrameSize(BytecodeFrame frame);
 
     /**
-     * Gets the value of the VM flag named {@code name} boxed in an Object.
+     * Invokes non-public method {@code java.lang.invoke.LambdaForm.compileToBytecode()} on
+     * {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance).
+     */
+    native void compileToBytecode(Object lambdaForm);
+
+    /**
+     * Gets the value of the VM flag named {@code name}.
      *
      * @param name name of a VM option
-     * @return {@code null} if the named VM option doesn't exist
+     * @return {@code this} if the named VM option doesn't exist, a {@link String} or {@code null}
+     *         if its type is {@code ccstr} or {@code ccstrlist}, a {@link Double} if its type is
+     *         {@code double}, a {@link Boolean} if its type is {@code bool} otherwise a
+     *         {@link Long}
      */
     native Object getFlagValue(String name);
 }
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Fri Feb 03 08:17:35 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Fri Feb 03 21:08:05 2017 +0100
@@ -22,7 +22,6 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
 import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers;
 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 
@@ -51,11 +50,11 @@
         this.holder = holder;
         this.type = type;
         this.index = (short) index;
+        this.offset = (int) offset;
+        this.modifiers = modifiers;
         assert this.index == index;
         assert offset != -1;
         assert offset == (int) offset : "offset larger than int";
-        this.offset = (int) offset;
-        this.modifiers = modifiers;
     }
 
     @Override
@@ -109,7 +108,7 @@
 
     @Override
     public String getName() {
-        return compilerToVM().getFieldName(holder, index);
+        return holder.createFieldInfo(index).getName();
     }
 
     @Override
@@ -178,18 +177,12 @@
         return null;
     }
 
-    private Field toJavaCache;
-
     private Field toJava() {
-        if (toJavaCache != null) {
-            return toJavaCache;
-        }
-
         if (isInternal()) {
             return null;
         }
         try {
-            return toJavaCache = holder.mirror().getDeclaredField(getName());
+            return holder.mirror().getDeclaredField(getName());
         } catch (NoSuchFieldException | NoClassDefFoundError e) {
             return null;
         }
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri Feb 03 08:17:35 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri Feb 03 21:08:05 2017 +0100
@@ -74,6 +74,11 @@
     private HotSpotMethodData methodData;
     private byte[] code;
     private Executable toJavaCache;
+
+    /**
+     * Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it
+     * lazily and cache it.
+     */
     private String nameCache;
 
     /**
@@ -144,7 +149,8 @@
 
     public String getName() {
         if (nameCache == null) {
-            nameCache = compilerToVM().getMethodName(this);
+            final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset);
+            nameCache = constantPool.lookupUtf8(nameIndex);
         }
         return nameCache;
     }
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri Feb 03 08:17:35 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri Feb 03 21:08:05 2017 +0100
@@ -563,11 +563,15 @@
         return null;
     }
 
+    FieldInfo createFieldInfo(int index) {
+        return new FieldInfo(index);
+    }
+
     /**
      * This class represents the field information for one field contained in the fields array of an
      * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
      */
-    private class FieldInfo {
+    class FieldInfo {
         /**
          * Native pointer into the array of Java shorts.
          */
@@ -591,6 +595,10 @@
             return readFieldSlot(config().fieldInfoAccessFlagsOffset);
         }
 
+        private int getNameIndex() {
+            return readFieldSlot(config().fieldInfoNameIndexOffset);
+        }
+
         private int getSignatureIndex() {
             return readFieldSlot(config().fieldInfoSignatureIndexOffset);
         }
@@ -613,6 +621,15 @@
         }
 
         /**
+         * Returns the name of this field as a {@link String}. If the field is an internal field the
+         * name index is pointing into the vmSymbols table.
+         */
+        public String getName() {
+            final int nameIndex = getNameIndex();
+            return isInternal() ? config().symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
+        }
+
+        /**
          * Returns the signature of this field as {@link String}. If the field is an internal field
          * the signature index is pointing into the vmSymbols table.
          */
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Fri Feb 03 08:17:35 2017 +0100
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Fri Feb 03 21:08:05 2017 +0100
@@ -281,7 +281,7 @@
         if (entry == null) {
             // Fall back to VM call
             value = store.compilerToVm.getFlagValue(name);
-            if (value == null) {
+            if (value == store.compilerToVm) {
                 if (notPresent != null) {
                     return notPresent;
                 }
@@ -315,6 +315,10 @@
             } 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;
         }
--- a/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Feb 03 08:17:35 2017 +0100
+++ b/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Feb 03 21:08:05 2017 +0100
@@ -283,20 +283,20 @@
   do_bool_flag(PrintInlining)                                              \
   do_bool_flag(ReduceInitialCardMarks)                                     \
   do_bool_flag(RestrictContended)                                          \
-  /*do_intx_flag(StackReservedPages) - JDK 9*/                             \
+  /* 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)                                                     \
+  X86_ONLY(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)                           \
+  X86_ONLY(do_bool_flag(UseCountLeadingZerosInstruction))                  \
+  X86_ONLY(do_bool_flag(UseCountTrailingZerosInstruction))                 \
   do_bool_flag(UseG1GC)                                                    \
   COMPILER2_PRESENT(do_bool_flag(UseMontgomeryMultiplyIntrinsic))          \
   COMPILER2_PRESENT(do_bool_flag(UseMontgomerySquareIntrinsic))            \
@@ -312,6 +312,7 @@
   do_bool_flag(UseTLAB)                                                    \
   do_bool_flag(VerifyOops)                                                 \
 
+#define BOXED_BOOLEAN(name, value) oop name = ((jboolean)(value) ? boxedTrue() : boxedFalse())
 #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; \
@@ -343,7 +344,6 @@
   } while (0)
 
 C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
-
   ResourceMark rm;
   HandleMark hm;
 
@@ -351,6 +351,10 @@
   ResourceHashtable<jlong, Handle> longs;
   ResourceHashtable<const char*, Handle, &CompilerToVM::cstring_hash, &CompilerToVM::cstring_equals> strings;
 
+  jvalue prim;
+  prim.z = true;  Handle boxedTrue =  java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
+  prim.z = false; Handle boxedFalse = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
+
   CompilerToVM::Data::initialize(CHECK_NULL);
 
   VMField::klass()->initialize(CHECK_NULL);
@@ -373,23 +377,23 @@
     VMField::set_address(vmFieldObj, (jlong) vmField.address);
     if (vmField.isStatic && vmField.typeString != NULL) {
       if (strcmp(vmField.typeString, "bool") == 0) {
-        BOXED_LONG(value, *(jbyte*) vmField.address);
-        VMField::set_value(vmFieldObj, value);
+        BOXED_BOOLEAN(box, *(jbyte*) vmField.address);
+        VMField::set_value(vmFieldObj, box);
       } else if (strcmp(vmField.typeString, "int") == 0 ||
                  strcmp(vmField.typeString, "jint") == 0) {
-        BOXED_LONG(value, *(jint*) vmField.address);
-        VMField::set_value(vmFieldObj, value);
+        BOXED_LONG(box, *(jint*) vmField.address);
+        VMField::set_value(vmFieldObj, box);
       } else if (strcmp(vmField.typeString, "uint64_t") == 0) {
-        BOXED_LONG(value, *(uint64_t*) vmField.address);
-        VMField::set_value(vmFieldObj, value);
+        BOXED_LONG(box, *(uint64_t*) vmField.address);
+        VMField::set_value(vmFieldObj, box);
       } else if (strcmp(vmField.typeString, "address") == 0 ||
                  strcmp(vmField.typeString, "intptr_t") == 0 ||
                  strcmp(vmField.typeString, "uintptr_t") == 0 ||
                  strcmp(vmField.typeString, "size_t") == 0 ||
                  // All foo* types are addresses.
                  vmField.typeString[strlen(vmField.typeString) - 1] == '*') {
-        BOXED_LONG(value, *((address*) vmField.address));
-        VMField::set_value(vmFieldObj, value);
+        BOXED_LONG(box, *((address*) vmField.address));
+        VMField::set_value(vmFieldObj, box);
       }
     }
     vmFields->obj_at_put(i, vmFieldObj());
@@ -429,8 +433,8 @@
 #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); \
+  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
@@ -439,7 +443,7 @@
 
 #define ADD_FLAG(type, name, convert) { \
   CHECK_FLAG(type, name) \
-	instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL); \
+  instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL); \
   STRING(fname, #name); \
   STRING(ftype, #type); \
   VMFlag::set_name(vmFlagObj, fname()); \
@@ -448,13 +452,13 @@
   VMFlag::set_value(vmFlagObj, value); \
   vmFlags->obj_at_put(i++, vmFlagObj()); \
 }
-#define ADD_BOOL_FLAG(name)  ADD_FLAG(bool, name, BOXED_LONG)
+#define ADD_BOOL_FLAG(name)  ADD_FLAG(bool, name, BOXED_BOOLEAN)
 #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);
-	int i = 0;
+  int i = 0;
   PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG)
 
   objArrayHandle vmIntrinsics = CompilerToVM::initialize_intrinsics(CHECK_NULL);
@@ -475,7 +479,7 @@
 #undef CHECK_FLAG
 C2V_END
 
-C2V_VMENTRY(jobject, getFlagValue, (JNIEnv *, jobject, jobject name_handle))
+C2V_VMENTRY(jobject, getFlagValue, (JNIEnv *, jobject c2vm, 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);
@@ -485,17 +489,26 @@
   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;
+    return c2vm;
   }
   if (flag->is_bool()) {
-    RETURN_BOXED_LONG(flag->get_bool());
+    jvalue prim;
+    prim.z = flag->get_bool();
+    oop box = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
+    return JNIHandles::make_local(THREAD, box);
   } 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_int()) {
+    RETURN_BOXED_LONG(flag->get_int());
+  } else if (flag->is_uint()) {
+    RETURN_BOXED_LONG(flag->get_uint());*/
   } else if (flag->is_uint64_t()) {
     RETURN_BOXED_LONG(flag->get_uint64_t());
+/*} else if (flag->is_size_t()) {
+    RETURN_BOXED_LONG(flag->get_size_t());*/
   } else if (flag->is_uintx()) {
     RETURN_BOXED_LONG(flag->get_uintx());
   } else if (flag->is_double()) {
@@ -881,14 +894,16 @@
   ResourceMark rm;
   constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
   Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
-  fieldDescriptor result;
-  LinkResolver::resolve_field_access(result, cp, index, Bytecodes::java_code(code), true, false, CHECK_0);
+  fieldDescriptor fd;
+  LinkResolver::resolve_field_access(fd, cp, index, Bytecodes::java_code(code), true, false, CHECK_0);
   typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
-  assert(info != NULL && info->length() == 2, "must be");
-  info->int_at_put(0, result.access_flags().as_int());
-  info->int_at_put(1, result.offset());
-  info->int_at_put(2, result.index());
-  oop field_holder = CompilerToVM::get_jvmci_type(result.field_holder(), CHECK_NULL);
+  if (info == NULL || info->length() != 3) {
+    JVMCI_ERROR_NULL("info must not be null and have a length of 3");
+  }
+  info->int_at_put(0, fd.access_flags().as_int());
+  info->int_at_put(1, fd.offset());
+  info->int_at_put(2, fd.index());
+  oop field_holder = CompilerToVM::get_jvmci_type(fd.field_holder(), CHECK_NULL);
   return JNIHandles::make_local(THREAD, field_holder);
 C2V_END
 
@@ -1243,21 +1258,6 @@
   return JNIHandles::make_local(THREAD, sym());
 C2V_END
 
-C2V_VMENTRY(jobject, getFieldName, (JNIEnv*, jobject, jobject jvmci_type, jint index))
-  InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type);
-  if (index < 0 || index >= klass->fields()->length()) {
-    THROW_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
-  }
-  Handle name = java_lang_String::create_from_symbol(klass->field_name(index), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, name());
-C2V_END
-
-C2V_VMENTRY(jobject, getMethodName, (JNIEnv*, jobject, jobject jvmci_method))
-  Method* method = CompilerToVM::asMethod(jvmci_method);
-  Handle name = java_lang_String::create_from_symbol(method->name(), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, name());
-C2V_END
-
 bool matches(jobjectArray methods, Method* method) {
   objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods);
 
@@ -1709,8 +1709,6 @@
   {CC"isMature",                                     CC"("METASPACE_METHOD_DATA")Z",                                                   FN_PTR(isMature)},
   {CC"hasCompiledCodeForOSR",                        CC"("HS_RESOLVED_METHOD"II)Z",                                                    FN_PTR(hasCompiledCodeForOSR)},
   {CC"getSymbol",                                    CC"(J)"STRING,                                                                    FN_PTR(getSymbol)},
-  {CC"getFieldName",                                 CC"("HS_RESOLVED_KLASS"I)"STRING,                                                 FN_PTR(getFieldName)},
-  {CC"getMethodName",                                CC"("HS_RESOLVED_METHOD")"STRING,                                                 FN_PTR(getMethodName)},
   {CC"getNextStackFrame",                            CC"("HS_STACK_FRAME_REF "["RESOLVED_METHOD"I)"HS_STACK_FRAME_REF,                 FN_PTR(getNextStackFrame)},
   {CC"materializeVirtualObjects",                    CC"("HS_STACK_FRAME_REF"Z)V",                                                     FN_PTR(materializeVirtualObjects)},
   {CC"shouldDebugNonSafepoints",                     CC"()Z",                                                                          FN_PTR(shouldDebugNonSafepoints)},