changeset 22012:53b4acee50f1

Add ResolvedJavaMethod.isSignaturePolymorphic and ResolvedJavaType.findMethod
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Thu, 18 Jun 2015 17:44:47 +0200
parents 4c9d4fe1cbd8
children 3904e33db5b3
files jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaMethod.java jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaType.java jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaMethod.java jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaType.java
diffstat 4 files changed, 72 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaMethod.java	Thu Jun 18 17:51:05 2015 +0200
+++ b/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaMethod.java	Thu Jun 18 17:44:47 2015 +0200
@@ -338,4 +338,22 @@
     }
 
     SpeculationLog getSpeculationLog();
+
+    /**
+     * Determines if the method identified by its holder and name is a <a
+     * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">signature
+     * polymorphic</a> method.
+     */
+    static boolean isSignaturePolymorphic(JavaType holder, String name, MetaAccessProvider metaAccess) {
+        if (!holder.getName().equals("Ljava/lang/invoke/MethodHandle;")) {
+            return false;
+        }
+        ResolvedJavaType methodHandleType = metaAccess.lookupJavaType(MethodHandle.class);
+        Signature signature = metaAccess.parseMethodDescriptor("([Ljava/lang/Object;)Ljava/lang/Object;");
+        ResolvedJavaMethod method = methodHandleType.findMethod(name, signature);
+        if (method == null) {
+            return false;
+        }
+        return method.isNative() && method.isVarArgs();
+    }
 }
--- a/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaType.java	Thu Jun 18 17:51:05 2015 +0200
+++ b/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaType.java	Thu Jun 18 17:44:47 2015 +0200
@@ -351,4 +351,13 @@
      * where the JVM verifier would not give any guarantees other than {@link Object}.
      */
     boolean isTrustedInterfaceType();
+
+    default ResolvedJavaMethod findMethod(String name, Signature signature) {
+        for (ResolvedJavaMethod method : getDeclaredMethods()) {
+            if (method.getName().equals(name) && method.getSignature().equals(signature)) {
+                return method;
+            }
+        }
+        return null;
+    }
 }
--- a/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaMethod.java	Thu Jun 18 17:51:05 2015 +0200
+++ b/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaMethod.java	Thu Jun 18 17:44:47 2015 +0200
@@ -25,6 +25,7 @@
 import static org.junit.Assert.*;
 
 import java.lang.annotation.*;
+import java.lang.invoke.*;
 import java.lang.reflect.*;
 import java.util.*;
 
@@ -361,6 +362,20 @@
         }
     }
 
+    @Test
+    public void isSignaturePolymorphicTest() {
+        ResolvedJavaType methodHandleType = metaAccess.lookupJavaType(MethodHandle.class);
+        assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invokeExact", metaAccess));
+        assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invoke", metaAccess));
+        assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invokeBasic", metaAccess));
+        assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToVirtual", metaAccess));
+        assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToStatic", metaAccess));
+        assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToSpecial", metaAccess));
+        assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToInterface", metaAccess));
+        assertFalse(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "type", metaAccess));
+        assertFalse(ResolvedJavaMethod.isSignaturePolymorphic(metaAccess.lookupJavaType(Object.class), "toString", metaAccess));
+    }
+
     private Method findTestMethod(Method apiMethod) {
         String testName = apiMethod.getName() + "Test";
         for (Method m : getClass().getDeclaredMethods()) {
@@ -400,6 +415,9 @@
     public void testCoverage() {
         Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
         for (Method m : ResolvedJavaMethod.class.getDeclaredMethods()) {
+            if (Modifier.isStatic(m.getModifiers())) {
+                continue;
+            }
             if (findTestMethod(m) == null) {
                 assertTrue("test missing for " + m, known.contains(m.getName()));
             } else {
--- a/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaType.java	Thu Jun 18 17:51:05 2015 +0200
+++ b/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaType.java	Thu Jun 18 17:44:47 2015 +0200
@@ -771,6 +771,10 @@
         }
     }
 
+    static class SubD extends D {
+
+    }
+
     @Test
     public void getClassInitializerTest() {
         assertNotNull(metaAccess.lookupJavaType(A.class).getClassInitializer());
@@ -833,6 +837,29 @@
         }
     }
 
+    @Test
+    public void findMethodTest() {
+        try {
+            ResolvedJavaMethod findFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("()V"));
+            ResolvedJavaMethod expectedFoo = metaAccess.lookupJavaMethod(D.class.getDeclaredMethod("foo"));
+            assertEquals(expectedFoo, findFoo);
+
+            ResolvedJavaMethod wrongReturnTypeFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("()I"));
+            assertNull(wrongReturnTypeFoo);
+
+            ResolvedJavaMethod wrongArgumentsFoo = metaAccess.lookupJavaType(D.class).findMethod("foo", metaAccess.parseMethodDescriptor("(I)V"));
+            assertNull(wrongArgumentsFoo);
+
+            ResolvedJavaMethod wrongNameFoo = metaAccess.lookupJavaType(D.class).findMethod("bar", metaAccess.parseMethodDescriptor("()V"));
+            assertNull(wrongNameFoo);
+
+            ResolvedJavaMethod wrongClassFoo = metaAccess.lookupJavaType(SubD.class).findMethod("foo", metaAccess.parseMethodDescriptor("()V"));
+            assertNull(wrongClassFoo);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     private Method findTestMethod(Method apiMethod) {
         String testName = apiMethod.getName() + "Test";
         for (Method m : getClass().getDeclaredMethods()) {