changeset 19390:7f4201b633e7

renamed GraphBuilderPlugins to InvocationPlugins and consolidated it into GraphBuilderConfiguration; moved declaration of GraphBuilderPlugin sub-interfaces into GraphBuilderPlugin
author Doug Simon <doug.simon@oracle.com>
date Mon, 16 Feb 2015 11:57:43 +0100
parents e6d78307bdc9
children aff26d9a9fb6
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java
diffstat 18 files changed, 485 insertions(+), 497 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Feb 16 11:57:43 2015 +0100
@@ -800,9 +800,8 @@
     protected PhaseSuite<HighTierContext> getCustomGraphBuilderSuite(GraphBuilderConfiguration gbConf) {
         PhaseSuite<HighTierContext> suite = getDefaultGraphBuilderSuite().copy();
         ListIterator<BasePhase<? super HighTierContext>> iterator = suite.findPhase(GraphBuilderPhase.class);
-        GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous();
         iterator.remove();
-        iterator.add(new GraphBuilderPhase(gbConf, graphBuilderPhase.getGraphBuilderPlugins()));
+        iterator.add(new GraphBuilderPhase(gbConf));
         return suite;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Mon Feb 16 11:57:43 2015 +0100
@@ -68,7 +68,7 @@
 
         try (InitTimer st = timer("graphBuilderPlugins.initialize")) {
             GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous();
-            GraphBuilderPlugins plugins = phase.getGraphBuilderPlugins();
+            InvocationPlugins plugins = phase.getGraphBuilderConfig().getInvocationPlugins();
             registerGraphBuilderPlugins(providers.getMetaAccess(), plugins);
         }
 
@@ -101,7 +101,7 @@
         }
     }
 
-    protected void registerGraphBuilderPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+    protected void registerGraphBuilderPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
         StandardGraphBuilderPlugins.registerPlugins(metaAccess, plugins);
         HotSpotGraphBuilderPlugins.registerPlugins(metaAccess, plugins);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Mon Feb 16 11:57:43 2015 +0100
@@ -28,9 +28,9 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.java.*;
-import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin;
-import com.oracle.graal.java.GraphBuilderPlugins.Registration;
-import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver;
+import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin;
+import com.oracle.graal.java.InvocationPlugins.Registration;
+import com.oracle.graal.java.InvocationPlugins.Registration.Receiver;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -42,7 +42,7 @@
  * Provider of HotSpot specific {@link GraphBuilderPlugin}s.
  */
 public class HotSpotGraphBuilderPlugins {
-    public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+    public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
         // Object.class
         Registration r = new Registration(plugins, metaAccess, Object.class);
         r.register1("getClass", Receiver.class, new InvocationPlugin() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Mon Feb 16 11:57:43 2015 +0100
@@ -31,8 +31,9 @@
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode;
-import com.oracle.graal.java.GraphBuilderPlugins.InlineInvokePlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin;
 import com.oracle.graal.lir.phases.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.options.DerivedOptionValue.OptionSupplier;
 import com.oracle.graal.phases.*;
@@ -106,9 +107,12 @@
         PhaseSuite<HighTierContext> suite = new PhaseSuite<>();
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault();
         config.setInlineInvokePlugin(new InlineInvokePlugin() {
-            public boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth) {
-                return GraalOptions.InlineDuringParsing.getValue() && method.getCode().length <= GraalOptions.TrivialInliningSize.getValue() &&
-                                depth < GraalOptions.InlineDuringParsingMaxDepth.getValue();
+            public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType, int depth) {
+                if (GraalOptions.InlineDuringParsing.getValue() && method.getCode().length <= GraalOptions.TrivialInliningSize.getValue() &&
+                                depth < GraalOptions.InlineDuringParsingMaxDepth.getValue()) {
+                    return method;
+                }
+                return null;
             }
         });
         suite.appendPhase(new GraphBuilderPhase(config));
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Feb 16 11:57:43 2015 +0100
@@ -37,6 +37,8 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
+import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
@@ -699,7 +701,7 @@
         Kind kind = field.getKind();
         T receiver = frameState.apop();
         if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
-            GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin();
+            LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin();
             if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ValueNode) receiver, (ResolvedJavaField) field)) {
                 appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field));
             }
@@ -748,7 +750,7 @@
     private void genGetStatic(JavaField field) {
         Kind kind = field.getKind();
         if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
-            GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin();
+            InvocationPlugin.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin();
             if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) {
                 appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field));
             }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java	Sun Feb 15 22:38:29 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +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.java;
-
-import java.util.*;
-import java.util.stream.*;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * Default implementation of {@link GraphBuilderPlugins} that uses a map.
- */
-public class DefaultGraphBuilderPlugins implements GraphBuilderPlugins {
-
-    private final Map<ResolvedJavaMethod, InvocationPlugin> plugins = new HashMap<>();
-
-    /**
-     * Registers an invocation plugin for a given method. There must be no plugin currently
-     * registered for {@code method}.
-     */
-    public void register(ResolvedJavaMethod method, InvocationPlugin plugin) {
-        assert InvocationPluginChecker.check(method, plugin);
-        GraphBuilderPlugin oldValue = plugins.put(method, plugin);
-        // System.out.println("registered: " + plugin);
-        assert oldValue == null;
-    }
-
-    /**
-     * Gets the plugin for a given method.
-     *
-     * @param method the method to lookup
-     * @return the plugin associated with {@code method} or {@code null} if none exists
-     */
-    public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) {
-        return plugins.get(method);
-    }
-
-    public DefaultGraphBuilderPlugins copy() {
-        DefaultGraphBuilderPlugins result = new DefaultGraphBuilderPlugins();
-        result.plugins.putAll(plugins);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", "));
-    }
-}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java	Mon Feb 16 11:57:43 2015 +0100
@@ -24,15 +24,15 @@
 
 import com.oracle.graal.api.directives.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin;
