8163105: SIGSEGV: constantPoolHandle::constantPoolHandle(ConstantPool*)
authordnsimon
Mon, 08 Aug 2016 17:06:21 +0200
changeset 40372 ee472073dab0
parent 40371 98d4822ec8ef
child 40373 7602cdc31867
8163105: SIGSEGV: constantPoolHandle::constantPoolHandle(ConstantPool*) Summary: Simplify CompilerToVM.getConstantPool() and related tests. Reviewed-by: kvn, zmajo
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Mon Aug 08 11:30:46 2016 +0300
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Mon Aug 08 17:06:21 2016 +0200
@@ -265,9 +265,10 @@
     native HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool, int cpi) throws LinkageError;
 
     /**
-     * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry for at index {@code cpi} in
-     * {@code constantPool}. For some opcodes, checks are performed that require the {@code method}
-     * that contains {@code opcode} to be specified. The values returned in {@code info} are:
+     * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry for at index
+     * {@code cpi} in {@code constantPool}. For some opcodes, checks are performed that require the
+     * {@code method} that contains {@code opcode} to be specified. The values returned in
+     * {@code info} are:
      *
      * <pre>
      *     [(int) flags,   // only valid if field is resolved
@@ -556,20 +557,18 @@
     native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, long displacement);
 
     /**
-     * Read a HotSpot ConstantPool* value from the memory location described by {@code base} plus
-     * {@code displacement} and return the {@link HotSpotConstantPool} wrapping it. This method does
-     * no checking that the memory location actually contains a valid pointer and may crash the VM
-     * if an invalid location is provided. If the {@code base} is null then {@code displacement} is
-     * used by itself. If {@code base} is a {@link HotSpotResolvedJavaMethodImpl},
-     * {@link HotSpotConstantPool} or {@link HotSpotResolvedObjectTypeImpl} then the metaspace
-     * pointer is fetched from that object and added to {@code displacement}. Any other non-null
-     * object type causes an {@link IllegalArgumentException} to be thrown.
+     * Gets the {@code ConstantPool*} associated with {@code object} and returns a
+     * {@link HotSpotConstantPool} wrapping it.
      *
-     * @param base an object to read from or null
-     * @param displacement
-     * @return null or the resolved method for this location
+     * @param object a {@link HotSpotResolvedJavaMethodImpl} or
+     *            {@link HotSpotResolvedObjectTypeImpl} object
+     * @return a {@link HotSpotConstantPool} wrapping the {@code ConstantPool*} associated with
+     *         {@code object}
+     * @throws NullPointerException if {@code object == null}
+     * @throws IllegalArgumentException if {@code object} is neither a
+     *             {@link HotSpotResolvedJavaMethodImpl} nor a {@link HotSpotResolvedObjectTypeImpl}
      */
