8193930: [JVMCI] calling ResolvedTypeType.getClassInitializer on an array type crashes
authordnsimon
Fri, 22 Dec 2017 18:34:36 +0100
changeset 48480 614068b0ddd7
parent 48479 7b5c930b878c
child 48481 b97818fba2b0
8193930: [JVMCI] calling ResolvedTypeType.getClassInitializer on an array type crashes Reviewed-by: never, dlong
src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetImplementorTest.java
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Wed Nov 29 13:58:28 2017 +0100
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri Dec 22 18:34:36 2017 +0100
@@ -749,8 +749,13 @@
 C2V_END
 
 C2V_VMENTRY(jobject, getImplementor, (JNIEnv *, jobject, jobject jvmci_type))
-  InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type);
-  oop implementor = CompilerToVM::get_jvmci_type(klass->implementor(), CHECK_NULL);
+  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+  if (!klass->is_interface()) {
+    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+        err_msg("Expected interface type, got %s", klass->external_name()));
+  }
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  oop implementor = CompilerToVM::get_jvmci_type(iklass->implementor(), CHECK_NULL);
   return JNIHandles::make_local(THREAD, implementor);
 C2V_END
 
@@ -989,8 +994,12 @@
 C2V_END
 
 C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv *, jobject, jobject jvmci_type))
-  InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type);
-  oop result = CompilerToVM::get_jvmci_method(klass->class_initializer(), CHECK_NULL);
+  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+  if (!klass->is_instance_klass()) {
+    return NULL;
+  }
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  oop result = CompilerToVM::get_jvmci_method(iklass->class_initializer(), CHECK_NULL);
   return JNIHandles::make_local(THREAD, result);
 C2V_END
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Wed Nov 29 13:58:28 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Dec 22 18:34:36 2017 +0100
@@ -135,8 +135,9 @@
     /**
      * Gets the implementor for the interface class {@code type}.
      *
-     * @return the implementor if there is a single implementor, 0 if there is no implementor, or
-     *         {@code type} itself if there is more than one implementor
+     * @return the implementor if there is a single implementor, {@code null} if there is no
+     *         implementor, or {@code type} itself if there is more than one implementor
+     * @throws IllegalArgumentException if type is not an interface type
      */
     native HotSpotResolvedObjectTypeImpl getImplementor(HotSpotResolvedObjectTypeImpl type);
 
@@ -256,14 +257,13 @@
     native void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
 
     /**
-     * If {@code cpi} denotes an entry representing a resolved dynamic adapter
-     * (see {@code resolveInvokeDynamicInPool} and {@code resolveInvokeHandleInPool}),
-     * return the opcode of the instruction for which the resolution was performed
-     * ({@code invokedynamic} or {@code invokevirtual}}, or {@code -1} otherwise.
+     * If {@code cpi} denotes an entry representing a resolved dynamic adapter (see
+     * {@code resolveInvokeDynamicInPool} and {@code resolveInvokeHandleInPool}), return the opcode
+     * of the instruction for which the resolution was performed ({@code invokedynamic} or
+     * {@code invokevirtual}}, or {@code -1} otherwise.
      */
     native int isResolvedInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
 
-
     /**
      * Gets the list of type names (in the format of {@link JavaType#getName()}) denoting the
      * classes that define signature polymorphic methods.
@@ -388,7 +388,7 @@
     /**
      * Gets the static initializer of {@code type}.
      *
-     * @return 0 if {@code type} has no static initializer
+     * @return {@code null} if {@code type} has no static initializer
      */
     native HotSpotResolvedJavaMethodImpl getClassInitializer(HotSpotResolvedObjectTypeImpl type);
 
@@ -468,7 +468,8 @@
     native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method);
 
     /**
-     * Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM.
+     * Sets flags on {@code method} indicating that it should never be inlined or compiled by the
+     * VM.
      */
     native void setNotInlinableOrCompilable(HotSpotResolvedJavaMethodImpl method);
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Wed Nov 29 13:58:28 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri Dec 22 18:34:36 2017 +0100
@@ -922,7 +922,10 @@
     }
 
     public ResolvedJavaMethod getClassInitializer() {
-        return compilerToVM().getClassInitializer(this);
+        if (!isArray()) {
+            return compilerToVM().getClassInitializer(this);
+        }
+        return null;
     }
 
     @Override
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetImplementorTest.java	Wed Nov 29 13:58:28 2017 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetImplementorTest.java	Fri Dec 22 18:34:36 2017 +0100
@@ -103,6 +103,14 @@
         HotSpotResolvedObjectType resolvedIface = CompilerToVMHelper
                 .lookupTypeHelper(Utils.toJVMTypeSignature(tcase.anInterface),
                         getClass(), /* resolve = */ true);
+        if (!resolvedIface.isInterface()) {
+            try {
+                CompilerToVMHelper.getImplementor(resolvedIface);
+                Asserts.fail("Expected " + IllegalArgumentException.class.getName());
+            } catch (IllegalArgumentException e) {
+            }
+            return;
+        }
         HotSpotResolvedObjectType resolvedImplementer = CompilerToVMHelper
                 .getImplementor(resolvedIface);
         HotSpotResolvedObjectType resolvedExpected = null;
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Wed Nov 29 13:58:28 2017 +0100
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Fri Dec 22 18:34:36 2017 +0100
@@ -473,6 +473,20 @@
         metaAccess.lookupJavaType(ConcreteTransitiveImplementor1.class);
         metaAccess.lookupJavaType(ConcreteTransitiveImplementor2.class);
         assertEquals(aSai2, iSai2.getSingleImplementor());
+
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            try {
+                type.getSingleImplementor();
+                if (!c.isInterface()) {
+                    throw new AssertionError("Expected exception for calling getSingleImplmentor on " + c.getName());
+                }
+            } catch (JVMCIError e) {
+                if (c.isInterface()) {
+                    throw new AssertionError("Unexpected exception", e);
+                }
+            }
+        }
     }
 
     @Test(expected = JVMCIError.class)
@@ -830,6 +844,10 @@
         assertNull(metaAccess.lookupJavaType(C.class).getClassInitializer());
         assertNull(metaAccess.lookupJavaType(int.class).getClassInitializer());
         assertNull(metaAccess.lookupJavaType(void.class).getClassInitializer());
+        for (Class<?> c : classes) {
+            ResolvedJavaType type = metaAccess.lookupJavaType(c);
+            type.getClassInitializer();
+        }
     }
 
     @Test