# HG changeset patch # User Doug Simon # Date 1486594172 -3600 # Node ID 839dcc4f2cf6d80369fba64e4ef127beaa1c2c38 # Parent 955ebad35cba54db57e9a8abab574587e94c5653 handle signature polymorphic methods correctly (JDK-8161550) diff -r 955ebad35cba -r 839dcc4f2cf6 jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java --- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java Wed Feb 08 23:25:01 2017 +0100 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java Wed Feb 08 23:49:32 2017 +0100 @@ -715,16 +715,20 @@ } - static class Lazy { - static final String[] signaturePolymorphicHolders = compilerToVM().getSignaturePolymorphicHolders(); - } + // Lazily initialized. + private static String[] signaturePolymorphicHolders; /** * Determines if {@code type} contains signature polymorphic methods. */ - private static boolean isSignaturePolymorphicHolder(final HotSpotResolvedObjectTypeImpl type) { + @SuppressFBWarnings(value = "LI_LAZY_INIT_STATIC", justification = "signaturePolymorphicHolders is a cache, not a singleton that must be constructed exactly once" + + "and compiler re-ordering is not an issue due to the VM call") + static boolean isSignaturePolymorphicHolder(final ResolvedJavaType type) { String name = type.getName(); - for (String holder : Lazy.signaturePolymorphicHolders) { + if (signaturePolymorphicHolders == null) { + signaturePolymorphicHolders = compilerToVM().getSignaturePolymorphicHolders(); + } + for (String holder : signaturePolymorphicHolders) { if (name.equals(holder)) { return true; } diff -r 955ebad35cba -r 839dcc4f2cf6 jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java --- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Wed Feb 08 23:25:01 2017 +0100 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Wed Feb 08 23:49:32 2017 +0100 @@ -24,6 +24,7 @@ import static java.util.Objects.requireNonNull; import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; +import static jdk.vm.ci.hotspot.HotSpotConstantPool.isSignaturePolymorphicHolder; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmClassModifiers; import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; @@ -427,7 +428,7 @@ // Methods can only be resolved against concrete types return null; } - if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic()) { + if (method.isConcrete() && method.getDeclaringClass().equals(this) && method.isPublic() && !isSignaturePolymorphicHolder(method.getDeclaringClass())) { return method; } if (!method.getDeclaringClass().isAssignableFrom(this)) { diff -r 955ebad35cba -r 839dcc4f2cf6 jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java --- a/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Wed Feb 08 23:25:01 2017 +0100 +++ b/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Wed Feb 08 23:49:32 2017 +0100 @@ -68,10 +68,28 @@ * Tests for {@link ResolvedJavaType}. */ public class TestResolvedJavaType extends TypeUniverse { + private static final Class SIGNATURE_POLYMORPHIC_CLASS = findPolymorphicSignatureClass(); public TestResolvedJavaType() { } + @SuppressWarnings("unchecked") + private static Class findPolymorphicSignatureClass() { + Class signaturePolyAnnotation = null; + try { + for (Class clazz : TestResolvedJavaType.class.getClassLoader().loadClass("java.lang.invoke.MethodHandle").getDeclaredClasses()) { + if (clazz.getName().endsWith("PolymorphicSignature") && Annotation.class.isAssignableFrom(clazz)) { + signaturePolyAnnotation = (Class) clazz; + break; + } + } + } catch (Throwable e) { + throw new AssertionError("Could not find annotation PolymorphicSignature in java.lang.invoke.MethodHandle", e); + } + assertNotNull(signaturePolyAnnotation); + return signaturePolyAnnotation; + } + @Test public void findInstanceFieldWithOffsetTest() { for (Class c : classes) { @@ -571,8 +589,14 @@ for (Method decl : decls) { ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl); if (m.isPublic()) { - ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl); - assertEquals(m.toString(), i, type.resolveMethod(m, context)); + ResolvedJavaMethod resolvedMethod = type.resolveMethod(m, context); + if (isSignaturePolymorphic(m)) { + // Signature polymorphic methods must not be resolved + assertNull(resolvedMethod); + } else { + ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl); + assertEquals(m.toString(), i, resolvedMethod); + } } } } @@ -600,8 +624,14 @@ for (Method decl : decls) { ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl); if (m.isPublic()) { - ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl); - assertEquals(i, type.resolveConcreteMethod(m, context)); + ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(m, context); + if (isSignaturePolymorphic(m)) { + // Signature polymorphic methods must not be resolved + assertNull(String.format("Got: %s", resolvedMethod), resolvedMethod); + } else { + ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl); + assertEquals(i, resolvedMethod); + } } } } @@ -919,4 +949,8 @@ } } } + + private static boolean isSignaturePolymorphic(ResolvedJavaMethod method) { + return method.getAnnotation(SIGNATURE_POLYMORPHIC_CLASS) != null; + } } diff -r 955ebad35cba -r 839dcc4f2cf6 src/share/vm/jvmci/jvmciCompilerToVM.cpp --- a/src/share/vm/jvmci/jvmciCompilerToVM.cpp Wed Feb 08 23:25:01 2017 +0100 +++ b/src/share/vm/jvmci/jvmciCompilerToVM.cpp Wed Feb 08 23:49:32 2017 +0100 @@ -938,6 +938,11 @@ Symbol* h_name = method->name(); Symbol* h_signature = method->signature(); + vmIntrinsics::ID iid = method()->intrinsic_id(); + if (MethodHandles::is_signature_polymorphic(iid) && MethodHandles::is_signature_polymorphic_intrinsic(iid)) { + // Signature polymorphic methods are already resolved, JVMCI just returns NULL in this case. + return NULL; + } methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail.