changeset 23677:eb166b568645

Merge
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Thu, 09 Jun 2016 18:58:09 -0700
parents a6a7657877fe (current diff) 28dbeb87ec75 (diff)
children e86a0b0ba969
files jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java src/share/vm/jvmci/jvmciCodeInstaller.cpp src/share/vm/jvmci/jvmciRuntime.cpp src/share/vm/jvmci/jvmciRuntime.hpp src/share/vm/prims/jvmtiEnv.cpp
diffstat 12 files changed, 94 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java	Thu Jun 09 18:57:51 2016 -0700
+++ b/jvmci/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java	Thu Jun 09 18:58:09 2016 -0700
@@ -81,8 +81,6 @@
 
     private final Register[] allocatable;
 
-    private final int maxFrameSize;
-
     /**
      * The caller saved registers always include all parameter registers.
      */
@@ -92,10 +90,6 @@
 
     private final RegisterAttributes[] attributesMap;
 
-    public int getMaximumFrameSize() {
-        return maxFrameSize;
-    }
-
     @Override
     public Register[] getAllocatableRegisters() {
         return allocatable.clone();
@@ -161,13 +155,12 @@
     }
 
     public AArch64HotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
-        this(target, config, initAllocatable(target.arch, config.useCompressedOops));
+        this(target, initAllocatable(target.arch, config.useCompressedOops));
         assert callerSaved.length >= allocatable.length;
     }
 
