changeset 20849:91f44f419e29

support substituting non-static methods with a MethodSubstitutionPlugin
author Doug Simon <doug.simon@oracle.com>
date Wed, 08 Apr 2015 10:33:47 +0200
parents 0c1cd72188dc
children 9d4a36560833
files graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java
diffstat 1 files changed, 48 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java	Wed Apr 08 00:03:10 2015 +0200
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java	Wed Apr 08 10:33:47 2015 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.graphbuilderconf;
 
 import java.lang.reflect.*;
+import java.util.*;
+import java.util.stream.*;
 
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver;
 import com.oracle.graal.nodes.*;
@@ -43,6 +44,7 @@
     private final Class<?> declaringClass;
     private final String name;
     private final Class<?>[] parameters;
+    private final boolean originalIsStatic;
 
     /**
      * Creates a method substitution plugin.
@@ -57,6 +59,7 @@
         this.declaringClass = declaringClass;
         this.name = name;
         this.parameters = parameters;
+        this.originalIsStatic = parameters.length == 0 || parameters[0] != Receiver.class;
     }
 
     /**
@@ -65,7 +68,6 @@
     public ResolvedJavaMethod getSubstitute(MetaAccessProvider metaAccess) {
         if (cachedSubstitute == null) {
             cachedSubstitute = metaAccess.lookupJavaMethod(getJavaSubstitute());
-            assert cachedSubstitute.getAnnotation(MethodSubstitution.class) != null;
         }
         return cachedSubstitute;
     }
@@ -74,19 +76,53 @@
      * Gets the reflection API version of the substitution method.
      */
     Method getJavaSubstitute() throws GraalInternalError {
-        try {
-            Method substituteMethod = declaringClass.getDeclaredMethod(name, parameters);
-            int modifiers = substituteMethod.getModifiers();
-            if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
-                throw new GraalInternalError("Substitution method must not be abstract or native: " + substituteMethod);
+        Method substituteMethod = lookupSubstitute();
+        int modifiers = substituteMethod.getModifiers();
+        if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+            throw new GraalInternalError("Substitution method must not be abstract or native: " + substituteMethod);
+        }
+        if (!Modifier.isStatic(modifiers)) {
+            throw new GraalInternalError("Substitution method must be static: " + substituteMethod);
+        }
+        return substituteMethod;
+    }
+
+    /**
+     * Determines if a given method is the substitute method of this plugin.
+     */
+    private boolean isSubstitute(Method m) {
+        if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) {
+            if (parameters.length == m.getParameterCount()) {
+                Class<?>[] mparams = m.getParameterTypes();
+                int start = 0;
+                if (!originalIsStatic) {
+                    start = 1;
+                    if (!mparams[0].isAssignableFrom(parameters[0])) {
+                        return false;
+                    }
+                }
+                for (int i = start; i < mparams.length; i++) {
+                    if (mparams[i] != parameters[i]) {
+                        return false;
+                    }
+                }
             }
-            if (!Modifier.isStatic(modifiers)) {
-                throw new GraalInternalError("Substitution method must be static: " + substituteMethod);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Gets the substitute method of this plugin.
+     */
+    private Method lookupSubstitute() {
+        for (Method m : declaringClass.getDeclaredMethods()) {
+            if (isSubstitute(m)) {
+                return m;
             }
-            return substituteMethod;
-        } catch (NoSuchMethodException e) {
-            throw new GraalInternalError(e);
         }
+        throw new GraalInternalError("No method found in %s compatible with the signature (%s)", declaringClass.getName(), Arrays.asList(parameters).stream().map(c -> c.getSimpleName()).collect(
+                        Collectors.joining(",")));
     }
 
     /**