changeset 23150:cda21cbf6ac0

Only generate a single NodeIntrinsicPluginFactory for all @NodeIntrinsic and @Fold methods in a top-level class.
author Roland Schatz <roland.schatz@oracle.com>
date Wed, 09 Dec 2015 16:06:22 +0100
parents cca72677127b
children d450066656fd
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/FoldTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/ClassSubstitutionVerifier.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldPluginGenerator.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldVerifier.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/GeneratedFoldPlugin.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/GeneratedNodeIntrinsicPlugin.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/GeneratedPlugin.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/InjectedDependencies.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/MethodSubstitutionVerifier.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicPluginGenerator.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java
diffstat 19 files changed, 633 insertions(+), 590 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Wed Dec 09 16:06:22 2015 +0100
@@ -131,7 +131,7 @@
                 StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, invocationPlugins, true);
 
                 for (NodeIntrinsicPluginFactory factory : Services.load(NodeIntrinsicPluginFactory.class)) {
-                    factory.registerPlugin(invocationPlugins, nodeIntrinsificationProvider);
+                    factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider);
                 }
 
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java	Wed Dec 09 16:06:22 2015 +0100
@@ -33,5 +33,5 @@
         Stamp getReturnStamp(Class<?> type);
     }
 
-    void registerPlugin(InvocationPlugins plugins, InjectionProvider injection);
+    void registerPlugins(InvocationPlugins plugins, InjectionProvider injection);
 }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/FoldTest.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/FoldTest.java	Wed Dec 09 16:06:22 2015 +0100
@@ -95,8 +95,7 @@
         Plugins ret = super.getDefaultGraphBuilderPlugins();
         // manually register generated factories, jvmci service providers don't work from unit tests
         InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null);
-        new FoldFactory_FoldTest_FoldUtils_getNumber().registerPlugin(ret.getInvocationPlugins(), injection);
-        new FoldFactory_FoldTest_FoldUtils_multiply_255f288().registerPlugin(ret.getInvocationPlugins(), injection);
+        new PluginFactory_FoldTest().registerPlugins(ret.getInvocationPlugins(), injection);
         return ret;
     }
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java	Wed Dec 09 16:06:22 2015 +0100
@@ -48,7 +48,7 @@
     protected Plugins getDefaultGraphBuilderPlugins() {
         Plugins ret = super.getDefaultGraphBuilderPlugins();
         // manually register generated factory, jvmci service providers don't work from unit tests
-        new NodeIntrinsicFactory_ReplacementsParseTest_TestMethodsSubstitutions_asNonNullStringIntrinsic_2bfccb54().registerPlugin(ret.getInvocationPlugins(), null);
+        new PluginFactory_ReplacementsParseTest().registerPlugins(ret.getInvocationPlugins(), null);
         return ret;
     }
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java	Wed Dec 09 16:06:22 2015 +0100
@@ -128,9 +128,7 @@
     protected Plugins getDefaultGraphBuilderPlugins() {
         Plugins ret = super.getDefaultGraphBuilderPlugins();
         // manually register generated factories, jvmci service providers don't work from unit tests
-        new NodeIntrinsicFactory_SubstitutionsTest_TestGuard_guard_1c2b7e8f().registerPlugin(ret.getInvocationPlugins(), null);
-        new NodeIntrinsicFactory_SubstitutionsTest_TestMemory_memory().registerPlugin(ret.getInvocationPlugins(), null);
-        new NodeIntrinsicFactory_SubstitutionsTest_TestValue_value_a22f0f5f().registerPlugin(ret.getInvocationPlugins(), null);
+        new PluginFactory_SubstitutionsTest().registerPlugins(ret.getInvocationPlugins(), null);
         return ret;
     }
 
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java	Wed Dec 09 16:06:22 2015 +0100
@@ -26,18 +26,9 @@
 import java.util.List;
 
 import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVariable;
