# HG changeset patch # User Tom Rodriguez # Date 1400224361 25200 # Node ID 423bf61c9c32dc75166e104b66b95b8b85792dff # Parent eaeba148bb1537bfc072bc5bb2765df01812908c use inner classes instead of reflection during matching diff -r eaeba148bb15 -r 423bf61c9c32 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchGenerator.java Thu May 15 20:11:16 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchGenerator.java Fri May 16 00:12:41 2014 -0700 @@ -32,5 +32,10 @@ * @returns null if the match can't be generated or a {@link ComplexMatchResult} that can be * evaluated during LIR generation to produce the final LIR value. */ - ComplexMatchResult match(NodeLIRBuilder gen); + ComplexMatchResult match(NodeLIRBuilder gen, Object... args); + + /** + * @return a descriptive name meaningful to the user. + */ + String getName(); } diff -r eaeba148bb15 -r 423bf61c9c32 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Thu May 15 20:11:16 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Fri May 16 00:12:41 2014 -0700 @@ -331,7 +331,8 @@ List requiredPackages = new ArrayList<>(); /** - * The java.lang.reflect.Method for invoking a method based MatchRule. + * The mapping between elements with MatchRules and the wrapper class used invoke the code + * generation after the match. */ private Map invokers = new LinkedHashMap<>(); @@ -486,9 +487,7 @@ out.println("package " + pkg + ";"); out.println(""); out.println("import java.util.*;"); - out.println("import java.lang.reflect.*;"); out.println("import " + MatchStatementSet.class.getPackage().getName() + ".*;"); - out.println("import " + GraalInternalError.class.getName() + ";"); out.println("import " + NodeLIRBuilder.class.getName() + ";"); out.println("import " + NodeClass.class.getName() + ";"); for (String p : requiredPackages) { @@ -498,33 +497,33 @@ out.println("public class " + matchStatementClassName + " implements " + MatchStatementSet.class.getSimpleName() + " {"); out.println(); - out.println(" private static Method lookupMethod(Class theClass, String name, Class... args) {"); - out.println(" try {"); - out.println(" return theClass.getDeclaredMethod(name, args);"); - out.println(" } catch (Exception e) {"); - out.println(" throw new GraalInternalError(e);"); - out.println(" }"); - out.println(" }"); - out.println(); - // Generate declarations for the reflective invocation of the code generation methods. + // Generate declarations for the wrapper class to invoke the code generation methods. for (MethodInvokerItem invoker : invokers.values()) { StringBuilder args = new StringBuilder(); StringBuilder types = new StringBuilder(); int count = invoker.fields.size(); + int index = 0; for (VariableElement arg : invoker.fields) { args.append('"'); args.append(arg.getSimpleName()); args.append('"'); - types.append(fullClassName(typeUtils.asElement(arg.asType()))); - types.append(".class"); + types.append(String.format("(%s) args[%s]", fullClassName(typeUtils.asElement(arg.asType())), index++)); if (count-- > 1) { args.append(", "); types.append(", "); } } out.printf(" private static final String[] %s = new String[] {%s};\n", invoker.argumentsListName(), args); - out.printf(" private static final Method %s = lookupMethod(%s.class, \"%s\", %s);\n", invoker.reflectiveMethodName(), invoker.nodeLIRBuilderClass, invoker.methodName, types); + out.printf(" private static final class %s implements MatchGenerator {\n", invoker.wrapperClass()); + out.printf(" static MatchGenerator instance = new %s();\n", invoker.wrapperClass()); + out.printf(" public ComplexMatchResult match(NodeLIRBuilder builder, Object...args) {\n"); + out.printf(" return ((%s) builder).%s(%s);\n", invoker.nodeLIRBuilderClass, invoker.methodName, types); + out.printf(" }\n"); + out.printf(" public String getName() {\n"); + out.printf(" return \"%s\";\n", invoker.methodName); + out.printf(" }\n"); + out.printf(" }\n"); out.println(); } @@ -606,13 +605,12 @@ * @return a string which will construct the MatchStatement instance to match this pattern. */ public String ruleBuilder() { - return String.format("new MatchStatement(\"%s\", %s, %s, %s)", invoker.name, matchPattern, invoker.reflectiveMethodName(), invoker.argumentsListName()); + return String.format("new MatchStatement(\"%s\", %s, %s.instance, %s)", invoker.name, matchPattern, invoker.wrapperClass(), invoker.argumentsListName()); } } /** - * Used to generate the declarations needed for reflective invocation of the code generation - * method. + * Used to generate the wrapper class to invoke the code generation method. */ static class MethodInvokerItem { final String name; @@ -627,8 +625,8 @@ this.fields = fields; } - String reflectiveMethodName() { - return methodName + "_invoke"; + String wrapperClass() { + return "MatchGenerator_" + methodName; } String argumentsListName() { diff -r eaeba148bb15 -r 423bf61c9c32 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java Thu May 15 20:11:16 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java Fri May 16 00:12:41 2014 -0700 @@ -24,11 +24,9 @@ import static com.oracle.graal.compiler.GraalDebugConfig.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.match.MatchPattern.MatchResultCode; import com.oracle.graal.compiler.match.MatchPattern.Result; @@ -59,14 +57,14 @@ /** * The method in the {@link NodeLIRBuilder} subclass that will actually do the code emission. */ - private Method generatorMethod; + private MatchGenerator generatorMethod; /** * The name of arguments in the order they are expected to be passed to the generator method. */ private String[] arguments; - public MatchStatement(String name, MatchPattern pattern, Method generator, String[] arguments) { + public MatchStatement(String name, MatchPattern pattern, MatchGenerator generator, String[] arguments) { this.name = name; this.pattern = pattern; this.generatorMethod = generator; @@ -93,23 +91,19 @@ MatchContext context = new MatchContext(builder, this, index, node, nodes); result = pattern.matchUsage(node, context); if (result == Result.OK) { - try { - // Invoke the generator method and set the result if it's non null. - ComplexMatchResult value = (ComplexMatchResult) generatorMethod.invoke(builder, buildArgList(context)); - if (value != null) { - context.setResult(value); - MatchStatementSuccess.increment(); - Debug.metric("MatchStatement[%s]", getName()).increment(); - return true; - } - // The pattern matched but some other code generation constraint disallowed code - // generation for the pattern. - if (LogVerbose.getValue()) { - Debug.log("while matching %s|%s %s %s returned null", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), generatorMethod.getName()); - Debug.log("with nodes %s", formatMatch(node)); - } - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new GraalInternalError(e); + // Invoke the generator method and set the result if it's non null. + ComplexMatchResult value = generatorMethod.match(builder, buildArgList(context)); + if (value != null) { + context.setResult(value); + MatchStatementSuccess.increment(); + Debug.metric("MatchStatement[%s]", getName()).increment(); + return true; + } + // The pattern matched but some other code generation constraint disallowed code + // generation for the pattern. + if (LogVerbose.getValue()) { + Debug.log("while matching %s|%s %s %s returned null", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), generatorMethod.getName()); + Debug.log("with nodes %s", formatMatch(node)); } } else { if (LogVerbose.getValue() && result.code != MatchResultCode.WRONG_CLASS) {