-    native HotSpotConstantPool getConstantPool(Object base, long displacement);
+    native HotSpotConstantPool getConstantPool(Object object);
 
     /**
      * Read a HotSpot Klass* value from the memory location described by {@code base} plus
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Mon Aug 08 11:30:46 2016 +0300
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Mon Aug 08 17:06:21 2016 +0200
@@ -121,7 +121,7 @@
         if (metaspaceConstantPool == holder.getConstantPool().getMetaspaceConstantPool()) {
             this.constantPool = holder.getConstantPool();
         } else {
-            this.constantPool = compilerToVM().getConstantPool(null, constMethod + config.constMethodConstantsOffset);
+            this.constantPool = compilerToVM().getConstantPool(this);
         }
 
         final int nameIndex = UNSAFE.getChar(constMethod + config.constMethodNameIndexOffset);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Mon Aug 08 11:30:46 2016 +0300
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Mon Aug 08 17:06:21 2016 +0200
@@ -445,7 +445,7 @@
              * 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);
+            constantPool = compilerToVM().getConstantPool(this);
         }
         return constantPool;
     }
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Mon Aug 08 11:30:46 2016 +0300
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Mon Aug 08 17:06:21 2016 +0200
@@ -461,31 +461,26 @@
   return JNIHandles::make_local(THREAD, result);
 }
 
-C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject base, jlong offset))
+C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject object_handle))
   constantPoolHandle cp;
-  oop base_object = JNIHandles::resolve(base);
-  jlong base_address = 0;
-  if (base_object != NULL) {
-    if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-      base_address = HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object);
-    } else if (base_object->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
-      base_address = HotSpotConstantPool::metaspaceConstantPool(base_object);
-    } else if (base_object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
-      base_address = (jlong) CompilerToVM::asKlass(base_object);
-    } else {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  err_msg("Unexpected type: %s", base_object->klass()->external_name()));
-    }
+  oop object = JNIHandles::resolve(object_handle);
+  if (object == NULL) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
   }
-  cp = *((ConstantPool**) (intptr_t) (base_address + offset));
-  if (!cp.is_null()) {
-    JavaValue method_result(T_OBJECT);
-    JavaCallArguments args;
-    args.push_long((jlong) (address) cp());
-    JavaCalls::call_static(&method_result, SystemDictionary::HotSpotConstantPool_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::constantPool_fromMetaspace_signature(), &args, CHECK_NULL);
-    return JNIHandles::make_local(THREAD, (oop)method_result.get_jobject());
+  if (object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+    cp = CompilerToVM::asMethod(object)->constMethod()->constants();
+  } else if (object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
+    cp = InstanceKlass::cast(CompilerToVM::asKlass(object))->constants();
+  } else {
+    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Unexpected type: %s", object->klass()->external_name()));
   }
-  return NULL;
+  assert(!cp.is_null(), "npe");
+  JavaValue method_result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_long((jlong) (address) cp());
+  JavaCalls::call_static(&method_result, SystemDictionary::HotSpotConstantPool_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::constantPool_fromMetaspace_signature(), &args, CHECK_NULL);
+  return JNIHandles::make_local(THREAD, (oop)method_result.get_jobject());
 }
 
 C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlong offset, jboolean compressed))
@@ -1522,7 +1517,7 @@
   {CC "getMaxCallTargetOffset",                       CC "(J)J",                                                                            FN_PTR(getMaxCallTargetOffset)},
   {CC "getResolvedJavaMethodAtSlot",                  CC "(" CLASS "I)" HS_RESOLVED_METHOD,                                                 FN_PTR(getResolvedJavaMethodAtSlot)},
   {CC "getResolvedJavaMethod",                        CC "(Ljava/lang/Object;J)" HS_RESOLVED_METHOD,                                        FN_PTR(getResolvedJavaMethod)},
-  {CC "getConstantPool",                              CC "(Ljava/lang/Object;J)" HS_CONSTANT_POOL,                                          FN_PTR(getConstantPool)},
+  {CC "getConstantPool",                              CC "(Ljava/lang/Object;)" HS_CONSTANT_POOL,                                           FN_PTR(getConstantPool)},
   {CC "getResolvedJavaType",                          CC "(Ljava/lang/Object;JZ)" HS_RESOLVED_KLASS,                                        FN_PTR(getResolvedJavaType)},
   {CC "readConfiguration",                            CC "()[" OBJECT,                                                                      FN_PTR(readConfiguration)},
   {CC "installCode",                                  CC "(" TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE HS_SPECULATION_LOG ")I",    FN_PTR(installCode)},
--- a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Mon Aug 08 11:30:46 2016 +0300
+++ b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Mon Aug 08 17:06:21 2016 +0200
@@ -273,8 +273,8 @@
         return CTVM.getResolvedJavaMethod(base, displacement);
     }
 
-    public static HotSpotConstantPool getConstantPool(Object base, long displacement) {
-        return CTVM.getConstantPool(base, displacement);
+    public static HotSpotConstantPool getConstantPool(Object object) {
+        return CTVM.getConstantPool(object);
     }
 
     public static HotSpotResolvedObjectType getResolvedJavaType(Object base,
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Mon Aug 08 11:30:46 2016 +0300
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Mon Aug 08 17:06:21 2016 +0200
@@ -29,187 +29,76 @@
  * @library /testlibrary /test/lib /
  * @library ../common/patches
  * @modules java.base/jdk.internal.misc
- * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @modules java.base/jdk.internal.org.objectweb.asm
+            java.base/jdk.internal.org.objectweb.asm.tree
+            jdk.vm.ci/jdk.vm.ci.hotspot
  *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.code
  *
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
- * @build jdk.vm.ci/jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
  * @build compiler.jvmci.compilerToVM.GetConstantPoolTest
- * @build sun.hotspot.WhiteBox
- * @run driver ClassFileInstaller sun.hotspot.WhiteBox
- *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   compiler.jvmci.compilerToVM.GetConstantPoolTest
  */
 package compiler.jvmci.compilerToVM;
 