-import com.oracle.graal.java.GraphBuilderPlugins.Registration;
+import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin;
+import com.oracle.graal.java.InvocationPlugins.Registration;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.extended.*;
 
 public class GraalDirectivePlugins {
 
-    public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+    public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
         Registration r = new Registration(plugins, metaAccess, GraalDirectives.class);
         r.register0("deoptimize", new InvocationPlugin() {
             public boolean apply(GraphBuilderContext builder) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Mon Feb 16 11:57:43 2015 +0100
@@ -26,6 +26,10 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin;
 import com.oracle.graal.nodes.*;
 
 public class GraphBuilderConfiguration {
@@ -36,10 +40,11 @@
     private final ResolvedJavaType[] skippedExceptionTypes;
     private final DebugInfoMode debugInfoMode;
     private final boolean doLivenessAnalysis;
-    private GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin;
-    private GraphBuilderPlugins.ParameterPlugin parameterPlugin;
-    private GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin;
-    private GraphBuilderPlugins.LoopExplosionPlugin loopExplosionPlugin;
+    private final InvocationPlugins invocationPlugins = new InvocationPlugins();
+    private LoadFieldPlugin loadFieldPlugin;
+    private ParameterPlugin parameterPlugin;
+    private InlineInvokePlugin inlineInvokePlugin;
+    private LoopExplosionPlugin loopExplosionPlugin;
 
     public static enum DebugInfoMode {
         SafePointsOnly,
@@ -96,11 +101,15 @@
         return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis);
     }
 
-    public GraphBuilderPlugins.LoadFieldPlugin getLoadFieldPlugin() {
+    public InvocationPlugins getInvocationPlugins() {
+        return invocationPlugins;
+    }
+
+    public LoadFieldPlugin getLoadFieldPlugin() {
         return loadFieldPlugin;
     }
 
-    public void setLoadFieldPlugin(GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin) {
+    public void setLoadFieldPlugin(LoadFieldPlugin loadFieldPlugin) {
         this.loadFieldPlugin = loadFieldPlugin;
     }
 
@@ -153,27 +162,27 @@
         return eagerResolving;
     }
 
-    public GraphBuilderPlugins.ParameterPlugin getParameterPlugin() {
+    public ParameterPlugin getParameterPlugin() {
         return parameterPlugin;
     }
 
-    public void setParameterPlugin(GraphBuilderPlugins.ParameterPlugin parameterPlugin) {
+    public void setParameterPlugin(ParameterPlugin parameterPlugin) {
         this.parameterPlugin = parameterPlugin;
     }
 
-    public GraphBuilderPlugins.InlineInvokePlugin getInlineInvokePlugin() {
+    public InlineInvokePlugin getInlineInvokePlugin() {
         return inlineInvokePlugin;
     }
 
-    public void setInlineInvokePlugin(GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin) {
+    public void setInlineInvokePlugin(InlineInvokePlugin inlineInvokePlugin) {
         this.inlineInvokePlugin = inlineInvokePlugin;
     }
 
-    public GraphBuilderPlugins.LoopExplosionPlugin getLoopExplosionPlugin() {
+    public LoopExplosionPlugin getLoopExplosionPlugin() {
         return loopExplosionPlugin;
     }
 
-    public void setLoopExplosionPlugin(GraphBuilderPlugins.LoopExplosionPlugin loopExplosionPlugin) {
+    public void setLoopExplosionPlugin(LoopExplosionPlugin loopExplosionPlugin) {
         this.loopExplosionPlugin = loopExplosionPlugin;
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Feb 16 11:57:43 2015 +0100
@@ -45,9 +45,9 @@
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock;
 import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
-import com.oracle.graal.java.GraphBuilderPlugins.InlineInvokePlugin;
-import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin;
-import com.oracle.graal.java.GraphBuilderPlugins.LoopExplosionPlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.calc.*;
@@ -65,30 +65,20 @@
 public class GraphBuilderPhase extends BasePhase<HighTierContext> {
 
     private final GraphBuilderConfiguration graphBuilderConfig;
-    private final GraphBuilderPlugins graphBuilderPlugins;
 
     public GraphBuilderPhase(GraphBuilderConfiguration config) {
-        this(config, new DefaultGraphBuilderPlugins());
-    }
-
-    public GraphBuilderPhase(GraphBuilderConfiguration config, GraphBuilderPlugins graphBuilderPlugins) {
         this.graphBuilderConfig = config;
-        this.graphBuilderPlugins = graphBuilderPlugins;
     }
 
     @Override
     protected void run(StructuredGraph graph, HighTierContext context) {
-        new Instance(context.getMetaAccess(), context.getStampProvider(), null, null, context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins, context.getOptimisticOptimizations()).run(graph);
+        new Instance(context.getMetaAccess(), context.getStampProvider(), null, null, context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph);
     }
 
     public GraphBuilderConfiguration getGraphBuilderConfig() {
         return graphBuilderConfig;
     }
 
-    public GraphBuilderPlugins getGraphBuilderPlugins() {
-        return graphBuilderPlugins;
-    }
-
     public static class Instance extends Phase {
 
         protected StructuredGraph currentGraph;
@@ -98,7 +88,6 @@
         private ResolvedJavaMethod rootMethod;
 
         private final GraphBuilderConfiguration graphBuilderConfig;
-        private final GraphBuilderPlugins graphBuilderPlugins;
         private final OptimisticOptimizations optimisticOpts;
         private final StampProvider stampProvider;
         private final ConstantReflectionProvider constantReflection;
@@ -114,12 +103,11 @@
         }
 
         public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, Replacements replacements,
-                        ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) {
+                        ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
             this.graphBuilderConfig = graphBuilderConfig;
             this.optimisticOpts = optimisticOpts;
             this.metaAccess = metaAccess;
             this.stampProvider = stampProvider;
-            this.graphBuilderPlugins = graphBuilderPlugins;
             this.constantReflection = constantReflection;
             this.snippetReflectionProvider = snippetReflectionProvider;
             this.replacements = replacements;
@@ -128,7 +116,7 @@
 
         public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig,
                         OptimisticOptimizations optimisticOpts) {
-            this(metaAccess, stampProvider, null, null, constantReflection, graphBuilderConfig, null, optimisticOpts);
+            this(metaAccess, stampProvider, null, null, constantReflection, graphBuilderConfig, optimisticOpts);
         }
 
         @Override
@@ -866,37 +854,39 @@
                     }
                 }
 
-                if (graphBuilderPlugins != null) {
-                    if (tryUsingInvocationPlugin(args, targetMethod, resultType)) {
+                if (tryUsingInvocationPlugin(args, targetMethod, resultType)) {
+                    if (GraalOptions.TraceInlineDuringParsing.getValue()) {
+                        for (int i = 0; i < this.currentDepth; ++i) {
+                            TTY.print(' ');
+                        }
+                        TTY.println("Used invocation plugin for " + targetMethod);
+                    }
+                    return;
+                }
+
+                InlineInvokePlugin inlineInvokePlugin = graphBuilderConfig.getInlineInvokePlugin();
+                if (inlineInvokePlugin != null && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes() &&
+                                (replacements == null || (replacements.getMethodSubstitution(targetMethod) == null && replacements.getMacroSubstitution(targetMethod) == null))) {
+
+                    ResolvedJavaMethod inlinedMethod = inlineInvokePlugin.getInlinedMethod(this, targetMethod, args, returnType, currentDepth);
+                    if (inlinedMethod != null) {
                         if (GraalOptions.TraceInlineDuringParsing.getValue()) {
+                            int bci = this.bci();
                             for (int i = 0; i < this.currentDepth; ++i) {
                                 TTY.print(' ');
                             }
-                            TTY.println("Used invocation plugin for " + targetMethod);
+                            StackTraceElement stackTraceElement = this.method.asStackTraceElement(bci);
+                            String s = String.format("%s (%s:%d)", method.getName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber());
+                            TTY.print(s);
+                            TTY.println(" inlining call " + targetMethod.getName());
                         }
+
+                        ResolvedJavaMethod inlinedTargetMethod = inlinedMethod;
+                        parseAndInlineCallee(inlinedTargetMethod, args);
+                        inlineInvokePlugin.postInline(inlinedTargetMethod);
                         return;
                     }
                 }
-                InlineInvokePlugin inlineInvokePlugin = graphBuilderConfig.getInlineInvokePlugin();
-                if (inlineInvokePlugin != null && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes() &&
-                                (replacements == null || (replacements.getMethodSubstitution(targetMethod) == null && replacements.getMacroSubstitution(targetMethod) == null)) &&
-                                inlineInvokePlugin.shouldInlineInvoke(targetMethod, currentDepth)) {
-                    if (GraalOptions.TraceInlineDuringParsing.getValue()) {
-                        int bci = this.bci();
-                        for (int i = 0; i < this.currentDepth; ++i) {
-                            TTY.print(' ');
-                        }
-                        StackTraceElement stackTraceElement = this.method.asStackTraceElement(bci);
-                        String s = String.format("%s (%s:%d)", method.getName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber());
-                        TTY.print(s);
-                        TTY.println(" inlining call " + targetMethod.getName());
-                    }
-
-                    ResolvedJavaMethod inlinedTargetMethod = inlineInvokePlugin.inlinedMethod(this, targetMethod, args);
-                    parseAndInlineCallee(inlinedTargetMethod, args);
-                    inlineInvokePlugin.postInline(inlinedTargetMethod);
-                    return;
-                }
 
                 MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType));
 
@@ -913,7 +903,7 @@
             }
 
             private boolean tryUsingInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) {
-                InvocationPlugin plugin = graphBuilderPlugins.lookupInvocation(targetMethod);
+                InvocationPlugin plugin = graphBuilderConfig.getInvocationPlugins().lookupInvocation(targetMethod);
                 if (plugin != null) {
                     int beforeStackSize = frameState.stackSize;
                     boolean needsNullCheck = !targetMethod.isStatic() && !StampTool.isPointerNonNull(args[0].stamp());
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java	Mon Feb 16 11:57:43 2015 +0100
@@ -22,13 +22,141 @@
  */
 package com.oracle.graal.java;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
 /**
  * Marker interface for graph builder plugins.
- *
- * Concrete plugins implement one of the sub-interfaces of this interface.
- *
- * @see GraphBuilderPlugins
- * @see GraphBuilderPlugins.Registration
  */
 public interface GraphBuilderPlugin {
+
+    public interface LoadFieldPlugin extends GraphBuilderPlugin {
+        @SuppressWarnings("unused")
+        default boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) {
+            return false;
+        }
+
+        @SuppressWarnings("unused")
+        default boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) {
+            return false;
+        }
+
+        default boolean tryConstantFold(GraphBuilderContext builder, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ResolvedJavaField field, JavaConstant asJavaConstant) {
+            JavaConstant result = constantReflection.readConstantFieldValue(field, asJavaConstant);
+            if (result != null) {
+                ConstantNode constantNode = builder.append(ConstantNode.forConstant(result, metaAccess));
+                builder.push(constantNode.getKind().getStackKind(), constantNode);
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Plugin for customizing how the graph builder handles a CHECKCAST instruction in the context
+     * of the instruction that consumes it from the stack.
+     */
+    public interface CheckCastPlugin extends GraphBuilderPlugin {
+        boolean apply(GraphBuilderContext builder, ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck);
+    }
+
+    public interface InlineInvokePlugin extends GraphBuilderPlugin {
+
+        default void postInline(@SuppressWarnings("unused") ResolvedJavaMethod inlinedTargetMethod) {
+
+        }
+
+        ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType, int depth);
+    }
+
+    public interface LoopExplosionPlugin extends GraphBuilderPlugin {
+        boolean shouldExplodeLoops(ResolvedJavaMethod method);
+    }
+
+    public interface ParameterPlugin extends GraphBuilderPlugin {
+        FloatingNode interceptParameter(int index);
+    }
+
+    /**
+     * Plugin for handling an invocation based on the annotations of the invoked method.
+     */
+    public interface AnnotatedInvocationPlugin extends GraphBuilderPlugin {
+        /**
+         * Executes this plugin for an invocation of a given method with a given set of arguments.
+         *
+         * @return {@code true} if this plugin handled the invocation, {@code false} if not
+         */
+        boolean apply(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args);
+    }
+
+    /**
+     * Plugin for handling a specific method invocation.
+     */
+    public interface InvocationPlugin extends GraphBuilderPlugin {
+        /**
+         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
+         */
+        default boolean apply(GraphBuilderContext builder) {
+            throw invalidHandler(builder);
+        }
+
+        /**
+         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
+         */
+        default boolean apply(GraphBuilderContext builder, ValueNode arg) {
+            throw invalidHandler(builder, arg);
+        }
+
+        /**
+         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
+         */
+        default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) {
+            throw invalidHandler(builder, arg1, arg2);
+        }
+
+        /**
+         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
+         */
+        default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
+            throw invalidHandler(builder, arg1, arg2, arg3);
+        }
+
+        /**
+         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
+         */
+        default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) {
+            throw invalidHandler(builder, arg1, arg2, arg3, arg4);
+        }
+
+        /**
+         * Executes a given plugin against a set of invocation arguments by dispatching to the
+         * plugin's {@code apply(...)} method that matches the number of arguments.
+         *
+         * @return {@code true} if the plugin handled the invocation, {@code false} if the graph
+         *         builder should process the invoke further (e.g., by inlining it or creating an
+         *         {@link Invoke} node). A plugin that does not handle an invocation must not modify
+         *         the graph being constructed.
+         */
+        static boolean execute(GraphBuilderContext builder, InvocationPlugin plugin, ValueNode[] args) {
+            if (args.length == 0) {
+                return plugin.apply(builder);
+            } else if (args.length == 1) {
+                return plugin.apply(builder, args[0]);
+            } else if (args.length == 2) {
+                return plugin.apply(builder, args[0], args[1]);
+            } else if (args.length == 3) {
+                return plugin.apply(builder, args[0], args[1], args[2]);
+            } else if (args.length == 4) {
+                return plugin.apply(builder, args[0], args[1], args[2], args[3]);
+            } else {
+                throw plugin.invalidHandler(builder, args);
+            }
+        }
+
+        default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext builder, ValueNode... args) {
+            return new GraalInternalError("Invocation plugin %s does not handle invocations with %d arguments", getClass().getSimpleName(), args.length);
+        }
+    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Sun Feb 15 22:38:29 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +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.java;
-
-import static java.lang.String.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-
-/**
- * Interface for managing a set of graph builder {@link GraphBuilderPlugin}s.
- */
-public interface GraphBuilderPlugins {
-
-    public interface LoadFieldPlugin extends GraphBuilderPlugin {
-        @SuppressWarnings("unused")
-        default boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) {
-            return false;
-        }
-
-        @SuppressWarnings("unused")
-        default boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) {
-            return false;
-        }
-    }
-
-    public interface ParameterPlugin extends GraphBuilderPlugin {
-        FloatingNode interceptParameter(int index);
-    }
-
-    public interface InlineInvokePlugin extends GraphBuilderPlugin {
-        default ResolvedJavaMethod inlinedMethod(@SuppressWarnings("unused") GraphBuilderContext builder, ResolvedJavaMethod original, @SuppressWarnings("unused") ValueNode[] arguments) {
-            return original;
-        }
-
-        boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth);
-
-        default void postInline(@SuppressWarnings("unused") ResolvedJavaMethod inlinedTargetMethod) {
-
-        }
-    }
-
-    public interface LoopExplosionPlugin extends GraphBuilderPlugin {
-        boolean shouldExplodeLoops(ResolvedJavaMethod method);
-    }
-
-    /**
-     * Plugin for handling a method invocation.
-     */
-    public interface InvocationPlugin extends GraphBuilderPlugin {
-        /**
-         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
-         */
-        default boolean apply(GraphBuilderContext builder) {
-            throw invalidHandler(builder);
-        }
-
-        /**
-         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
-         */
-        default boolean apply(GraphBuilderContext builder, ValueNode arg) {
-            throw invalidHandler(builder, arg);
-        }
-
-        /**
-         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
-         */
-        default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) {
-            throw invalidHandler(builder, arg1, arg2);
-        }
-
-        /**
-         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
-         */
-        default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
-            throw invalidHandler(builder, arg1, arg2, arg3);
-        }
-
-        /**
-         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
-         */
-        default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) {
-            throw invalidHandler(builder, arg1, arg2, arg3, arg4);
-        }
-
-        /**
-         * Executes a given plugin against a set of invocation arguments by dispatching to the
-         * plugin's {@code apply(...)} method that matches the number of arguments.
-         *
-         * @return {@code true} if the plugin handled the invocation, {@code false} if the graph
-         *         builder should process the invoke further (e.g., by inlining it or creating an
-         *         {@link Invoke} node). A plugin that does not handle an invocation must not modify
-         *         the graph being constructed.
-         */
-        static boolean execute(GraphBuilderContext builder, InvocationPlugin plugin, ValueNode[] args) {
-            if (args.length == 0) {
-                return plugin.apply(builder);
-            } else if (args.length == 1) {
-                return plugin.apply(builder, args[0]);
-            } else if (args.length == 2) {
-                return plugin.apply(builder, args[0], args[1]);
-            } else if (args.length == 3) {
-                return plugin.apply(builder, args[0], args[1], args[2]);
-            } else if (args.length == 4) {
-                return plugin.apply(builder, args[0], args[1], args[2], args[3]);
-            } else {
-                throw plugin.invalidHandler(builder, args);
-            }
-        }
-
-        default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext builder, ValueNode... args) {
-            return new GraalInternalError("Invocation plugin %s does not handle invocations with %d arguments", getClass().getSimpleName(), args.length);
-        }
-    }
-
-    /**
-     * Utility for {@linkplain GraphBuilderPlugins#register(ResolvedJavaMethod, InvocationPlugin)
-     * registration} of plugins.
-     */
-    public static class Registration {
-
-        /**
-         * Sentinel class for use with {@link Registration#register1},
-         * {@link Registration#register2} or {@link Registration#register3} to denote the receiver
-         * argument for a non-static method.
-         */
-        public static final class Receiver {
-            private Receiver() {
-                throw GraalInternalError.shouldNotReachHere();
-            }
-        }
-
-        private final GraphBuilderPlugins plugins;
-        private final MetaAccessProvider metaAccess;
-        private final Class<?> declaringClass;
-
-        /**
-         * Creates an object for registering plugins for methods declared by a given class.
-         *
-         * @param plugins where to register the plugins
-         * @param metaAccess used to resolve classes and methods
-         * @param declaringClass the class declaring the methods for which plugins will be
-         *            registered via this object
-         */
-        public Registration(GraphBuilderPlugins plugins, MetaAccessProvider metaAccess, Class<?> declaringClass) {
-            this.plugins = plugins;
-            this.metaAccess = metaAccess;
-            this.declaringClass = declaringClass;
-        }
-
-        /**
-         * Registers a plugin for a method with no arguments.
-         *
-         * @param name the name of the method
-         * @param plugin the plugin to be registered
-         */
-        public void register0(String name, InvocationPlugin plugin) {
-            plugins.register(resolve(metaAccess, declaringClass, name), plugin);
-        }
-
-        /**
-         * Registers a plugin for a method with 1 argument.
-         *
-         * @param name the name of the method
-         * @param plugin the plugin to be registered
-         */
-        public void register1(String name, Class<?> arg, InvocationPlugin plugin) {
-            ResolvedJavaMethod method = arg == Receiver.class ? resolve(metaAccess, declaringClass, name) : resolve(metaAccess, declaringClass, name, arg);
-            plugins.register(method, plugin);
-        }
-
-        /**
-         * Registers a plugin for a method with 2 arguments.
-         *
-         * @param name the name of the method
-         * @param plugin the plugin to be registered
-         */
-        public void register2(String name, Class<?> arg1, Class<?> arg2, InvocationPlugin plugin) {
-            ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2) : resolve(metaAccess, declaringClass, name, arg1, arg2);
-            plugins.register(method, plugin);
-        }
-
-        /**
-         * Registers a plugin for a method with 3 arguments.
-         *
-         * @param name the name of the method
-         * @param plugin the plugin to be registered
-         */
-        public void register3(String name, Class<?> arg1, Class<?> arg2, Class<?> arg3, InvocationPlugin plugin) {
-            ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3);
-            plugins.register(method, plugin);
-        }
-
-        /**
-         * Registers a plugin for a method with 4 arguments.
-         *
-         * @param name the name of the method
-         * @param plugin the plugin to be registered
-         */
-        public void register4(String name, Class<?> arg1, Class<?> arg2, Class<?> arg3, Class<?> arg4, InvocationPlugin plugin) {
-            ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4);
-            plugins.register(method, plugin);
-        }
-
-        /**
-         * Resolves a method given a declaring class, name and parameter types.
-         */
-        public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class<?> declaringClass, String name, Class<?>... parameterTypes) {
-            try {
-                return metaAccess.lookupJavaMethod(name.equals("<init>") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(name, parameterTypes));
-            } catch (NoSuchMethodException | SecurityException e) {
-                throw new GraalInternalError(e);
-            }
-        }
-    }
-
-    public static class InvocationPluginChecker {
-        /**
-         * The set of all {@link InvocationPlugin#apply} method signatures.
-         */
-        static final Class<?>[][] SIGS;
-        static {
-            ArrayList<Class<?>[]> sigs = new ArrayList<>(5);
-            for (Method method : InvocationPlugin.class.getDeclaredMethods()) {
-                if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) {
-                    Class<?>[] sig = method.getParameterTypes();
-                    assert sig[0] == GraphBuilderContext.class;
-                    assert Arrays.asList(Arrays.copyOfRange(sig, 1, sig.length)).stream().allMatch(c -> c == ValueNode.class);
-                    while (sigs.size() < sig.length) {
-                        sigs.add(null);
-                    }
-                    sigs.set(sig.length - 1, sig);
-                }
-            }
-            assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null),
-                            ValueNode.class.getSimpleName());
-            SIGS = sigs.toArray(new Class<?>[sigs.size()][]);
-        }
-
-        public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) {
-            int arguments = method.getSignature().getParameterCount(!method.isStatic());
-            assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method.format("%H.%n(%p)"));
-            Method expected = null;
-            for (Method m : plugin.getClass().getDeclaredMethods()) {
-                if (m.getName().equals("apply")) {
-                    Class<?>[] parameterTypes = m.getParameterTypes();
-                    assert Arrays.equals(SIGS[arguments], parameterTypes) : format("graph builder plugin for %s has wrong signature%nexpected: (%s)%n  actual: (%s)", method.format("%H.%n(%p)"),
-                                    sigString(SIGS[arguments]), sigString(m.getParameterTypes()));
-                    expected = m;
-                }
-            }
-            assert expected != null : format("graph builder plugin %s must define exactly one \"apply\" method, none found", plugin);
-            return true;
-        }
-
-        protected static String sigString(Class<?>... sig) {
-            StringBuilder sb = new StringBuilder();
-            for (Class<?> t : sig) {
-                if (sb.length() != 0) {
-                    sb.append(", ");
-                }
-                sb.append(t.getSimpleName());
-            }
-            return sb.toString();
-        }
-
-    }
-
-    /**
-     * Registers an {@link InvocationPlugin} for a given method. There must be no plugin currently
-     * registered for {@code method}.
-     */
-    void register(ResolvedJavaMethod method, InvocationPlugin plugin);
-
-    /**
-     * Gets the {@link InvocationPlugin} for a given method.
-     *
-     * @param method the method to lookup
-     * @return the plugin associated with {@code method} or {@code null} if none exists
-     */
-    InvocationPlugin lookupInvocation(ResolvedJavaMethod method);
-
-    DefaultGraphBuilderPlugins copy();
-}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Mon Feb 16 11:57:43 2015 +0100
@@ -32,7 +32,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
-import com.oracle.graal.java.GraphBuilderPlugins.ParameterPlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java	Mon Feb 16 11:57:43 2015 +0100
@@ -0,0 +1,239 @@
+/*
+ * 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.java;
+
+import static java.lang.String.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.stream.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Manages a set of {@link InvocationPlugin}s.
+ */
+public class InvocationPlugins {
+    /**
+     * Utility for {@linkplain InvocationPlugins#register(ResolvedJavaMethod, InvocationPlugin)
+     * registration} of invocation plugins.
+     */
+    public static class Registration {
+
+        /**
+         * Sentinel class for use with {@link Registration#register1},
+         * {@link Registration#register2} or {@link Registration#register3} to denote the receiver
+         * argument for a non-static method.
+         */
+        public static final class Receiver {
+            private Receiver() {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        private final InvocationPlugins plugins;
+        private final MetaAccessProvider metaAccess;
+        private final Class<?> declaringClass;
+
+        /**
+         * Creates an object for registering {@link InvocationPlugin}s for methods declared by a
+         * given class.
+         *
+         * @param plugins where to register the plugins
+         * @param metaAccess used to resolve classes and methods
+         * @param declaringClass the class declaring the methods for which plugins will be
+         *            registered via this object
+         */
+        public Registration(InvocationPlugins plugins, MetaAccessProvider metaAccess, Class<?> declaringClass) {
+            this.plugins = plugins;
+            this.metaAccess = metaAccess;
+            this.declaringClass = declaringClass;
+        }
+
+        /**
+         * Registers a plugin for a method with no arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void register0(String name, InvocationPlugin plugin) {
+            plugins.register(resolve(metaAccess, declaringClass, name), plugin);
+        }
+
+        /**
+         * Registers a plugin for a method with 1 argument.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void register1(String name, Class<?> arg, InvocationPlugin plugin) {
+            ResolvedJavaMethod method = arg == Receiver.class ? resolve(metaAccess, declaringClass, name) : resolve(metaAccess, declaringClass, name, arg);
+            plugins.register(method, plugin);
+        }
+
+        /**
+         * Registers a plugin for a method with 2 arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void register2(String name, Class<?> arg1, Class<?> arg2, InvocationPlugin plugin) {
+            ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2) : resolve(metaAccess, declaringClass, name, arg1, arg2);
+            plugins.register(method, plugin);
+        }
+
+        /**
+         * Registers a plugin for a method with 3 arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void register3(String name, Class<?> arg1, Class<?> arg2, Class<?> arg3, InvocationPlugin plugin) {
+            ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3);
+            plugins.register(method, plugin);
+        }
+
+        /**
+         * Registers a plugin for a method with 4 arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void register4(String name, Class<?> arg1, Class<?> arg2, Class<?> arg3, Class<?> arg4, InvocationPlugin plugin) {
+            ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4);
+            plugins.register(method, plugin);
+        }
+
+        /**
+         * Resolves a method given a declaring class, name and parameter types.
+         */
+        public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class<?> declaringClass, String name, Class<?>... parameterTypes) {
+            try {
+                return metaAccess.lookupJavaMethod(name.equals("<init>") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(name, parameterTypes));
+            } catch (NoSuchMethodException | SecurityException e) {
+                throw new GraalInternalError(e);
+            }
+        }
+    }
+
+    private final Map<ResolvedJavaMethod, InvocationPlugin> plugins = new HashMap<>();
+
+    /**
+     * The invocation plugins deferred to if a plugin is not found in this object.
+     */
+    private InvocationPlugins defaults;
+
+    /**
+     * Registers an invocation plugin for a given method. There must be no plugin currently
+     * registered for {@code method}.
+     */
+    public void register(ResolvedJavaMethod method, InvocationPlugin plugin) {
+        assert Checker.check(method, plugin);
+        GraphBuilderPlugin oldValue = plugins.put(method, plugin);
+        // System.out.println("registered: " + plugin);
+        assert oldValue == null;
+    }
+
+    /**
+     * Gets the plugin for a given method.
+     *
+     * @param method the method to lookup
+     * @return the plugin associated with {@code method} or {@code null} if none exists
+     */
+    public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) {
+        InvocationPlugin res = plugins.get(method);
+        if (res == null && defaults != null) {
+            return defaults.lookupInvocation(method);
+        }
+        return res;
+    }
+
+    /**
+     * Sets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} if a
+     * plugin is not found in this object.
+     */
+    public InvocationPlugins setDefaults(InvocationPlugins defaults) {
+        InvocationPlugins old = this.defaults;
+        this.defaults = defaults;
+        return old;
+    }
+
+    @Override
+    public String toString() {
+        return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", "));
+    }
+
+    private static class Checker {
+        /**
+         * The set of all {@link InvocationPlugin#apply} method signatures.
+         */
+        static final Class<?>[][] SIGS;
+        static {
+            ArrayList<Class<?>[]> sigs = new ArrayList<>(5);
+            for (Method method : InvocationPlugin.class.getDeclaredMethods()) {
+                if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) {
+                    Class<?>[] sig = method.getParameterTypes();
+                    assert sig[0] == GraphBuilderContext.class;
+                    assert Arrays.asList(Arrays.copyOfRange(sig, 1, sig.length)).stream().allMatch(c -> c == ValueNode.class);
+                    while (sigs.size() < sig.length) {
+                        sigs.add(null);
+                    }
+                    sigs.set(sig.length - 1, sig);
+                }
+            }
+            assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null),
+                            ValueNode.class.getSimpleName());
+            SIGS = sigs.toArray(new Class<?>[sigs.size()][]);
+        }
+
+        public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) {
+            int arguments = method.getSignature().getParameterCount(!method.isStatic());
+            assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method.format("%H.%n(%p)"));
+            Method expected = null;
+            for (Method m : plugin.getClass().getDeclaredMethods()) {
+                if (m.getName().equals("apply")) {
+                    Class<?>[] parameterTypes = m.getParameterTypes();
+                    assert Arrays.equals(SIGS[arguments], parameterTypes) : format("graph builder plugin for %s has wrong signature%nexpected: (%s)%n  actual: (%s)", method.format("%H.%n(%p)"),
+                                    sigString(SIGS[arguments]), sigString(m.getParameterTypes()));
+                    expected = m;
+                }
+            }
+            assert expected != null : format("graph builder plugin %s must define exactly one \"apply\" method, none found", plugin);
+            return true;
+        }
+
+        protected static String sigString(Class<?>... sig) {
+            StringBuilder sb = new StringBuilder();
+            for (Class<?> t : sig) {
+                if (sb.length() != 0) {
+                    sb.append(", ");
+                }
+                sb.append(t.getSimpleName());
+            }
+            return sb.toString();
+        }
+    }
+}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java	Mon Feb 16 11:57:43 2015 +0100
@@ -25,9 +25,9 @@
 import static com.oracle.graal.java.GraphBuilderContext.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin;
-import com.oracle.graal.java.GraphBuilderPlugins.Registration;
-import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver;
+import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin;
+import com.oracle.graal.java.InvocationPlugins.Registration;
+import com.oracle.graal.java.InvocationPlugins.Registration.Receiver;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -37,7 +37,7 @@
  * Provider of non-runtime specific {@link GraphBuilderPlugin}s.
  */
 public class StandardGraphBuilderPlugins {
-    public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+    public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
         Registration r = new Registration(plugins, metaAccess, Object.class);
         r.register1("<init>", Receiver.class, new InvocationPlugin() {
             public boolean apply(GraphBuilderContext builder, ValueNode object) {
@@ -92,7 +92,7 @@
             return true;
         }
 
-        void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+        void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
             ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), "valueOf", kind.toJavaClass());
             plugins.register(method, this);
         }
@@ -112,7 +112,7 @@
             return true;
         }
 
-        void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+        void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
             String name = kind.toJavaClass().getSimpleName() + "Value";
             ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name);
             plugins.register(method, this);
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Feb 16 11:57:43 2015 +0100
@@ -89,7 +89,7 @@
         compilable.call(arguments);
 
         try (Scope s = Debug.scope("TruffleCompilation", new TruffleDebugJavaMethod(compilable))) {
-            return truffleCompiler.getPartialEvaluator().createGraph(compilable, allowAssumptions, truffleCompiler.createGraphBuilderSuitePlugins());
+            return truffleCompiler.getPartialEvaluator().createGraph(compilable, allowAssumptions);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Feb 16 11:57:43 2015 +0100
@@ -38,6 +38,8 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.java.*;
+import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
@@ -98,7 +100,7 @@
         }
     }
 
