changeset 24100:839dcc4f2cf6 jvmci-0.24

handle signature polymorphic methods correctly (JDK-8161550)
author Doug Simon <doug.simon@oracle.com>
date Wed, 08 Feb 2017 23:49:32 +0100
parents 955ebad35cba
children efea6cfade16
files jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java src/share/vm/jvmci/jvmciCompilerToVM.cpp
diffstat 4 files changed, 54 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- 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;
             }
--- 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)) {
--- 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<? extends Annotation> SIGNATURE_POLYMORPHIC_CLASS = findPolymorphicSignatureClass();
 
     public TestResolvedJavaType() {
     }
 
+    @SuppressWarnings("unchecked")
+    private static Class<? extends Annotation> findPolymorphicSignatureClass() {
+        Class<? extends Annotation> 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<? extends Annotation>) 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;
+    }
 }
--- 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.