-import jdk.internal.misc.Unsafe;
 import jdk.test.lib.Utils;
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.TestCase;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.vm.ci.meta.ConstantPool;
-import sun.hotspot.WhiteBox;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
 
 /**
  * Tests for jdk.vm.ci.hotspot.CompilerToVM::getConstantPool method
  */
 public class GetConstantPoolTest {
-    private static enum TestCase {
-        NULL_BASE {
-            @Override
-            ConstantPool getConstantPool() {
-                return CompilerToVMHelper.getConstantPool(null,
-                        getPtrToCpAddress());
-            }
-        },
-        JAVA_METHOD_BASE {
-            @Override
-            ConstantPool getConstantPool() {
-                HotSpotResolvedJavaMethod methodInstance
-                        = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
-                                TEST_CLASS, 0);
-                Field field;
-                try {
-                    // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod
-                    field = methodInstance.getClass()
-                            .getDeclaredField("metaspaceMethod");
-                    field.setAccessible(true);
-                    field.set(methodInstance, getPtrToCpAddress());
-                } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e, e);
-                }
 
-                return CompilerToVMHelper.getConstantPool(methodInstance, 0L);
-            }
-        },
-        CONSTANT_POOL_BASE {
-            @Override
-            ConstantPool getConstantPool() {
-                ConstantPool cpInst;
-                try {
-                    cpInst = CompilerToVMHelper.getConstantPool(null,
-                            getPtrToCpAddress());
-                    Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
-                            .getDeclaredField("metaspaceConstantPool");
-                    field.setAccessible(true);
-                    field.set(cpInst, getPtrToCpAddress());
-                } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
-                }
-                return CompilerToVMHelper.getConstantPool(cpInst, 0L);
-            }
-        },
-        CONSTANT_POOL_BASE_IN_TWO {
-            @Override
-            ConstantPool getConstantPool() {
-                long ptr = getPtrToCpAddress();
-                ConstantPool cpInst;
-                try {
-                    cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
-                    Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
-                            .getDeclaredField("metaspaceConstantPool");
-                    field.setAccessible(true);
-                    field.set(cpInst, ptr / 2L);
-                } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
-                }
-                return CompilerToVMHelper.getConstantPool(cpInst,
-                        ptr - ptr / 2L);
-            }
-        },
-        CONSTANT_POOL_BASE_ZERO {
-            @Override
-            ConstantPool getConstantPool() {
-                long ptr = getPtrToCpAddress();
-                ConstantPool cpInst;
-                try {
-                    cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
-                    Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
-                            .getDeclaredField("metaspaceConstantPool");
-                    field.setAccessible(true);
-                    field.set(cpInst, 0L);
-                } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
-                }
-                return CompilerToVMHelper.getConstantPool(cpInst, ptr);
-            }
-        },
-        ;
-        abstract ConstantPool getConstantPool();
+    public static void testMethod(Executable executable) {
+        test(CTVMUtilities.getResolvedMethod(executable));
     }
 