-    public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions, GraphBuilderPlugins graalPlugins) {
+    public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions) {
         if (TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) {
             constantReceivers = new HashSet<>();
         }
@@ -122,7 +124,7 @@
             HighTierContext tierContext = new HighTierContext(providers, graphCache, new PhaseSuite<HighTierContext>(), OptimisticOptimizations.NONE);
 
             if (TruffleCompilerOptions.FastPE.getValue()) {
-                fastPartialEvaluation(callTarget, graph, baseContext, tierContext, graalPlugins);
+                fastPartialEvaluation(callTarget, graph, baseContext, tierContext);
             } else {
                 createRootGraph(graph);
                 partialEvaluation(callTarget, graph, baseContext, tierContext);
@@ -145,7 +147,7 @@
         return graph;
     }
 
-    private class InterceptLoadFieldPlugin implements GraphBuilderPlugins.LoadFieldPlugin {
+    private class InterceptLoadFieldPlugin implements LoadFieldPlugin {
 
         public boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) {
             if (receiver.isConstant()) {
@@ -175,7 +177,7 @@
         }
     }
 
-    private class InterceptReceiverPlugin implements GraphBuilderPlugins.ParameterPlugin {
+    private class InterceptReceiverPlugin implements ParameterPlugin {
 
         private final Object receiver;
 
@@ -191,7 +193,7 @@
         }
     }
 
-    private class InlineInvokePlugin implements GraphBuilderPlugins.InlineInvokePlugin {
+    private class InlineInvokePlugin implements GraphBuilderPlugin.InlineInvokePlugin {
 
         private Stack<TruffleInlining> inlining;
         private OptimizedDirectCallNode lastDirectCallNode;
@@ -201,7 +203,10 @@
             this.inlining.push(inlining);
         }
 
-        public ResolvedJavaMethod inlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments) {
+        public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType, int depth) {
+            if (original.getAnnotation(TruffleBoundary.class) != null) {
+                return null;
+            }
             if (original.equals(callSiteProxyMethod)) {
                 ValueNode arg1 = arguments[0];
                 if (!arg1.isConstant()) {
@@ -225,19 +230,14 @@
             return original;
         }
 
-        public boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth) {
-            return method.getAnnotation(TruffleBoundary.class) == null;
-        }
-
         public void postInline(ResolvedJavaMethod inlinedTargetMethod) {
             if (inlinedTargetMethod.equals(callInlinedMethod)) {
                 inlining.pop();
             }
         }
-
     }
 
-    private class LoopExplosionPlugin implements GraphBuilderPlugins.LoopExplosionPlugin {
+    private class LoopExplosionPlugin implements GraphBuilderPlugin.LoopExplosionPlugin {
 
         public boolean shouldExplodeLoops(ResolvedJavaMethod method) {
             return method.getAnnotation(ExplodeLoop.class) != null;
@@ -246,18 +246,18 @@
     }
 
     @SuppressWarnings("unused")
-    private void fastPartialEvaluation(OptimizedCallTarget callTarget, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext, GraphBuilderPlugins graalPlugins) {
+    private void fastPartialEvaluation(OptimizedCallTarget callTarget, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) {
         GraphBuilderConfiguration newConfig = configForRoot.copy();
+        newConfig.getInvocationPlugins().setDefaults(configForRoot.getInvocationPlugins());
         newConfig.setLoadFieldPlugin(new InterceptLoadFieldPlugin());
         newConfig.setParameterPlugin(new InterceptReceiverPlugin(callTarget));
         callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy()));
         newConfig.setInlineInvokePlugin(new InlineInvokePlugin(callTarget.getInlining()));
         newConfig.setLoopExplosionPlugin(new LoopExplosionPlugin());
-        DefaultGraphBuilderPlugins plugins = graalPlugins == null ? new DefaultGraphBuilderPlugins() : graalPlugins.copy();
-        TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), plugins);
+        TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), newConfig.getInvocationPlugins());
         long ms = System.currentTimeMillis();
         new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getReplacements(), providers.getConstantReflection(), newConfig,
