# HG changeset patch # User Doug Simon # Date 1428482027 -7200 # Node ID 91f44f419e293643a30a73aafa5e62d71fb22a8a # Parent 0c1cd72188dc5ddf554d4a51a316c4809284ae06 support substituting non-static methods with a MethodSubstitutionPlugin diff -r 0c1cd72188dc -r 91f44f419e29 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java --- 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(","))); } /**