-    private static final WhiteBox WB = WhiteBox.getWhiteBox();
-    private static final Unsafe UNSAFE = Utils.getUnsafe();
-
-    private static final Class TEST_CLASS = GetConstantPoolTest.class;
-    private static final long CP_ADDRESS
-            = WB.getConstantPool(GetConstantPoolTest.class);
+    public static void testClass(Class cls) {
+        HotSpotResolvedObjectType type = CompilerToVMHelper
+                .lookupType(Utils.toJVMTypeSignature(cls),
+                        GetConstantPoolTest.class, /* resolve = */ true);
+        test(type);
+    }
 
-    public void test(TestCase testCase) {
-        System.out.println(testCase.name());
-        ConstantPool cp = testCase.getConstantPool();
-        String cpStringRep = cp.toString();
-        String cpClassSimpleName
-                = CompilerToVMHelper.HotSpotConstantPoolClass().getSimpleName();
-        if (!cpStringRep.contains(cpClassSimpleName)
-                || !cpStringRep.contains(TEST_CLASS.getName())) {
-            String msg = String.format("%s : "
-                    + " Constant pool is not valid."
-                    + " String representation should contain \"%s\" and \"%s\"",
-                    testCase.name(), cpClassSimpleName,
-                    TEST_CLASS.getName());
-            throw new AssertionError(msg);
-        }
+    private static void test(Object object) {
+        ConstantPool cp = CompilerToVMHelper.getConstantPool(object);
+        System.out.println(object + " -> " + cp);
     }
 
     public static void main(String[] args) {
-        GetConstantPoolTest test = new GetConstantPoolTest();
-        for (TestCase testCase : TestCase.values()) {
-            test.test(testCase);
-        }
-        testObjectBase();
-        testMetaspaceWrapperBase();
+        TestCase.getAllClasses().forEach(GetConstantPoolTest::testClass);
+        TestCase.getAllExecutables().forEach(GetConstantPoolTest::testMethod);
+        testNull();
+        testObject();
     }
 
-    private static void testObjectBase() {
+    private static void testNull() {
         try {
-            Object cp = CompilerToVMHelper.getConstantPool(new Object(), 0L);
-            throw new AssertionError("Test OBJECT_BASE."
+            Object cp = CompilerToVMHelper.getConstantPool(null);
+            throw new AssertionError("Test OBJECT."
+                + " Expected IllegalArgumentException has not been caught");
+        } catch (NullPointerException npe) {
+            // expected
+        }
+    }
+    private static void testObject() {
+        try {
+            Object cp = CompilerToVMHelper.getConstantPool(new Object());
+            throw new AssertionError("Test OBJECT."
                 + " Expected IllegalArgumentException has not been caught");
         } catch (IllegalArgumentException iae) {
             // expected
         }
     }
-    private static void testMetaspaceWrapperBase() {
-        try {
-            Object cp = CompilerToVMHelper.getConstantPool(
-                    new PublicMetaspaceWrapperObject() {
-                        @Override
-                        public long getMetaspacePointer() {
-                            return getPtrToCpAddress();
-                        }
-                    }, 0L);
-            throw new AssertionError("Test METASPACE_WRAPPER_BASE."
-                + " Expected IllegalArgumentException has not been caught");
-        } catch (IllegalArgumentException iae) {
-            // expected
-        }
-    }
-
-    private static long getPtrToCpAddress() {
-        Field field;
-        try {
-            field = TEST_CLASS.getDeclaredField("CP_ADDRESS");
-        } catch (NoSuchFieldException nsfe) {
-            throw new Error("TESTBUG : cannot find field \"CP_ADDRESS\" : "
-                    + nsfe.getMessage(), nsfe);
-        }
-        Object base = UNSAFE.staticFieldBase(field);
-        return WB.getObjectAddress(base) + UNSAFE.staticFieldOffset(field);
-    }
 }