-                        plugins, TruffleCompilerImpl.Optimizations).apply(graph);
+                        TruffleCompilerImpl.Optimizations).apply(graph);
         System.out.println("# ms: " + (System.currentTimeMillis() - ms));
         Debug.dump(graph, "After FastPE");
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Feb 16 11:57:43 2015 +0100
@@ -120,10 +120,10 @@
         compilationNotify.notifyCompilationStarted(compilable);
 
         try {
-            GraphBuilderSuiteInfo info = createGraphBuilderSuite();
+            PhaseSuite<HighTierContext> graphBuilderSuite = createGraphBuilderSuite();
 
             try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) {
-                graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES, info.plugins);
+                graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES);
             }
 
             if (Thread.currentThread().isInterrupted()) {
@@ -138,7 +138,7 @@
             }
 
             compilationNotify.notifyCompilationTruffleTierFinished(compilable, graph);
-            CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), info.suite, compilable.getSpeculationLog(), compilable);
+            CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), graphBuilderSuite, compilable.getSpeculationLog(), compilable);
             compilationNotify.notifyCompilationSuccess(compilable, graph, compilationResult);
         } catch (Throwable t) {
             compilationNotify.notifyCompilationFailed(compilable, graph, t);
@@ -158,8 +158,8 @@
             CodeCacheProvider codeCache = providers.getCodeCache();
             CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false);
             CompilationResult compilationResult = new CompilationResult(name);
