8193930: [JVMCI] calling ResolvedTypeType.getClassInitializer on an array type crashes

Reviewed-by: never, dlong
This commit is contained in:
Doug Simon 2017-12-22 18:34:36 +01:00
parent 3b3ebcd097
commit 77eb30dae3
5 changed files with 53 additions and 14 deletions

View file

@ -749,8 +749,13 @@ C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv *, jobject, jobject jvmci
C2V_END C2V_END
C2V_VMENTRY(jobject, getImplementor, (JNIEnv *, jobject, jobject jvmci_type)) C2V_VMENTRY(jobject, getImplementor, (JNIEnv *, jobject, jobject jvmci_type))
InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type); Klass* klass = CompilerToVM::asKlass(jvmci_type);
oop implementor = CompilerToVM::get_jvmci_type(klass->implementor(), CHECK_NULL); 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); return JNIHandles::make_local(THREAD, implementor);
C2V_END C2V_END
@ -989,8 +994,12 @@ C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject jvmci_t
C2V_END C2V_END
C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv *, jobject, jobject jvmci_type)) C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv *, jobject, jobject jvmci_type))
InstanceKlass* klass = (InstanceKlass*) CompilerToVM::asKlass(jvmci_type); Klass* klass = CompilerToVM::asKlass(jvmci_type);
oop result = CompilerToVM::get_jvmci_method(klass->class_initializer(), CHECK_NULL); 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); return JNIHandles::make_local(THREAD, result);
C2V_END C2V_END

View file

@ -135,8 +135,9 @@ final class CompilerToVM {
/** /**
* Gets the implementor for the interface class {@code type}. * 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 * @return the implementor if there is a single implementor, {@code null} if there is no
* {@code type} itself if there is more than one implementor * 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); native HotSpotResolvedObjectTypeImpl getImplementor(HotSpotResolvedObjectTypeImpl type);
@ -256,14 +257,13 @@ final class CompilerToVM {
native void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi); native void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
/** /**
* If {@code cpi} denotes an entry representing a resolved dynamic adapter * If {@code cpi} denotes an entry representing a resolved dynamic adapter (see
* (see {@code resolveInvokeDynamicInPool} and {@code resolveInvokeHandleInPool}), * {@code resolveInvokeDynamicInPool} and {@code resolveInvokeHandleInPool}), return the opcode
* return the opcode of the instruction for which the resolution was performed * of the instruction for which the resolution was performed ({@code invokedynamic} or
* ({@code invokedynamic} or {@code invokevirtual}}, or {@code -1} otherwise. * {@code invokevirtual}}, or {@code -1} otherwise.
*/ */
native int isResolvedInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi); native int isResolvedInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
/** /**
* Gets the list of type names (in the format of {@link JavaType#getName()}) denoting the * Gets the list of type names (in the format of {@link JavaType#getName()}) denoting the
* classes that define signature polymorphic methods. * classes that define signature polymorphic methods.
@ -388,7 +388,7 @@ final class CompilerToVM {
/** /**
* Gets the static initializer of {@code type}. * 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); native HotSpotResolvedJavaMethodImpl getClassInitializer(HotSpotResolvedObjectTypeImpl type);
@ -468,7 +468,8 @@ final class CompilerToVM {
native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method); 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); native void setNotInlinableOrCompilable(HotSpotResolvedJavaMethodImpl method);

View file

@ -922,7 +922,10 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
} }
public ResolvedJavaMethod getClassInitializer() { public ResolvedJavaMethod getClassInitializer() {
return compilerToVM().getClassInitializer(this); if (!isArray()) {
return compilerToVM().getClassInitializer(this);
}
return null;
} }
@Override @Override

View file

@ -103,6 +103,14 @@ public class GetImplementorTest {
HotSpotResolvedObjectType resolvedIface = CompilerToVMHelper HotSpotResolvedObjectType resolvedIface = CompilerToVMHelper
.lookupTypeHelper(Utils.toJVMTypeSignature(tcase.anInterface), .lookupTypeHelper(Utils.toJVMTypeSignature(tcase.anInterface),
getClass(), /* resolve = */ true); getClass(), /* resolve = */ true);
if (!resolvedIface.isInterface()) {
try {
CompilerToVMHelper.getImplementor(resolvedIface);
Asserts.fail("Expected " + IllegalArgumentException.class.getName());
} catch (IllegalArgumentException e) {
}
return;
}
HotSpotResolvedObjectType resolvedImplementer = CompilerToVMHelper HotSpotResolvedObjectType resolvedImplementer = CompilerToVMHelper
.getImplementor(resolvedIface); .getImplementor(resolvedIface);
HotSpotResolvedObjectType resolvedExpected = null; HotSpotResolvedObjectType resolvedExpected = null;

View file

@ -473,6 +473,20 @@ public class TestResolvedJavaType extends TypeUniverse {
metaAccess.lookupJavaType(ConcreteTransitiveImplementor1.class); metaAccess.lookupJavaType(ConcreteTransitiveImplementor1.class);
metaAccess.lookupJavaType(ConcreteTransitiveImplementor2.class); metaAccess.lookupJavaType(ConcreteTransitiveImplementor2.class);
assertEquals(aSai2, iSai2.getSingleImplementor()); 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) @Test(expected = JVMCIError.class)
@ -830,6 +844,10 @@ public class TestResolvedJavaType extends TypeUniverse {
assertNull(metaAccess.lookupJavaType(C.class).getClassInitializer()); assertNull(metaAccess.lookupJavaType(C.class).getClassInitializer());
assertNull(metaAccess.lookupJavaType(int.class).getClassInitializer()); assertNull(metaAccess.lookupJavaType(int.class).getClassInitializer());
assertNull(metaAccess.lookupJavaType(void.class).getClassInitializer()); assertNull(metaAccess.lookupJavaType(void.class).getClassInitializer());
for (Class<?> c : classes) {
ResolvedJavaType type = metaAccess.lookupJavaType(c);
type.getClassInitializer();
}
} }
@Test @Test