-    public AArch64HotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config, Register[] allocatable) {
+    public AArch64HotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
         this.target = target;
-        this.maxFrameSize = config.maxFrameSize;
 
         this.allocatable = allocatable.clone();
         Set<Register> callerSaveSet = new HashSet<>();
--- a/jvmci/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Thu Jun 09 18:57:51 2016 -0700
+++ b/jvmci/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Thu Jun 09 18:58:09 2016 -0700
@@ -73,8 +73,6 @@
 
     private final Register[] allocatable;
 
-    private final int maxFrameSize;
-
     /**
      * The caller saved registers always include all parameter registers.
      */
@@ -84,10 +82,6 @@
 
     private final RegisterAttributes[] attributesMap;
 
-    public int getMaximumFrameSize() {
-        return maxFrameSize;
-    }
-
     @Override
     public Register[] getAllocatableRegisters() {
         return allocatable.clone();
@@ -153,7 +147,6 @@
 
     public AMD64HotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config, Register[] allocatable) {
         this.target = target;
-        this.maxFrameSize = config.maxFrameSize;
 
         if (config.windowsOs) {
             javaGeneralParameterRegisters = new Register[]{rdx, r8, r9, rdi, rsi, rcx};
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Thu Jun 09 18:57:51 2016 -0700
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Thu Jun 09 18:58:09 2016 -0700
@@ -196,7 +196,9 @@
      */
     @SuppressWarnings("unused")
     private static HotSpotConstantPool fromMetaspace(long metaspaceConstantPool) {
-        return new HotSpotConstantPool(metaspaceConstantPool);
+        HotSpotConstantPool cp = new HotSpotConstantPool(metaspaceConstantPool);
+        runtime().metaAccessContext.add(cp);
+        return cp;
     }
 
     private HotSpotConstantPool(long metaspaceConstantPool) {
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Thu Jun 09 18:57:51 2016 -0700
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Thu Jun 09 18:58:09 2016 -0700
@@ -135,6 +135,7 @@
              */
             metadataRoots = list.getHead();
         }
+        assert isRegistered(metaspaceObject);
     }
 
     protected ResolvedJavaType createClass(Class<?> javaClass) {
@@ -208,7 +209,7 @@
             ChunkIterator() {
                 currentChunk = head;
                 currentIndex = -1;
-                findNext();
+                next = findNext();
             }
 
             Object[] currentChunk;
@@ -245,4 +246,13 @@
         }
 
     }
+
+    synchronized boolean isRegistered(MetaspaceWrapperObject wrapper) {
+        for (WeakReference<MetaspaceWrapperObject> m : list) {
+            if (m != null && m.get() == wrapper) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu Jun 09 18:57:51 2016 -0700
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu Jun 09 18:58:09 2016 -0700
@@ -132,10 +132,20 @@
         return UNSAFE.getInt(javaClass, (long) config().klassOffset) & 0xFFFFFFFFL;
     }
 
+    @Override
     public long getMetaspacePointer() {
         return getMetaspaceKlass();
     }
 
+    /**
+     * The Klass* for this object is kept alive by the direct reference to {@link #javaClass} so no
+     * extra work is required.
+     */
+    @Override
+    public boolean isRegistered() {
+        return true;
+    }
+
     @Override
     public int getModifiers() {
         if (isArray()) {
@@ -429,7 +439,13 @@
     }
 
     public HotSpotConstantPool getConstantPool() {
-        if (constantPool == null) {
+        if (constantPool == null || !isArray() && UNSAFE.getAddress(getMetaspaceKlass() + config().instanceKlassConstantsOffset) != constantPool.getMetaspaceConstantPool()) {
+            /*
+             * If the pointer to the ConstantPool has changed since this was last read refresh the
+             * HotSpotConstantPool wrapper object. This ensures that uses of the constant pool are
+             * operating on the latest one and that HotSpotResolvedJavaMethodImpls will be able to
+             * use the shared copy instead of creating their own instance.
+             */
             constantPool = compilerToVM().getConstantPool(this, config().instanceKlassConstantsOffset);
         }
         return constantPool;
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Thu Jun 09 18:57:51 2016 -0700
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Thu Jun 09 18:58:09 2016 -0700
@@ -71,11 +71,6 @@
         return runtime().getConfig();
     }
 
-    /**
-     * Maximum allowed size of allocated area for a frame.
-     */
-    public final int maxFrameSize = 16 * 1024;
-
     @Override
     public String toString() {
         return getClass().getSimpleName();
@@ -1293,6 +1288,12 @@
     @HotSpotVMConstant(name = "JVMCIRuntime::by_holder") @Stable public int compLevelAdjustmentByHolder;
     @HotSpotVMConstant(name = "JVMCIRuntime::by_full_signature") @Stable public int compLevelAdjustmentByFullSignature;
 
+    /**
+     * This is the largest stack offset encodeable in an OopMapValue. Offsets larger than this will
+     * throw an exception during code installation.
+     */
+    @HotSpotVMValue(expression = "JVMCIRuntime::max_oop_map_stack_offset") @Stable public int maxOopMapStackOffset;
+
     @HotSpotVMType(name = "BasicLock", get = HotSpotVMType.Type.SIZE) @Stable public int basicLockSize;
     @HotSpotVMField(name = "BasicLock::_displaced_header", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int basicLockDisplacedHeaderOffset;
 
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java	Thu Jun 09 18:57:51 2016 -0700
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java	Thu Jun 09 18:58:09 2016 -0700
@@ -23,7 +23,8 @@
 package jdk.vm.ci.hotspot;
 
 /**
- * A tag interface indicating that this type is a wrapper around a HotSpot metaspace object.
+ * A tag interface indicating that this type is a wrapper around a HotSpot metaspace object that
+ * requires GC interaction to keep alive.
  *
  * It would preferable if this were the base class containing the pointer but that would require
  * mixins since most of the wrapper types have complex supertype hierarchies.
@@ -31,4 +32,18 @@
 interface MetaspaceWrapperObject {
 
     long getMetaspacePointer();
+
+    /**
+     * Check if this object is properly registered for metadata tracking. All classes which
+     * implement this interface must be registered with the
+     * {@link HotSpotJVMCIMetaAccessContext#add} unless they are kept alive through other means.
+     * Currently the only type which doesn't require explicit registration is
+     * {@link HotSpotResolvedObjectTypeImpl} since it's kept alive by references to the
+     * {@link Class}.
+     *
+     * @return true if this object is properly registered for meta data tracking.
+     */
+    default boolean isRegistered() {
+        return HotSpotJVMCIRuntime.runtime().metaAccessContext.isRegistered(this);
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Thu Jun 09 18:57:51 2016 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Thu Jun 09 18:58:09 2016 -0700
@@ -62,7 +62,6 @@
             </file>
         </folder>
         <folder name="Window">
-            <file name="Tools_hidden"/>
             <file name="Web_hidden"/>
             <file name="org-netbeans-modules-tasks-ui-DashboardTopComponent.shadow_hidden"/>
         </folder>
--- a/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Thu Jun 09 18:57:51 2016 -0700
+++ b/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Thu Jun 09 18:58:09 2016 -0700
@@ -89,7 +89,19 @@
   } else {
     // stack slot
     if (offset % 4 == 0) {
-      return VMRegImpl::stack2reg(offset / 4);
+      VMReg vmReg = VMRegImpl::stack2reg(offset / 4);
+      if (!OopMapValue::legal_vm_reg_name(vmReg)) {
+        // This restriction only applies to VMRegs that are used in OopMap but
+        // since that's the only use of VMRegs it's simplest to put this test
+        // here.  This test should also be equivalent legal_vm_reg_name but JVMCI
+        // clients can use max_oop_map_stack_stack_offset to detect this problem
+        // directly.  The asserts just ensure that the tests are in agreement.
+        assert(offset > JVMCIRuntime::max_oop_map_stack_offset, "illegal VMReg");
+        JVMCI_ERROR_NULL("stack offset %d is too large to be encoded in OopMap (max %d)",
+                         offset, JVMCIRuntime::max_oop_map_stack_offset);
+      }
+      assert(OopMapValue::legal_vm_reg_name(vmReg), "illegal VMReg");
+      return vmReg;
     } else {
       JVMCI_ERROR_NULL("unaligned stack offset %d in oop map", offset);
     }
--- a/src/share/vm/jvmci/jvmciRuntime.cpp	Thu Jun 09 18:57:51 2016 -0700
+++ b/src/share/vm/jvmci/jvmciRuntime.cpp	Thu Jun 09 18:58:09 2016 -0700
@@ -51,6 +51,7 @@
 char** JVMCIRuntime::_trivial_prefixes = NULL;
 JVMCIRuntime::CompLevelAdjustment JVMCIRuntime::_comp_level_adjustment = JVMCIRuntime::none;
 bool JVMCIRuntime::_shutdown_called = false;
+int JVMCIRuntime::max_oop_map_stack_offset = (OopMapValue::register_mask - VMRegImpl::stack2reg(0)->value()) * VMRegImpl::stack_slot_size;
 
 BasicType JVMCIRuntime::kindToBasicType(Handle kind, TRAPS) {
   if (kind.is_null()) {
@@ -656,6 +657,10 @@
            "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization");
 #endif
 
+    int max_oop_map_stack_index = max_oop_map_stack_offset / VMRegImpl::stack_slot_size;
+    assert(OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index)), "should be valid");
+    assert(!OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index + 1)), "should be invalid");
+
     Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime",
                                "runtime",
                                "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK);
--- a/src/share/vm/jvmci/jvmciRuntime.hpp	Thu Jun 09 18:57:51 2016 -0700
+++ b/src/share/vm/jvmci/jvmciRuntime.hpp	Thu Jun 09 18:58:09 2016 -0700
@@ -51,6 +51,8 @@
      by_full_signature = 2 // adjust based on declaring class, name and signature of method
   };
 
+  static int max_oop_map_stack_offset;
+
  private:
   static jobject _HotSpotJVMCIRuntime_instance;
   static bool _HotSpotJVMCIRuntime_initialized;
--- a/src/share/vm/prims/jvmtiEnv.cpp	Thu Jun 09 18:57:51 2016 -0700
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Thu Jun 09 18:58:09 2016 -0700
@@ -226,6 +226,7 @@
                             NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count);
   NULL_CHECK(class_definitions, JVMTI_ERROR_OUT_OF_MEMORY);
 
+  int redef_index = 0;
   for (index = 0; index < class_count; index++) {
     HandleMark hm(current_thread);
 
@@ -253,6 +254,11 @@
       return JVMTI_ERROR_UNMODIFIABLE_CLASS;
     }
 
+    if (klass->oop_is_instance() && InstanceKlass::cast(klass())->is_anonymous()) {
+      // return JVMTI_ERROR_UNMODIFIABLE_CLASS;
+      continue;
+    }
+
     instanceKlassHandle ikh(current_thread, k_oop);
     if (ikh->get_cached_class_file_bytes() == NULL) {
       // Not cached, we need to reconstitute the class file from the
@@ -267,19 +273,24 @@
         return reconstituter.get_error();
       }
 
-      class_definitions[index].class_byte_count = (jint)reconstituter.class_file_size();
-      class_definitions[index].class_bytes      = (unsigned char*)
+      class_definitions[redef_index].class_byte_count = (jint)reconstituter.class_file_size();
+      class_definitions[redef_index].class_bytes      = (unsigned char*)
                                                        reconstituter.class_file_bytes();
     } else {
       // it is cached, get it from the cache
-      class_definitions[index].class_byte_count = ikh->get_cached_class_file_len();
-      class_definitions[index].class_bytes      = ikh->get_cached_class_file_bytes();
+      class_definitions[redef_index].class_byte_count = ikh->get_cached_class_file_len();
+      class_definitions[redef_index].class_bytes      = ikh->get_cached_class_file_bytes();
     }
-    class_definitions[index].klass              = jcls;
+    class_definitions[redef_index].klass              = jcls;
+    redef_index++;
   }
-  VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
-  VMThread::execute(&op);
-  return (op.check_error());
+  if (redef_index > 0) {
+    VM_RedefineClasses op(redef_index, class_definitions, jvmti_class_load_kind_retransform);
+    VMThread::execute(&op);
+    return (op.check_error());
+  } else {
+    return JVMTI_ERROR_NONE;
+  }
 } /* end RetransformClasses */