-            result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, graphBuilderSuite == null ? createGraphBuilderSuite().suite : graphBuilderSuite,
-                            Optimizations, getProfilingInfo(graph), speculationLog, suites, lirSuites, compilationResult, CompilationResultBuilderFactory.Default);
+            result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, graphBuilderSuite, Optimizations, getProfilingInfo(graph), speculationLog, suites,
+                            lirSuites, compilationResult, CompilationResultBuilderFactory.Default);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
@@ -205,22 +205,20 @@
 
     static class GraphBuilderSuiteInfo {
         final PhaseSuite<HighTierContext> suite;
-        final GraphBuilderPlugins plugins;
+        final InvocationPlugins plugins;
 
-        public GraphBuilderSuiteInfo(PhaseSuite<HighTierContext> suite, GraphBuilderPlugins plugins) {
+        public GraphBuilderSuiteInfo(PhaseSuite<HighTierContext> suite, InvocationPlugins plugins) {
             this.suite = suite;
             this.plugins = plugins;
         }
     }
 
-    private GraphBuilderSuiteInfo createGraphBuilderSuite() {
+    private PhaseSuite<HighTierContext> createGraphBuilderSuite() {
         PhaseSuite<HighTierContext> suite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
         ListIterator<BasePhase<? super HighTierContext>> iterator = suite.findPhase(GraphBuilderPhase.class);
-        GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous();
         iterator.remove();
-        GraphBuilderPlugins plugins = graphBuilderPhase.getGraphBuilderPlugins();
-        iterator.add(new GraphBuilderPhase(config, plugins));
-        return new GraphBuilderSuiteInfo(suite, plugins);
+        iterator.add(new GraphBuilderPhase(config));
+        return suite;
     }
 
     public void processAssumption(Set<Assumption> newAssumptions, Assumption assumption, List<AssumptionValidAssumption> manual) {
@@ -237,8 +235,4 @@
     public PartialEvaluator getPartialEvaluator() {
         return partialEvaluator;
     }
-
-    public GraphBuilderPlugins createGraphBuilderSuitePlugins() {
-        return this.createGraphBuilderSuite().plugins;
-    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Sun Feb 15 22:38:29 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Mon Feb 16 11:57:43 2015 +0100
@@ -32,9 +32,9 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.java.*;
-import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin;
-import com.oracle.graal.java.GraphBuilderPlugins.Registration;
-import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver;
+import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin;
+import com.oracle.graal.java.InvocationPlugins.Registration;
+import com.oracle.graal.java.InvocationPlugins.Registration.Receiver;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -50,7 +50,7 @@
  * Provider of {@link GraphBuilderPlugin}s for Truffle classes.
  */
 public class TruffleGraphBuilderPlugins {
-    public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+    public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
 
         // OptimizedAssumption.class
         Registration r = new Registration(plugins, metaAccess, OptimizedAssumption.class);