-import javax.lang.model.type.WildcardType;
 import javax.tools.Diagnostic.Kind;
 
 /**
@@ -105,81 +96,6 @@
         return cur;
     }
 
-    private static void getSignatureName(StringBuilder ret, Element element) {
-        Element enclosing = element.getEnclosingElement();
-        if (enclosing.getKind() == ElementKind.PACKAGE) {
-            ret.append(((PackageElement) enclosing).getQualifiedName().toString().replace('.', '/'));
-            ret.append('/');
-        } else {
-            getSignatureName(ret, enclosing);
-            ret.append('$');
-        }
-        ret.append(element.getSimpleName());
-    }
-
-    private static void getSignatureString(StringBuilder ret, TypeMirror type) {
-        switch (type.getKind()) {
-            case ARRAY:
-                ret.append('[');
-                getSignatureString(ret, ((ArrayType) type).getComponentType());
-                break;
-            case BOOLEAN:
-                ret.append('Z');
-                break;
-            case BYTE:
-                ret.append('B');
-                break;
-            case SHORT:
-                ret.append('S');
-                break;
-            case CHAR:
-                ret.append('C');
-                break;
-            case INT:
-                ret.append('I');
-                break;
-            case LONG:
-                ret.append('J');
-                break;
-            case FLOAT:
-                ret.append('F');
-                break;
-            case DOUBLE:
-                ret.append('D');
-                break;
-            case VOID:
-                ret.append('V');
-                break;
-            case DECLARED:
-                ret.append('L');
-                getSignatureName(ret, ((DeclaredType) type).asElement());
-                ret.append(';');
-                break;
-            case TYPEVAR:
-                getSignatureString(ret, ((TypeVariable) type).getUpperBound());
-                break;
-            case WILDCARD:
-                getSignatureString(ret, ((WildcardType) type).getExtendsBound());
-                break;
-            case INTERSECTION:
-                ret.append("Ljava/lang/Object;");
-                break;
-            default:
-                throw new IllegalArgumentException(type.toString());
-        }
-    }
-
-    public static String toSignature(ExecutableElement intrinsicMethod) {
-        StringBuilder ret = new StringBuilder();
-        ret.append('(');
-        for (VariableElement param : intrinsicMethod.getParameters()) {
-            getSignatureString(ret, param.asType());
-        }
-        ret.append(')');
-        getSignatureString(ret, intrinsicMethod.getReturnType());
-        return ret.toString();
-    }
-
     public int getParameterCount(boolean withReceiver) {
         return arguments.size() + (withReceiver ? 1 : 0);
     }
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java	Wed Dec 09 16:06:22 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
         this.env = env;
     }
 
-    public abstract void verify(Element element, AnnotationMirror annotation);
+    public abstract void verify(Element element, AnnotationMirror annotation, PluginGenerator generator);
 
     public abstract Class<? extends Annotation> getAnnotationClass();
 
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/ClassSubstitutionVerifier.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/ClassSubstitutionVerifier.java	Wed Dec 09 16:06:22 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public void verify(Element element, AnnotationMirror classSubstitution) {
+    public void verify(Element element, AnnotationMirror classSubstitution, PluginGenerator generator) {
         if (!element.getKind().isClass()) {
             assert false : "Element is guaranteed to be a class.";
             return;
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldPluginGenerator.java	Tue Dec 08 20:47:09 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.replacements.verifier;
-
-import java.io.PrintWriter;
-import java.lang.annotation.Annotation;
-import java.util.List;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeMirror;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.graal.api.replacements.Fold;
-import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency;
-
-/**
- * Create graph builder plugins for {@link Fold} methods.
- */
-public class FoldPluginGenerator extends PluginGenerator {
-
-    private class FoldVerifier extends AbstractVerifier {
-
-        public FoldVerifier(ProcessingEnvironment env) {
-            super(env);
-        }
-
-        @Override
-        public void verify(Element element, AnnotationMirror annotation) {
-            if (element.getKind() != ElementKind.METHOD) {
-                assert false : "Element is guaranteed to be a method.";
-                return;
-            }
-
-            ExecutableElement intrinsicMethod = (ExecutableElement) element;
-            if (intrinsicMethod.getModifiers().contains(Modifier.PRIVATE)) {
-                env.getMessager().printMessage(Kind.ERROR, "@Fold method can not be private.", element);
-            } else {
-                FoldPluginGenerator.this.createPluginFactory(intrinsicMethod, null, null);
-            }
-        }
-
-        @Override
-        public Class<? extends Annotation> getAnnotationClass() {
-            return Fold.class;
-        }
-    }
-
-    private TypeMirror stringType() {
-        return env.getElementUtils().getTypeElement("java.lang.String").asType();
-    }
-
-    public FoldPluginGenerator(ProcessingEnvironment env) {
-        super(env);
-    }
-
-    public AbstractVerifier getVerifier() {
-        return new FoldVerifier(env);
-    }
-
-    @Override
-    protected String getBaseName() {
-        return "FoldFactory";
-    }
-
-    @Override
-    protected void createImports(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement targetMethod) {
-        out.printf("import jdk.vm.ci.meta.JavaConstant;\n");
-        out.printf("import jdk.vm.ci.meta.JavaKind;\n");
-        out.printf("import com.oracle.graal.nodes.ConstantNode;\n");
-        super.createImports(out, intrinsicMethod, targetMethod);
-    }
-
-    @Override
-    protected InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) {
-        InjectedDependencies deps = new InjectedDependencies();
-        List<? extends VariableElement> params = intrinsicMethod.getParameters();
-
-        int argCount = 0;
-        Object receiver;
-        if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) {
-            receiver = intrinsicMethod.getEnclosingElement();
-        } else {
-            receiver = "arg0";
-            TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement();
-            constantArgument(out, deps, argCount, type.asType(), argCount);
-            argCount++;
-        }
-
-        int firstArg = argCount;
-        for (VariableElement param : params) {
-            constantArgument(out, deps, argCount, param.asType(), argCount);
-            argCount++;
-        }
-
-        if (intrinsicMethod.getAnnotation(Deprecated.class) != null) {
-            out.printf("            @SuppressWarnings(\"deprecation\")\n");
-        }
-        out.printf("            %s result = %s.%s(", intrinsicMethod.getReturnType(), receiver, intrinsicMethod.getSimpleName());
-        if (argCount > firstArg) {
-            out.printf("arg%d", firstArg);
-            for (int i = firstArg + 1; i < argCount; i++) {
-                out.printf(", arg%d", i);
-            }
-        }
-        out.printf(");\n");
-
-        TypeMirror returnType = intrinsicMethod.getReturnType();
-        switch (returnType.getKind()) {
-            case BOOLEAN:
-                out.printf("            JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n");
-                break;
-            case BYTE:
-            case SHORT:
-            case CHAR:
-            case INT:
-                out.printf("            JavaConstant constant = JavaConstant.forInt(result);\n");
-                break;
-            case LONG:
-                out.printf("            JavaConstant constant = JavaConstant.forLong(result);\n");
-                break;
-            case FLOAT:
-                out.printf("            JavaConstant constant = JavaConstant.forFloat(result);\n");
-                break;
-            case DOUBLE:
-                out.printf("            JavaConstant constant = JavaConstant.forDouble(result);\n");
-                break;
-            case ARRAY:
-            case TYPEVAR:
-            case DECLARED:
-                if (returnType.equals(stringType())) {
-                    out.printf("            JavaConstant constant = %s.forString(result);\n", deps.use(WellKnownDependency.CONSTANT_REFLECTION));
-                } else {
-                    out.printf("            JavaConstant constant = %s.forObject(result);\n", deps.use(WellKnownDependency.SNIPPET_REFLECTION));
-                }
-                break;
-            default:
-                throw new IllegalArgumentException(returnType.toString());
-        }
-
-        out.printf("            ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(WellKnownDependency.META_ACCESS), deps.use(WellKnownDependency.STRUCTURED_GRAPH));
-        out.printf("            b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod).name());
-        out.printf("            return true;\n");
-
-        return deps;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldVerifier.java	Wed Dec 09 16:06:22 2015 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.verifier;
+
+import java.lang.annotation.Annotation;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.graal.api.replacements.Fold;
+
+public final class FoldVerifier extends AbstractVerifier {
+
+    public FoldVerifier(ProcessingEnvironment env) {
+        super(env);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationClass() {
+        return Fold.class;
+    }
+
+    @Override
+    public void verify(Element element, AnnotationMirror annotation, PluginGenerator generator) {
+        if (element.getKind() != ElementKind.METHOD) {
+            assert false : "Element is guaranteed to be a method.";
+            return;
+        }
+
+        ExecutableElement foldMethod = (ExecutableElement) element;
+        if (foldMethod.getModifiers().contains(Modifier.PRIVATE)) {
+            env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must not be private.", Fold.class.getSimpleName()), element, annotation);
+        } else {
+            generator.addPlugin(new GeneratedFoldPlugin(foldMethod));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/GeneratedFoldPlugin.java	Wed Dec 09 16:06:22 2015 +0100
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.verifier;
+
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+import com.oracle.graal.api.replacements.Fold;
+import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency;
+
+/**
+ * Create graph builder plugins for {@link Fold} methods.
+ */
+public class GeneratedFoldPlugin extends GeneratedPlugin {
+
+    public GeneratedFoldPlugin(ExecutableElement intrinsicMethod) {
+        super(intrinsicMethod);
+    }
+
+    private static TypeMirror stringType(ProcessingEnvironment env) {
+        return env.getElementUtils().getTypeElement("java.lang.String").asType();
+    }
+
+    @Override
+    public void extraImports(Set<String> imports) {
+        imports.add("jdk.vm.ci.meta.JavaConstant");
+        imports.add("jdk.vm.ci.meta.JavaKind");
+        imports.add("com.oracle.graal.nodes.ConstantNode");
+    }
+
+    @Override
+    protected InjectedDependencies createExecute(ProcessingEnvironment env, PrintWriter out) {
+        InjectedDependencies deps = new InjectedDependencies();
+        List<? extends VariableElement> params = intrinsicMethod.getParameters();
+
+        int argCount = 0;
+        Object receiver;
+        if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) {
+            receiver = intrinsicMethod.getEnclosingElement();
+        } else {
+            receiver = "arg0";
+            TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement();
+            constantArgument(env, out, deps, argCount, type.asType(), argCount);
+            argCount++;
+        }
+
+        int firstArg = argCount;
+        for (VariableElement param : params) {
+            constantArgument(env, out, deps, argCount, param.asType(), argCount);
+            argCount++;
+        }
+
+        if (intrinsicMethod.getAnnotation(Deprecated.class) != null) {
+            out.printf("            @SuppressWarnings(\"deprecation\")\n");
+        }
+        out.printf("            %s result = %s.%s(", intrinsicMethod.getReturnType(), receiver, intrinsicMethod.getSimpleName());
+        if (argCount > firstArg) {
+            out.printf("arg%d", firstArg);
+            for (int i = firstArg + 1; i < argCount; i++) {
+                out.printf(", arg%d", i);
+            }
+        }
+        out.printf(");\n");
+
+        TypeMirror returnType = intrinsicMethod.getReturnType();
+        switch (returnType.getKind()) {
+            case BOOLEAN:
+                out.printf("            JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n");
+                break;
+            case BYTE:
+            case SHORT:
+            case CHAR:
+            case INT:
+                out.printf("            JavaConstant constant = JavaConstant.forInt(result);\n");
+                break;
+            case LONG:
+                out.printf("            JavaConstant constant = JavaConstant.forLong(result);\n");
+                break;
+            case FLOAT:
+                out.printf("            JavaConstant constant = JavaConstant.forFloat(result);\n");
+                break;
+            case DOUBLE:
+                out.printf("            JavaConstant constant = JavaConstant.forDouble(result);\n");
+                break;
+            case ARRAY:
+            case TYPEVAR:
+            case DECLARED:
+                if (returnType.equals(stringType(env))) {
+                    out.printf("            JavaConstant constant = %s.forString(result);\n", deps.use(WellKnownDependency.CONSTANT_REFLECTION));
+                } else {
+                    out.printf("            JavaConstant constant = %s.forObject(result);\n", deps.use(WellKnownDependency.SNIPPET_REFLECTION));
+                }
+                break;
+            default:
+                throw new IllegalArgumentException(returnType.toString());
+        }
+
+        out.printf("            ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(WellKnownDependency.META_ACCESS), deps.use(WellKnownDependency.STRUCTURED_GRAPH));
+        out.printf("            b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod).name());
+        out.printf("            return true;\n");
+
+        return deps;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/GeneratedNodeIntrinsicPlugin.java	Wed Dec 09 16:06:22 2015 +0100
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.verifier;
+
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic.Kind;
+
+import jdk.vm.ci.meta.JavaKind;
+
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.InjectedNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency;
+
+/**
+ * Create graph builder plugins for {@link NodeIntrinsic} methods.
+ */
+public abstract class GeneratedNodeIntrinsicPlugin extends GeneratedPlugin {
+
+    private final TypeMirror[] signature;
+
+    public GeneratedNodeIntrinsicPlugin(ExecutableElement intrinsicMethod, TypeMirror[] signature) {
+        super(intrinsicMethod);
+        this.signature = signature;
+    }
+
+    private static TypeMirror valueNodeType(ProcessingEnvironment env) {
+        return env.getElementUtils().getTypeElement("com.oracle.graal.nodes.ValueNode").asType();
+    }
+
+    protected abstract List<? extends VariableElement> getParameters();
+
+    protected abstract void factoryCall(ProcessingEnvironment env, PrintWriter out, InjectedDependencies deps, int argCount);
+
+    @Override
+    protected InjectedDependencies createExecute(ProcessingEnvironment env, PrintWriter out) {
+        InjectedDependencies deps = new InjectedDependencies();
+
+        List<? extends VariableElement> params = getParameters();
+
+        int idx = 0;
+        for (; idx < params.size(); idx++) {
+            VariableElement param = params.get(idx);
+            if (param.getAnnotation(InjectedNodeParameter.class) == null) {
+                break;
+            }
+
+            out.printf("            %s arg%d = %s;\n", param.asType(), idx, deps.use(env, (DeclaredType) param.asType()));
+        }
+
+        for (int i = 0; i < signature.length; i++, idx++) {
+            if (intrinsicMethod.getParameters().get(i).getAnnotation(ConstantNodeParameter.class) != null) {
+                constantArgument(env, out, deps, idx, signature[i], i);
+            } else {
+                if (signature[i].equals(valueNodeType(env))) {
+                    out.printf("            ValueNode arg%d = args[%d];\n", idx, i);
+                } else {
+                    out.printf("            %s arg%d = (%s) args[%d];\n", signature[i], idx, signature[i], i);
+                }
+            }
+        }
+
+        factoryCall(env, out, deps, idx);
+
+        return deps;
+    }
+
+    public static class ConstructorPlugin extends GeneratedNodeIntrinsicPlugin {
+
+        private final ExecutableElement constructor;
+
+        public ConstructorPlugin(ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) {
+            super(intrinsicMethod, signature);
+            this.constructor = constructor;
+        }
+
+        @Override
+        public void extraImports(Set<String> imports) {
+            if (getReturnKind(intrinsicMethod) != JavaKind.Void) {
+                imports.add("jdk.vm.ci.meta.JavaKind");
+            }
+        }
+
+        @Override
+        protected List<? extends VariableElement> getParameters() {
+            return constructor.getParameters();
+        }
+
+        @Override
+        protected void factoryCall(ProcessingEnvironment env, PrintWriter out, InjectedDependencies deps, int argCount) {
+            out.printf("            %s node = new %s(", constructor.getEnclosingElement(), constructor.getEnclosingElement());
+            if (argCount > 0) {
+                out.printf("arg0");
+                for (int i = 1; i < argCount; i++) {
+                    out.printf(", arg%d", i);
+                }
+            }
+            out.printf(");\n");
+
+            if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) {
+                out.printf("            node.setStamp(%s);\n", deps.use(WellKnownDependency.RETURN_STAMP));
+            }
+
+            JavaKind returnKind = getReturnKind(intrinsicMethod);
+            if (returnKind == JavaKind.Void) {
+                out.printf("            b.add(node);\n");
+            } else {
+                out.printf("            b.addPush(JavaKind.%s, node);\n", returnKind.name());
+            }
+            out.printf("            return true;\n");
+        }
+    }
+
+    public static class CustomFactoryPlugin extends GeneratedNodeIntrinsicPlugin {
+
+        private final ExecutableElement customFactory;
+
+        public CustomFactoryPlugin(ExecutableElement intrinsicMethod, ExecutableElement customFactory, TypeMirror[] signature) {
+            super(intrinsicMethod, signature);
+            this.customFactory = customFactory;
+        }
+
+        @Override
+        public void extraImports(Set<String> imports) {
+        }
+
+        @Override
+        protected List<? extends VariableElement> getParameters() {
+            List<? extends VariableElement> ret = customFactory.getParameters();
+            // remove initial GraphBuilderContext parameter
+            return ret.subList(1, ret.size());
+        }
+
+        @Override
+        protected void factoryCall(ProcessingEnvironment env, PrintWriter out, InjectedDependencies deps, int argCount) {
+            out.printf("            return %s.%s(b", customFactory.getEnclosingElement(), customFactory.getSimpleName());
+            for (int i = 0; i < argCount; i++) {
+                out.printf(", arg%d", i);
+            }
+            out.printf(");\n");
+
+            if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) {
+                env.getMessager().printMessage(Kind.WARNING, "Ignoring setStampFromReturnType because a custom 'intrinsify' method is used.", intrinsicMethod);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/GeneratedPlugin.java	Wed Dec 09 16:06:22 2015 +0100
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.verifier;
+
+import java.io.PrintWriter;
+import java.util.Set;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
+import javax.lang.model.type.WildcardType;
+
+import jdk.vm.ci.meta.JavaKind;
+
+import com.oracle.graal.replacements.verifier.InjectedDependencies.Dependency;
+import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency;
+
+public abstract class GeneratedPlugin {
+
+    protected final ExecutableElement intrinsicMethod;
+    private boolean needInjectionProvider;
+
+    public GeneratedPlugin(ExecutableElement intrinsicMethod) {
+        this.intrinsicMethod = intrinsicMethod;
+        this.needInjectionProvider = false;
+    }
+
+    public void generate(ProcessingEnvironment env, PrintWriter out, int idx) {
+        out.printf("    // class:  %s\n", intrinsicMethod.getEnclosingElement());
+        out.printf("    // method: %s\n", intrinsicMethod);
+        out.printf("    private static final class Plugin%d extends GeneratedInvocationPlugin {\n", idx);
+        out.printf("\n");
+        out.printf("        @Override\n");
+        out.printf("        public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) {\n");
+        out.printf("            if (!b.parsingIntrinsic()) {\n");
+        out.printf("                return false;\n");
+        out.printf("            }\n");
+        InjectedDependencies deps = createExecute(env, out);
+        out.printf("        }\n");
+
+        createPrivateMembers(out, deps, idx);
+
+        out.printf("    }\n");
+    }
+
+    public void register(PrintWriter out, int idx) {
+        out.printf("        plugins.register(new Plugin%d(", idx);
+        if (needInjectionProvider) {
+            out.printf("injection");
+        }
+        out.printf("), %s.class, \"%s\"", intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName());
+        if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) {
+            out.printf(", InvocationPlugin.Receiver.class");
+        }
+        for (VariableElement arg : intrinsicMethod.getParameters()) {
+            out.printf(", %s.class", getErasedType(arg.asType()));
+        }
+        out.printf(");\n");
+    }
+
+    public abstract void extraImports(Set<String> imports);
+
+    protected abstract InjectedDependencies createExecute(ProcessingEnvironment env, PrintWriter out);
+
+    private static TypeMirror resolvedJavaTypeType(ProcessingEnvironment env) {
+        return env.getElementUtils().getTypeElement("jdk.vm.ci.meta.ResolvedJavaType").asType();
+    }
+
+    static String getErasedType(TypeMirror type) {
+        switch (type.getKind()) {
+            case DECLARED:
+                DeclaredType declared = (DeclaredType) type;
+                TypeElement element = (TypeElement) declared.asElement();
+                return element.getQualifiedName().toString();
+            case TYPEVAR:
+                return getErasedType(((TypeVariable) type).getUpperBound());
+            case WILDCARD:
+                return getErasedType(((WildcardType) type).getExtendsBound());
+            case ARRAY:
+                return getErasedType(((ArrayType) type).getComponentType()) + "[]";
+            default:
+                return type.toString();
+        }
+    }
+
+    private void createPrivateMembers(PrintWriter out, InjectedDependencies deps, int idx) {
+        if (!deps.isEmpty()) {
+            out.printf("\n");
+            for (Dependency dep : deps) {
+                out.printf("        private final %s %s;\n", dep.type, dep.name);
+            }
+
+            out.printf("\n");
+            out.printf("        private Plugin%d(InjectionProvider injection) {\n", idx);
+            for (Dependency dep : deps) {
+                out.printf("            this.%s = %s;\n", dep.name, dep.inject(intrinsicMethod));
+            }
+            out.printf("        }\n");
+
+            needInjectionProvider = true;
+        }
+    }
+
+    protected static JavaKind getReturnKind(ExecutableElement method) {
+        switch (method.getReturnType().getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case SHORT:
+            case CHAR:
+            case INT:
+                return JavaKind.Int;
+            case LONG:
+                return JavaKind.Long;
+            case FLOAT:
+                return JavaKind.Float;
+            case DOUBLE:
+                return JavaKind.Double;
+            case VOID:
+                return JavaKind.Void;
+            case ARRAY:
+            case TYPEVAR:
+            case DECLARED:
+                return JavaKind.Object;
+            default:
+                throw new IllegalArgumentException(method.getReturnType().toString());
+        }
+    }
+
+    protected static void constantArgument(ProcessingEnvironment env, PrintWriter out, InjectedDependencies deps, int argIdx, TypeMirror type, int nodeIdx) {
+        out.printf("            %s arg%d;\n", type, argIdx);
+        out.printf("            if (args[%d].isConstant()) {\n", nodeIdx);
+        if (type.equals(resolvedJavaTypeType(env))) {
+            out.printf("                arg%d = %s.asJavaType(args[%d].asConstant());\n", argIdx, deps.use(WellKnownDependency.CONSTANT_REFLECTION), nodeIdx);
+        } else {
+            switch (type.getKind()) {
+                case BOOLEAN:
+                    out.printf("                arg%d = args[%d].asJavaConstant().asInt() != 0;\n", argIdx, nodeIdx);
+                    break;
+                case BYTE:
+                    out.printf("                arg%d = (byte) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx);
+                    break;
+                case CHAR:
+                    out.printf("                arg%d = (char) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx);
+                    break;
+                case SHORT:
+                    out.printf("                arg%d = (short) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx);
+                    break;
+                case INT:
+                    out.printf("                arg%d = args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx);
+                    break;
+                case LONG:
+                    out.printf("                arg%d = args[%d].asJavaConstant().asLong();\n", argIdx, nodeIdx);
+                    break;
+                case FLOAT:
+                    out.printf("                arg%d = args[%d].asJavaConstant().asFloat();\n", argIdx, nodeIdx);
+                    break;
+                case DOUBLE:
+                    out.printf("                arg%d = args[%d].asJavaConstant().asDouble();\n", argIdx, nodeIdx);
+                    break;
+                case DECLARED:
+                    out.printf("                arg%d = %s.asObject(%s.class, args[%d].asJavaConstant());\n", argIdx, deps.use(WellKnownDependency.SNIPPET_REFLECTION), type, nodeIdx);
+                    break;
+                default:
+                    throw new IllegalArgumentException();
+            }
+        }
+        out.printf("            } else {\n");
+        out.printf("                return false;\n");
+        out.printf("            }\n");
+    }
+}
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/InjectedDependencies.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/InjectedDependencies.java	Wed Dec 09 16:06:22 2015 +0100
@@ -67,7 +67,7 @@
 
         @Override
         public String inject(ExecutableElement inject) {
-            return String.format("injection.getReturnStamp(%s.class)", NodeIntrinsicPluginGenerator.getErasedType(inject.getReturnType()));
+            return String.format("injection.getReturnStamp(%s.class)", GeneratedPlugin.getErasedType(inject.getReturnType()));
         }
     }
 
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/MethodSubstitutionVerifier.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/MethodSubstitutionVerifier.java	Wed Dec 09 16:06:22 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,7 +67,7 @@
 
     @SuppressWarnings("unused")
     @Override
-    public void verify(Element element, AnnotationMirror annotation) {
+    public void verify(Element element, AnnotationMirror annotation, PluginGenerator generator) {
         if (element.getKind() != ElementKind.METHOD) {
             assert false : "Element is guaranteed to be a method.";
             return;
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicPluginGenerator.java	Tue Dec 08 20:47:09 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.replacements.verifier;
-
-import java.io.PrintWriter;
-import java.util.List;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.tools.Diagnostic.Kind;
-
-import jdk.vm.ci.meta.JavaKind;
-
-import com.oracle.graal.graph.Node.ConstantNodeParameter;
-import com.oracle.graal.graph.Node.InjectedNodeParameter;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency;
-
-/**
- * Create graph builder plugins for {@link NodeIntrinsic} methods.
- */
-public class NodeIntrinsicPluginGenerator extends PluginGenerator {
-
-    public NodeIntrinsicPluginGenerator(ProcessingEnvironment env) {
-        super(env);
-    }
-
-    private TypeMirror valueNodeType() {
-        return env.getElementUtils().getTypeElement("com.oracle.graal.nodes.ValueNode").asType();
-    }
-
-    @Override
-    protected String getBaseName() {
-        return "NodeIntrinsicFactory";
-    }
-
-    @Override
-    protected void createImports(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement targetMethod) {
-        if (targetMethod.getKind() == ElementKind.CONSTRUCTOR && getReturnKind(intrinsicMethod) != JavaKind.Void) {
-            out.printf("import jdk.vm.ci.meta.JavaKind;\n");
-        }
-        super.createImports(out, intrinsicMethod, targetMethod);
-    }
-
-    @Override
-    protected InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) {
-        InjectedDependencies deps = new InjectedDependencies();
-
-        List<? extends VariableElement> params = constructor.getParameters();
-
-        boolean customFactory = constructor.getKind() != ElementKind.CONSTRUCTOR;
-        int idx = customFactory ? 1 : 0;
-        for (; idx < params.size(); idx++) {
-            VariableElement param = params.get(idx);
-            if (param.getAnnotation(InjectedNodeParameter.class) == null) {
-                break;
-            }
-
-            out.printf("            %s arg%d = %s;\n", param.asType(), idx, deps.use(env, (DeclaredType) param.asType()));
-        }
-
-        for (int i = 0; i < signature.length; i++, idx++) {
-            if (intrinsicMethod.getParameters().get(i).getAnnotation(ConstantNodeParameter.class) != null) {
-                constantArgument(out, deps, idx, signature[i], i);
-            } else {
-                if (signature[i].equals(valueNodeType())) {
-                    out.printf("            ValueNode arg%d = args[%d];\n", idx, i);
-                } else {
-                    out.printf("            %s arg%d = (%s) args[%d];\n", signature[i], idx, signature[i], i);
-                }
-            }
-        }
-
-        if (customFactory) {
-            out.printf("            return %s.%s(b", constructor.getEnclosingElement(), constructor.getSimpleName());
-            for (int i = 1; i < idx; i++) {
-                out.printf(", arg%d", i);
-            }
-            out.printf(");\n");
-
-            if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) {
-                env.getMessager().printMessage(Kind.WARNING, "Ignoring setStampFromReturnType because a custom 'intrinsify' method is used.", intrinsicMethod);
-            }
-        } else {
-            out.printf("            %s node = new %s(", constructor.getEnclosingElement(), constructor.getEnclosingElement());
-            if (idx > 0) {
-                out.printf("arg0");
-                for (int i = 1; i < idx; i++) {
-                    out.printf(", arg%d", i);
-                }
-            }
-            out.printf(");\n");
-
-            if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) {
-                out.printf("            node.setStamp(%s);\n", deps.use(WellKnownDependency.RETURN_STAMP));
-            }
-
-            JavaKind returnKind = getReturnKind(intrinsicMethod);
-            if (returnKind == JavaKind.Void) {
-                out.printf("            b.add(node);\n");
-            } else {
-                out.printf("            b.addPush(JavaKind.%s, node);\n", returnKind.name());
-            }
-            out.printf("            return true;\n");
-        }
-
-        return deps;
-    }
-}
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java	Wed Dec 09 16:06:22 2015 +0100
@@ -77,11 +77,8 @@
         return env.getElementUtils().getTypeElement("com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext").asType();
     }
 
-    private final NodeIntrinsicPluginGenerator factoryGen;
-
     public NodeIntrinsicVerifier(ProcessingEnvironment env) {
         super(env);
-        factoryGen = new NodeIntrinsicPluginGenerator(env);
     }
 
     @Override
@@ -90,7 +87,7 @@
     }
 
     @Override
-    public void verify(Element element, AnnotationMirror annotation) {
+    public void verify(Element element, AnnotationMirror annotation, PluginGenerator generator) {
         if (element.getKind() != ElementKind.METHOD) {
             assert false : "Element is guaranteed to be a method.";
             return;
@@ -124,7 +121,7 @@
         TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod);
         ExecutableElement custom = findCustomIntrinsifyMethod(nodeClass, constructorSignature);
         if (custom != null) {
-            factoryGen.createPluginFactory(intrinsicMethod, custom, constructorSignature);
+            generator.addPlugin(new GeneratedNodeIntrinsicPlugin.CustomFactoryPlugin(intrinsicMethod, custom, constructorSignature));
         } else {
             if (isNodeType(nodeClass)) {
                 if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) {
@@ -137,7 +134,7 @@
 
                     ExecutableElement constructor = findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation);
                     if (constructor != null) {
-                        factoryGen.createPluginFactory(intrinsicMethod, constructor, constructorSignature);
+                        generator.addPlugin(new GeneratedNodeIntrinsicPlugin.ConstructorPlugin(intrinsicMethod, constructor, constructorSignature));
                     }
                 }
             } else {
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java	Wed Dec 09 16:06:22 2015 +0100
@@ -24,38 +24,42 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
 import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVariable;
-import javax.lang.model.type.WildcardType;
 import javax.tools.Diagnostic;
 import javax.tools.JavaFileObject;
 
-import jdk.vm.ci.meta.JavaKind;
-
-import com.oracle.graal.replacements.verifier.InjectedDependencies.Dependency;
-import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency;
+public class PluginGenerator {
 
-public abstract class PluginGenerator {
+    private final Map<Element, List<GeneratedPlugin>> plugins;
 
-    protected final ProcessingEnvironment env;
-
-    public PluginGenerator(ProcessingEnvironment env) {
-        this.env = env;
+    public PluginGenerator() {
+        this.plugins = new HashMap<>();
     }
 
-    private TypeMirror resolvedJavaTypeType() {
-        return env.getElementUtils().getTypeElement("jdk.vm.ci.meta.ResolvedJavaType").asType();
+    public void addPlugin(GeneratedPlugin plugin) {
+        Element topLevel = getTopLevelClass(plugin.intrinsicMethod);
+        List<GeneratedPlugin> list = plugins.get(topLevel);
+        if (list == null) {
+            list = new ArrayList<>();
+            plugins.put(topLevel, list);
+        }
+        list.add(plugin);
+    }
+
+    public void generateAll(ProcessingEnvironment env) {
+        for (Entry<Element, List<GeneratedPlugin>> entry : plugins.entrySet()) {
+            createPluginFactory(env, entry.getKey(), entry.getValue());
+        }
     }
 
     private static Element getTopLevelClass(Element element) {
@@ -68,84 +72,30 @@
         return prev;
     }
 
-    private static void mkClassName(StringBuilder ret, Element cls) {
-        Element enclosingClass = cls.getEnclosingElement();
-        if (enclosingClass.getKind() == ElementKind.CLASS || enclosingClass.getKind() == ElementKind.INTERFACE) {
-            mkClassName(ret, enclosingClass);
-            ret.append('_');
-        }
-        ret.append(cls.getSimpleName());
-    }
-
-    static String getErasedType(TypeMirror type) {
-        switch (type.getKind()) {
-            case DECLARED:
-                DeclaredType declared = (DeclaredType) type;
-                TypeElement element = (TypeElement) declared.asElement();
-                return element.getQualifiedName().toString();
-            case TYPEVAR:
-                return getErasedType(((TypeVariable) type).getUpperBound());
-            case WILDCARD:
-                return getErasedType(((WildcardType) type).getExtendsBound());
-            case ARRAY:
-                return getErasedType(((ArrayType) type).getComponentType()) + "[]";
-            default:
-                return type.toString();
-        }
-    }
-
-    protected abstract String getBaseName();
-
-    private String mkFactoryClassName(ExecutableElement intrinsicMethod) {
-        StringBuilder ret = new StringBuilder();
-        ret.append(getBaseName());
-        ret.append('_');
-        mkClassName(ret, intrinsicMethod.getEnclosingElement());
-        ret.append('_');
-        ret.append(intrinsicMethod.getSimpleName());
-        if (!intrinsicMethod.getParameters().isEmpty()) {
-            ret.append('_');
-            ret.append(Integer.toHexString(APHotSpotSignature.toSignature(intrinsicMethod).hashCode()));
-        }
-        return ret.toString();
-    }
-
-    void createPluginFactory(ExecutableElement intrinsicMethod, ExecutableElement targetMethod, TypeMirror[] constructorSignature) {
-        Element declaringClass = intrinsicMethod.getEnclosingElement();
-        Element topLevelClass = getTopLevelClass(declaringClass);
+    private static void createPluginFactory(ProcessingEnvironment env, Element topLevelClass, List<GeneratedPlugin> plugins) {
         PackageElement pkg = (PackageElement) topLevelClass.getEnclosingElement();
 
-        String genClassName = mkFactoryClassName(intrinsicMethod);
+        String genClassName = "PluginFactory_" + topLevelClass.getSimpleName();
 
         try {
-            JavaFileObject factory = env.getFiler().createSourceFile(pkg.getQualifiedName() + "." + genClassName, topLevelClass, declaringClass, intrinsicMethod);
+            JavaFileObject factory = env.getFiler().createSourceFile(pkg.getQualifiedName() + "." + genClassName, topLevelClass);
             try (PrintWriter out = new PrintWriter(factory.openWriter())) {
                 out.printf("// CheckStyle: stop header check\n");
                 out.printf("// CheckStyle: stop line length check\n");
                 out.printf("// GENERATED CONTENT - DO NOT EDIT\n");
                 out.printf("package %s;\n", pkg.getQualifiedName());
                 out.printf("\n");
-                createImports(out, intrinsicMethod, targetMethod);
+                createImports(out, plugins);
                 out.printf("\n");
                 out.printf("@ServiceProvider(NodeIntrinsicPluginFactory.class)\n");
                 out.printf("public class %s implements NodeIntrinsicPluginFactory {\n", genClassName);
-                out.printf("\n");
-                out.printf("    private static final class Plugin extends GeneratedInvocationPlugin {\n");
+                int idx = 0;
+                for (GeneratedPlugin plugin : plugins) {
+                    out.printf("\n");
+                    plugin.generate(env, out, idx++);
+                }
                 out.printf("\n");
-
-                out.printf("        @Override\n");
-                out.printf("        public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) {\n");
-                out.printf("            if (!b.parsingIntrinsic()) {\n");
-                out.printf("                return false;\n");
-                out.printf("            }\n");
-                InjectedDependencies deps = createExecute(out, intrinsicMethod, targetMethod, constructorSignature);
-                out.printf("        }\n");
-
-                createPrivateMembers(out, intrinsicMethod, deps);
-
-                out.printf("    }\n");
-                out.printf("\n");
-                createPluginFactoryMethod(out, intrinsicMethod, deps);
+                createPluginFactoryMethod(out, plugins);
                 out.printf("}\n");
             }
         } catch (IOException e) {
@@ -153,9 +103,7 @@
         }
     }
 
-    protected abstract InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature);
-
-    protected void createImports(PrintWriter out, @SuppressWarnings("unused") ExecutableElement intrinsicMethod, @SuppressWarnings("unused") ExecutableElement targetMethod) {
+    protected static void createImports(PrintWriter out, List<GeneratedPlugin> plugins) {
         out.printf("import jdk.vm.ci.meta.ResolvedJavaMethod;\n");
         out.printf("import jdk.vm.ci.service.ServiceProvider;\n");
         out.printf("\n");
@@ -165,103 +113,25 @@
         out.printf("import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin;\n");
         out.printf("import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins;\n");
         out.printf("import com.oracle.graal.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;\n");
-    }
 
-    private static void createPrivateMembers(PrintWriter out, ExecutableElement intrinsicMethod, InjectedDependencies deps) {
-        if (!deps.isEmpty()) {
+        HashSet<String> extra = new HashSet<>();
+        for (GeneratedPlugin plugin : plugins) {
+            plugin.extraImports(extra);
+        }
+        if (!extra.isEmpty()) {
             out.printf("\n");
-            for (Dependency dep : deps) {
-                out.printf("        private final %s %s;\n", dep.type, dep.name);
+            for (String i : extra) {
+                out.printf("import %s;\n", i);
             }
-
-            out.printf("\n");
-            out.printf("        private Plugin(InjectionProvider injection) {\n");
-            for (Dependency dep : deps) {
-                out.printf("            this.%s = %s;\n", dep.name, dep.inject(intrinsicMethod));
-            }
-            out.printf("        }\n");
         }
     }
 
-    private static void createPluginFactoryMethod(PrintWriter out, ExecutableElement intrinsicMethod, InjectedDependencies deps) {
-        out.printf("    public void registerPlugin(InvocationPlugins plugins, InjectionProvider injection) {\n");
-        out.printf("        Plugin plugin = new Plugin(%s);\n", deps.isEmpty() ? "" : "injection");
-        out.printf("        plugins.register(plugin, %s.class, \"%s\"", intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName());
-        if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) {
-            out.printf(", InvocationPlugin.Receiver.class");
+    private static void createPluginFactoryMethod(PrintWriter out, List<GeneratedPlugin> plugins) {
+        out.printf("    public void registerPlugins(InvocationPlugins plugins, InjectionProvider injection) {\n");
+        int idx = 0;
+        for (GeneratedPlugin plugin : plugins) {
+            plugin.register(out, idx++);
         }
-        for (VariableElement arg : intrinsicMethod.getParameters()) {
-            out.printf(", %s.class", getErasedType(arg.asType()));
-        }
-        out.printf(");\n");
         out.printf("    }\n");
     }
-
-    protected static JavaKind getReturnKind(ExecutableElement method) {
-        switch (method.getReturnType().getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case SHORT:
-            case CHAR:
-            case INT:
-                return JavaKind.Int;
-            case LONG:
-                return JavaKind.Long;
-            case FLOAT:
-                return JavaKind.Float;
-            case DOUBLE:
-                return JavaKind.Double;
-            case VOID:
-                return JavaKind.Void;
-            case ARRAY:
-            case TYPEVAR:
-            case DECLARED:
-                return JavaKind.Object;
-            default:
-                throw new IllegalArgumentException(method.getReturnType().toString());
-        }
-    }
-
-    protected void constantArgument(PrintWriter out, InjectedDependencies deps, int argIdx, TypeMirror type, int nodeIdx) {
-        out.printf("            %s arg%d;\n", type, argIdx);
-        out.printf("            if (args[%d].isConstant()) {\n", nodeIdx);
-        if (type.equals(resolvedJavaTypeType())) {
-            out.printf("                arg%d = %s.asJavaType(args[%d].asConstant());\n", argIdx, deps.use(WellKnownDependency.CONSTANT_REFLECTION), nodeIdx);
-        } else {
-            switch (type.getKind()) {
-                case BOOLEAN:
-                    out.printf("                arg%d = args[%d].asJavaConstant().asInt() != 0;\n", argIdx, nodeIdx);
-                    break;
-                case BYTE:
-                    out.printf("                arg%d = (byte) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx);
-                    break;
-                case CHAR:
-                    out.printf("                arg%d = (char) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx);
-                    break;
-                case SHORT:
-                    out.printf("                arg%d = (short) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx);
-                    break;
-                case INT:
-                    out.printf("                arg%d = args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx);
-                    break;
-                case LONG:
-                    out.printf("                arg%d = args[%d].asJavaConstant().asLong();\n", argIdx, nodeIdx);
-                    break;
-                case FLOAT:
-                    out.printf("                arg%d = args[%d].asJavaConstant().asFloat();\n", argIdx, nodeIdx);
-                    break;
-                case DOUBLE:
-                    out.printf("                arg%d = args[%d].asJavaConstant().asDouble();\n", argIdx, nodeIdx);
-                    break;
-                case DECLARED:
-                    out.printf("                arg%d = %s.asObject(%s.class, args[%d].asJavaConstant());\n", argIdx, deps.use(WellKnownDependency.SNIPPET_REFLECTION), type, nodeIdx);
-                    break;
-                default:
-                    throw new IllegalArgumentException();
-            }
-        }
-        out.printf("            } else {\n");
-        out.printf("                return false;\n");
-        out.printf("            }\n");
-    }
 }
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java	Tue Dec 08 20:47:09 2015 -0800
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java	Wed Dec 09 16:06:22 2015 +0100
@@ -49,6 +49,7 @@
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (!roundEnv.processingOver()) {
+            PluginGenerator generator = new PluginGenerator();
             for (AbstractVerifier verifier : getVerifiers()) {
                 Class<? extends Annotation> annotationClass = verifier.getAnnotationClass();
                 for (Element e : roundEnv.getElementsAnnotatedWith(annotationClass)) {
@@ -57,9 +58,11 @@
                         assert false : "Annotation mirror always expected.";
                         continue;
                     }
-                    verifier.verify(e, annotationMirror);
+                    verifier.verify(e, annotationMirror, generator);
                 }
             }
+
+            generator.generateAll(processingEnv);
         }
         return false;
     }
@@ -84,7 +87,7 @@
             verifiers.add(new ClassSubstitutionVerifier(this.processingEnv));
             verifiers.add(new MethodSubstitutionVerifier(this.processingEnv));
             verifiers.add(new NodeIntrinsicVerifier(this.processingEnv));
-            verifiers.add(new FoldPluginGenerator(this.processingEnv).getVerifier());
+            verifiers.add(new FoldVerifier(this.processingEnv));
         }
         return verifiers;
     }