changeset 19882:0c29075aeafe

graph builder plugins are created before GraphBuilderConfigurations and the process for deriving plugins from an existing configuration is simplified
author Doug Simon <doug.simon@oracle.com>
date Sun, 15 Mar 2015 10:52:22 +0100
parents 6a684aeb1590
children 4d33cd6e0c8f
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.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/HotSpotInvocationPlugins.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.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
diffstat 23 files changed, 198 insertions(+), 167 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Sun Mar 15 10:52:22 2015 +0100
@@ -69,8 +69,7 @@
         MetaAccessProvider metaAccess = providers.getMetaAccess();
 
         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
-        GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault();
-        config.setPlugins(new Plugins(metaAccess));
+        GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault(new Plugins(new InvocationPlugins(metaAccess)));
         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
         HighTierContext context = new HighTierContext(providers, null, graphBuilderSuite, OptimisticOptimizations.NONE);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Sun Mar 15 10:52:22 2015 +0100
@@ -33,7 +33,6 @@
 import com.oracle.graal.api.meta.Assumptions.NoFinalizableSubclass;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.*;
-import com.oracle.graal.java.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.java.*;
@@ -67,8 +66,7 @@
         final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]);
         StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions);
 
-        GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault();
-        conf.setPlugins(new Plugins(getMetaAccess()));
+        GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins());
         new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), conf, OptimisticOptimizations.ALL, null).apply(graph);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Sun Mar 15 10:52:22 2015 +0100
@@ -49,6 +49,7 @@
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.java.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.phases.*;
 import com.oracle.graal.nodeinfo.*;
@@ -774,7 +775,7 @@
     }
 
     /**
-     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault() default} mode to
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault default} mode to
      * produce a graph.
      *
      * @param methodName the name of the method in {@code this.getClass()} to be parsed
@@ -784,7 +785,7 @@
     }
 
     /**
-     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault() default} mode to
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault default} mode to
      * produce a graph.
      */
     protected StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) {
@@ -792,8 +793,8 @@
     }
 
     /**
-     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getEagerDefault() eager} mode
-     * to produce a graph.
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getEagerDefault eager} mode to
+     * produce a graph.
      *
      * @param methodName the name of the method in {@code this.getClass()} to be parsed
      */
@@ -802,19 +803,19 @@
     }
 
     /**
-     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getEagerDefault() eager} mode
-     * to produce a graph.
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getEagerDefault eager} mode to
+     * produce a graph.
      */
     protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) {
-        return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerDefault()), allowAssumptions);
+        return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerDefault(getDefaultGraphBuilderPlugins())), allowAssumptions);
     }
 
     /**
-     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getFullDebugDefault() full
-     * debug} mode to produce a graph.
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getFullDebugDefault full debug}
+     * mode to produce a graph.
      */
     protected StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) {
-        return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()), allowAssumptions);
+        return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault(getDefaultGraphBuilderPlugins())), allowAssumptions);
     }
 
     private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite<HighTierContext> graphBuilderSuite, AllowAssumptions allowAssumptions) {
@@ -828,32 +829,31 @@
         }
     }
 
+    protected Plugins getDefaultGraphBuilderPlugins() {
+        PhaseSuite<HighTierContext> suite = backend.getSuites().getDefaultGraphBuilderSuite();
+        Plugins defaultPlugins = ((GraphBuilderPhase) suite.findPhase(GraphBuilderPhase.class).previous()).getGraphBuilderConfig().getPlugins();
+        // defensive copying
+        return new Plugins(defaultPlugins);
+    }
+
     protected PhaseSuite<HighTierContext> getDefaultGraphBuilderSuite() {
         // defensive copying
         return backend.getSuites().getDefaultGraphBuilderSuite().copy();
     }
 
     protected PhaseSuite<HighTierContext> getCustomGraphBuilderSuite(GraphBuilderConfiguration gbConf) {
-        PhaseSuite<HighTierContext> suite = getDefaultGraphBuilderSuite().copy();
+        PhaseSuite<HighTierContext> suite = getDefaultGraphBuilderSuite();
         ListIterator<BasePhase<? super HighTierContext>> iterator = suite.findPhase(GraphBuilderPhase.class);
-        GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous();
-        GraphBuilderConfiguration gbConfCopy = editGraphBuilderConfiguration(gbConf.copy().copyPluginsFrom(graphBuilderPhase.getGraphBuilderConfig()));
+        GraphBuilderConfiguration gbConfCopy = editGraphBuilderConfiguration(gbConf.copy());
         iterator.remove();
         iterator.add(new GraphBuilderPhase(gbConfCopy));
         return suite;
     }
 
     protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
-        editGraphBuilderPlugins(conf.getPlugins());
         return conf;
     }
 
-    /**
-     * @param plugins
-     */
-    protected void editGraphBuilderPlugins(GraphBuilderConfiguration.Plugins plugins) {
-    }
-
     protected Replacements getReplacements() {
         return getProviders().getReplacements();
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Sun Mar 15 10:52:22 2015 +0100
@@ -84,7 +84,7 @@
         }
         assertTrue(graphLineSPs > 0);
         CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
-        PhaseSuite<HighTierContext> graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault());
+        PhaseSuite<HighTierContext> graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault(getDefaultGraphBuilderPlugins()));
         final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL,
                         getProfilingInfo(graph), getSpeculationLog(), getSuites(), getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default);
         int lineSPs = 0;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Sun Mar 15 10:52:22 2015 +0100
@@ -231,7 +231,8 @@
         try (Scope s = Debug.scope("InliningTest", new DebugDumpScope(snippet))) {
             ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
             StructuredGraph graph = eagerInfopointMode ? parseDebug(method, AllowAssumptions.YES) : parseEager(method, AllowAssumptions.YES);
-            PhaseSuite<HighTierContext> graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()) : getDefaultGraphBuilderSuite();
+            PhaseSuite<HighTierContext> graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault(getDefaultGraphBuilderPlugins()))
+                            : getDefaultGraphBuilderSuite();
             HighTierContext context = new HighTierContext(getProviders(), null, graphBuilderSuite, OptimisticOptimizations.ALL);
             Debug.dump(graph, "Graph");
             new CanonicalizerPhase().apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java	Sun Mar 15 10:52:22 2015 +0100
@@ -223,7 +223,7 @@
                      * the code before static analysis, the classes would otherwise be not loaded
                      * yet and the bytecode parser would only create a graph.
                      */
-                    GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getEagerDefault();
+                    GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getEagerDefault(new Plugins(new InvocationPlugins(metaAccess)));
                     /*
                      * For simplicity, we ignore all exception handling during the static analysis.
                      * This is a constraint of this example code, a real static analysis needs to
@@ -238,7 +238,6 @@
                      */
                     OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE;
 
-                    graphBuilderConfig.setPlugins(new Plugins(metaAccess));
                     GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, graphBuilderConfig, optimisticOpts, null);
                     graphBuilder.apply(graph);
                 } catch (Throwable ex) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Sun Mar 15 10:52:22 2015 +0100
@@ -33,7 +33,8 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.hotspot.word.*;
+import com.oracle.graal.java.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.phases.util.*;
 
 @ServiceProvider(HotSpotBackendFactory.class)
@@ -124,9 +125,11 @@
         HotSpotMetaAccessProvider metaAccess;
         HotSpotLoweringProvider lowerer;
         HotSpotSnippetReflectionProvider snippetReflection;
-        Replacements replacements;
+        HotSpotReplacementsImpl replacements;
         HotSpotDisassemblerProvider disassembler;
         HotSpotSuitesProvider suites;
+        HotSpotWordTypes wordTypes;
+        Plugins plugins;
         try (InitTimer t = timer("create providers")) {
             try (InitTimer rt = timer("create HotSpotRegisters provider")) {
                 registers = createRegisters();
@@ -152,7 +155,8 @@
             try (InitTimer rt = timer("create Lowerer provider")) {
                 lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target);
             }
-            Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, new HotSpotStampProvider());
+            HotSpotStampProvider stampProvider = new HotSpotStampProvider();
+            Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, stampProvider);
 
             try (InitTimer rt = timer("create SnippetReflection provider")) {
                 snippetReflection = createSnippetReflection(runtime);
@@ -163,10 +167,17 @@
             try (InitTimer rt = timer("create Disassembler provider")) {
                 disassembler = createDisassembler(runtime);
             }
+            try (InitTimer rt = timer("create WordTypes")) {
+                wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind);
+            }
+            try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
+                plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch);
+                replacements.setGraphBuilderPlugins(plugins);
+            }
             try (InitTimer rt = timer("create Suites provider")) {
-                suites = createSuites(runtime);
+                suites = createSuites(runtime, plugins);
             }
-            providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection);
+            providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection, wordTypes, plugins);
         }
         try (InitTimer rt = timer("instantiate backend")) {
             return createBackend(runtime, providers);
@@ -185,7 +196,7 @@
         return new HotSpotDisassemblerProvider(runtime);
     }
 
-    protected Replacements createReplacements(HotSpotGraalRuntimeProvider runtime, Providers p, SnippetReflectionProvider snippetReflection) {
+    protected HotSpotReplacementsImpl createReplacements(HotSpotGraalRuntimeProvider runtime, Providers p, SnippetReflectionProvider snippetReflection) {
         return new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), p.getCodeCache().getTarget());
     }
 
@@ -210,8 +221,8 @@
         return new HotSpotMetaAccessProvider(runtime);
     }
 
-    protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime) {
-        return new HotSpotSuitesProvider(runtime);
+    protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime, Plugins plugins) {
+        return new HotSpotSuitesProvider(runtime, plugins);
     }
 
     protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Sun Mar 15 10:52:22 2015 +0100
@@ -29,6 +29,8 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.word.*;
+import com.oracle.graal.java.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.sparc.*;
@@ -60,18 +62,23 @@
         Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig());
         HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters);
         LoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target);
-        Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, new HotSpotStampProvider());
+        HotSpotStampProvider stampProvider = new HotSpotStampProvider();
+        Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, stampProvider);
         HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime);
         HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), target);
         HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime);
-        HotSpotSuitesProvider suites = createSuites(runtime);
-        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection);
+        HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind);
+        Plugins plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch);
+        replacements.setGraphBuilderPlugins(plugins);
+        HotSpotSuitesProvider suites = createSuites(runtime, plugins);
+        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection,
+                        wordTypes, plugins);
 
         return createBackend(runtime, providers);
     }
 
-    protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime) {
-        return new HotSpotSuitesProvider(runtime);
+    protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime, Plugins plugins) {
+        return new HotSpotSuitesProvider(runtime, plugins);
     }
 
     protected HotSpotCodeCacheProvider createCodeCache(HotSpotGraalRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Sun Mar 15 10:52:22 2015 +0100
@@ -31,8 +31,6 @@
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
-import com.oracle.graal.java.GraphBuilderConfiguration.Plugins;
-import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -72,15 +70,6 @@
         final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
         HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements();
 
-        try (InitTimer st = timer("graphBuilderPlugins.initialize")) {
-            Plugins plugins = HotSpotGraphBuilderPlugins.create(config, providers.getWordTypes(), providers.getMetaAccess(), providers.getConstantReflection(), providers.getSnippetReflection(),
-                            providers.getForeignCalls(), providers.getStampProvider(), replacements, providers.getCodeCache().getTarget().arch);
-            providers.setGraphBuilderPlugins(plugins);
-            GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous();
-            phase.getGraphBuilderConfig().setPlugins(plugins);
-            replacements.completeInitialization(plugins);
-        }
-
         try (InitTimer st = timer("foreignCalls.initialize")) {
             foreignCalls.initialize(providers, config);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Sun Mar 15 10:52:22 2015 +0100
@@ -51,6 +51,8 @@
  */
 public class HotSpotGraphBuilderPlugins {
 
+    private static final int PLUGIN_COUNT_ESTIMATE = 160;
+
     /**
      * Creates a {@link Plugins} object that should be used when running on HotSpot.
      *
@@ -62,7 +64,7 @@
     public static Plugins create(HotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection,
                     SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements, Architecture arch) {
 
-        InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess);
+        InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess, PLUGIN_COUNT_ESTIMATE);
 
         Plugins plugins = new Plugins(invocationPlugins);
         NodeIntrinsificationPhase nodeIntrinsification = new NodeIntrinsificationPhase(metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider);
@@ -79,6 +81,10 @@
         registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config);
         registerStableOptionPlugins(invocationPlugins);
         StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, arch, invocationPlugins, !config.useHeapProfiler);
+
+        int size = invocationPlugins.size();
+        assert PLUGIN_COUNT_ESTIMATE >= size : String.format("adjust %s.PLUGIN_COUNT_ESTIMATE to be above or equal to %d", HotSpotGraphBuilderPlugins.class.getSimpleName(), size);
+        assert PLUGIN_COUNT_ESTIMATE - size < 20 : String.format("adjust %s.PLUGIN_COUNT_ESTIMATE to be closer to %d", HotSpotGraphBuilderPlugins.class.getSimpleName(), size);
         return plugins;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java	Sun Mar 15 10:52:22 2015 +0100
@@ -34,8 +34,8 @@
 final class HotSpotInvocationPlugins extends InvocationPlugins {
     final HotSpotVMConfig config;
 
-    public HotSpotInvocationPlugins(HotSpotVMConfig config, MetaAccessProvider metaAccess) {
-        super(metaAccess);
+    public HotSpotInvocationPlugins(HotSpotVMConfig config, MetaAccessProvider metaAccess, int estimatePluginCount) {
+        super(metaAccess, estimatePluginCount);
         this.config = config;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Sun Mar 15 10:52:22 2015 +0100
@@ -41,17 +41,18 @@
     private final HotSpotRegistersProvider registers;
     private final SnippetReflectionProvider snippetReflection;
     private final HotSpotWordTypes wordTypes;
-    private Plugins graphBuilderPlugins;
+    private final Plugins graphBuilderPlugins;
 
     public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls,
                     LoweringProvider lowerer, Replacements replacements, HotSpotDisassemblerProvider disassembler, SuitesProvider suites, HotSpotRegistersProvider registers,
-                    SnippetReflectionProvider snippetReflection) {
+                    SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes, Plugins graphBuilderPlugins) {
         super(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, new HotSpotStampProvider());
         this.disassembler = disassembler;
         this.suites = suites;
         this.registers = registers;
         this.snippetReflection = snippetReflection;
-        this.wordTypes = new HotSpotWordTypes(metaAccess, codeCache.getTarget().wordKind);
+        this.wordTypes = wordTypes;
+        this.graphBuilderPlugins = graphBuilderPlugins;
     }
 
     @Override
@@ -80,12 +81,7 @@
         return snippetReflection;
     }
 
-    public void setGraphBuilderPlugins(Plugins plugins) {
-        graphBuilderPlugins = plugins;
-    }
-
     public Plugins getGraphBuilderPlugins() {
-        assert graphBuilderPlugins != null;
         return graphBuilderPlugins;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Sun Mar 15 10:52:22 2015 +0100
@@ -29,6 +29,7 @@
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode;
+import com.oracle.graal.java.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.lir.phases.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.options.DerivedOptionValue.OptionSupplier;
@@ -65,9 +66,9 @@
 
     }
 
-    public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime) {
+    public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime, Plugins plugins) {
         this.runtime = runtime;
-        this.defaultGraphBuilderSuite = createGraphBuilderSuite();
+        this.defaultGraphBuilderSuite = createGraphBuilderSuite(plugins);
         this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier());
         this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier());
     }
@@ -99,9 +100,9 @@
         return ret;
     }
 
-    protected PhaseSuite<HighTierContext> createGraphBuilderSuite() {
+    protected PhaseSuite<HighTierContext> createGraphBuilderSuite(Plugins plugins) {
         PhaseSuite<HighTierContext> suite = new PhaseSuite<>();
-        GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault();
+        GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins);
         suite.appendPhase(new GraphBuilderPhase(config));
         return suite;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Sun Mar 15 10:52:22 2015 +0100
@@ -80,11 +80,10 @@
     @Override
     protected StructuredGraph getGraph() {
         Plugins defaultPlugins = providers.getGraphBuilderPlugins();
-        Plugins plugins = new Plugins(providers.getMetaAccess()).updateFrom(defaultPlugins, false);
-        plugins.getInvocationPlugins().setDefaults(defaultPlugins.getInvocationPlugins());
-        plugins.setParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), plugins.getParameterPlugin(), providers.getMetaAccess(), providers.getSnippetReflection()));
-        GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
-        config.setPlugins(plugins);
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        Plugins plugins = new Plugins(defaultPlugins);
+        plugins.setParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), plugins.getParameterPlugin(), metaAccess, providers.getSnippetReflection()));
+        GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
 
         // Stubs cannot have optimistic assumptions since they have
         // to be valid for the entire run of the VM. Nor can they be
@@ -94,7 +93,7 @@
 
         assert SnippetGraphUnderConstruction.get() == null;
         SnippetGraphUnderConstruction.set(graph);
-        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, method).apply(graph);
+        new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, method).apply(graph);
         SnippetGraphUnderConstruction.set(null);
 
         graph.setGuardsStage(GuardsStage.FLOATING_GUARDS);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Sun Mar 15 10:52:22 2015 +0100
@@ -698,7 +698,7 @@
     }
 
     private void maybeEagerlyResolve(int cpi, int bytecode) {
-        if (graphBuilderConfig.eagerResolving() || parsingReplacement()) {
+        if (graphBuilderConfig.eagerResolving() || replacementContext instanceof IntrinsicContext) {
             constantPool.loadReferencedType(cpi, bytecode);
         }
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java	Sun Mar 15 10:52:22 2015 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.java;
 
+import com.oracle.graal.java.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.lir.phases.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.options.DerivedOptionValue.OptionSupplier;
@@ -54,8 +55,8 @@
 
     }
 
-    public DefaultSuitesProvider() {
-        this.defaultGraphBuilderSuite = createGraphBuilderSuite();
+    public DefaultSuitesProvider(Plugins plugins) {
+        this.defaultGraphBuilderSuite = createGraphBuilderSuite(plugins);
         this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier());
         this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier());
     }
@@ -72,9 +73,9 @@
         return defaultGraphBuilderSuite;
     }
 
-    protected PhaseSuite<HighTierContext> createGraphBuilderSuite() {
+    protected PhaseSuite<HighTierContext> createGraphBuilderSuite(Plugins plugins) {
         PhaseSuite<HighTierContext> suite = new PhaseSuite<>();
-        suite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault()));
+        suite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault(plugins)));
         return suite;
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Sun Mar 15 10:52:22 2015 +0100
@@ -37,7 +37,7 @@
 public class GraphBuilderConfiguration {
 
     public static class Plugins {
-        private InvocationPlugins invocationPlugins;
+        private final InvocationPlugins invocationPlugins;
         private LoadFieldPlugin loadFieldPlugin;
         private LoadIndexedPlugin loadIndexedPlugin;
         private ParameterPlugin parameterPlugin;
@@ -45,10 +45,27 @@
         private GenericInvocationPlugin genericInvocationPlugin;
         private LoopExplosionPlugin loopExplosionPlugin;
 
-        public Plugins(MetaAccessProvider metaAccess) {
-            invocationPlugins = new InvocationPlugins(metaAccess);
+        /**
+         * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in
+         * {@code copyFrom} become the {@linkplain InvocationPlugins#getDefaults() default}
+         * {@linkplain #getInvocationPlugins() invocation plugins} in this object.
+         */
+        public Plugins(Plugins copyFrom) {
+            this.invocationPlugins = new InvocationPlugins(copyFrom.invocationPlugins);
+            this.parameterPlugin = copyFrom.parameterPlugin;
+            this.loadFieldPlugin = copyFrom.loadFieldPlugin;
+            this.loadIndexedPlugin = copyFrom.loadIndexedPlugin;
+            this.inlineInvokePlugin = copyFrom.inlineInvokePlugin;
+            this.loopExplosionPlugin = copyFrom.loopExplosionPlugin;
+            this.genericInvocationPlugin = copyFrom.genericInvocationPlugin;
         }
 
+        /**
+         * Creates a new set of plugins.
+         *
+         * @param invocationPlugins the {@linkplain #getInvocationPlugins() invocation plugins} in
+         *            this object
+         */
         public Plugins(InvocationPlugins invocationPlugins) {
             this.invocationPlugins = invocationPlugins;
         }
@@ -104,19 +121,6 @@
         public void setLoopExplosionPlugin(LoopExplosionPlugin plugin) {
             this.loopExplosionPlugin = plugin;
         }
-
-        public Plugins updateFrom(Plugins other, boolean includeInvocationPlugins) {
-            if (includeInvocationPlugins) {
-                this.invocationPlugins.updateFrom(other.getInvocationPlugins());
-            }
-            this.parameterPlugin = other.parameterPlugin;
-            this.loadFieldPlugin = other.loadFieldPlugin;
-            this.loadIndexedPlugin = other.loadIndexedPlugin;
-            this.inlineInvokePlugin = other.inlineInvokePlugin;
-            this.loopExplosionPlugin = other.loopExplosionPlugin;
-            this.genericInvocationPlugin = other.genericInvocationPlugin;
-            return this;
-        }
     }
 
     private static final ResolvedJavaType[] EMPTY = new ResolvedJavaType[]{};
@@ -127,7 +131,7 @@
     private final DebugInfoMode debugInfoMode;
     private final boolean doLivenessAnalysis;
     private boolean useProfiling;
-    private Plugins plugins;
+    private final Plugins plugins;
 
     public static enum DebugInfoMode {
         SafePointsOnly,
@@ -153,19 +157,26 @@
         Full,
     }
 
-    protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes, boolean doLivenessAnalysis) {
+    protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes, boolean doLivenessAnalysis,
+                    Plugins plugins) {
         this.eagerResolving = eagerResolving;
         this.omitAllExceptionEdges = omitAllExceptionEdges;
         this.debugInfoMode = debugInfoMode;
         this.skippedExceptionTypes = skippedExceptionTypes;
         this.doLivenessAnalysis = doLivenessAnalysis;
         this.useProfiling = true;
+        this.plugins = plugins;
     }
 
+    /**
+     * Creates a copy of this configuration with all its plugins. The {@link InvocationPlugins} in
+     * this configuration become the {@linkplain InvocationPlugins#getDefaults defaults} of the
+     * {@link InvocationPlugins} in the copy.
+     */
     public GraphBuilderConfiguration copy() {
-        GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis);
+        Plugins newPlugins = new Plugins(new InvocationPlugins(plugins.getInvocationPlugins()));
+        GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis, newPlugins);
         result.useProfiling = useProfiling;
-        result.copyPluginsFrom(this);
         return result;
     }
 
@@ -178,20 +189,20 @@
     }
 
     public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) {
-        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis);
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis, plugins);
     }
 
     public GraphBuilderConfiguration withOmitAllExceptionEdges(boolean newOmitAllExceptionEdges) {
-        return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis);
+        return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis, plugins);
     }
 
     public GraphBuilderConfiguration withDebugInfoMode(DebugInfoMode newDebugInfoMode) {
         ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length);
-        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newDebugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis);
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newDebugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis, plugins);
     }
 
     public GraphBuilderConfiguration withDoLivenessAnalysis(boolean newLivenessAnalysis) {
-        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis);
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis, plugins);
     }
 
     public ResolvedJavaType[] getSkippedExceptionTypes() {
@@ -218,20 +229,20 @@
         return doLivenessAnalysis;
     }
 
-    public static GraphBuilderConfiguration getDefault() {
-        return new GraphBuilderConfiguration(false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue());
+    public static GraphBuilderConfiguration getDefault(Plugins plugins) {
+        return new GraphBuilderConfiguration(false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
     }
 
-    public static GraphBuilderConfiguration getEagerDefault() {
-        return new GraphBuilderConfiguration(true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue());
+    public static GraphBuilderConfiguration getEagerDefault(Plugins plugins) {
+        return new GraphBuilderConfiguration(true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
     }
 
-    public static GraphBuilderConfiguration getSnippetDefault() {
-        return new GraphBuilderConfiguration(true, true, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue());
+    public static GraphBuilderConfiguration getSnippetDefault(Plugins plugins) {
+        return new GraphBuilderConfiguration(true, true, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
     }
 
-    public static GraphBuilderConfiguration getFullDebugDefault() {
-        return new GraphBuilderConfiguration(true, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptLivenessAnalysis.getValue());
+    public static GraphBuilderConfiguration getFullDebugDefault(Plugins plugins) {
+        return new GraphBuilderConfiguration(true, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
     }
 
     /**
@@ -246,18 +257,4 @@
     public Plugins getPlugins() {
         return plugins;
     }
-
-    public void setPlugins(Plugins plugins) {
-        this.plugins = plugins;
-    }
-
-    public GraphBuilderConfiguration copyPluginsFrom(GraphBuilderConfiguration other) {
-        if (other.plugins != null) {
-            if (this.plugins == null) {
-                this.plugins = new Plugins(other.plugins.getInvocationPlugins().getMetaAccess());
-            }
-            this.plugins.updateFrom(other.plugins, true);
-        }
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java	Sun Mar 15 10:52:22 2015 +0100
@@ -193,7 +193,14 @@
     }
 
     protected final MetaAccessProvider metaAccess;
-    private final Map<MethodInfo, InvocationPlugin> registrations = new HashMap<>();
+
+    private final Map<MethodInfo, InvocationPlugin> registrations;
+
+    private final Thread registrationThread;
+
+    /**
+     * Null while registration is open, non-null when registration is closed.
+     */
     private volatile Map<ResolvedJavaMethod, InvocationPlugin> plugins;
 
     /**
@@ -201,8 +208,30 @@
      */
     private InvocationPlugins defaults;
 
+    /**
+     * Creates a set of invocation plugins with a given non-null set of plugins as the
+     * {@linkplain #getDefaults defaults}.
+     */
+    public InvocationPlugins(InvocationPlugins defaults) {
+        this.registrationThread = Thread.currentThread();
+        this.metaAccess = defaults.getMetaAccess();
+        this.registrations = new HashMap<>();
+        InvocationPlugins defs = defaults;
+        // Only adopt non-empty defaults
+        while (defs != null && defs.size() == 0) {
+            defs = defs.defaults;
+        }
+        this.defaults = defs;
+    }
+
     public InvocationPlugins(MetaAccessProvider metaAccess) {
+        this(metaAccess, 16);
+    }
+
+    public InvocationPlugins(MetaAccessProvider metaAccess, int estimatePluginCount) {
         this.metaAccess = metaAccess;
+        this.registrations = new HashMap<>(estimatePluginCount);
+        this.registrationThread = Thread.currentThread();
     }
 
     /**
@@ -210,11 +239,12 @@
      * registered for {@code method}.
      */
     public void register(InvocationPlugin plugin, Class<?> declaringClass, String name, Class<?>... argumentTypes) {
+        assert Thread.currentThread() == registrationThread : "invocation plugin registration must be single threaded";
         MethodInfo method = new MethodInfo(declaringClass, name, argumentTypes);
         assert Checker.check(method, plugin);
-        assert plugins == null;
+        assert plugins == null : "invocation plugin registration is closed";
         GraphBuilderPlugin oldValue = registrations.put(method, plugin);
-        assert oldValue == null;
+        assert oldValue == null : "a plugin is already registered for " + method;
     }
 
     /**
@@ -224,17 +254,23 @@
      * @return the plugin associated with {@code method} or {@code null} if none exists
      */
     public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) {
+        InvocationPlugin res = null;
         if (plugins == null) {
             synchronized (this) {
                 if (plugins == null) {
-                    plugins = new HashMap<>(registrations.size());
-                    for (Map.Entry<MethodInfo, InvocationPlugin> e : registrations.entrySet()) {
-                        plugins.put(e.getKey().resolve(metaAccess), e.getValue());
+                    if (registrations.isEmpty()) {
+                        plugins = Collections.emptyMap();
+                    } else {
+                        // System.out.println("resolving " + registrations.size() + " plugins");
+                        plugins = new HashMap<>(registrations.size());
+                        for (Map.Entry<MethodInfo, InvocationPlugin> e : registrations.entrySet()) {
+                            plugins.put(e.getKey().resolve(metaAccess), e.getValue());
+                        }
                     }
                 }
             }
         }
-        InvocationPlugin res = plugins.get(method);
+        res = plugins.get(method);
         if (res == null && defaults != null) {
             return defaults.lookupInvocation(method);
         }
@@ -242,24 +278,11 @@
     }
 
     /**
-     * Sets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} if a
+     * Gets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} if a
      * plugin is not found in this object.
      */
-    public InvocationPlugins setDefaults(InvocationPlugins defaults) {
-        assert defaults != this.defaults;
-        InvocationPlugins old = this.defaults;
-        this.defaults = defaults;
-        return old;
-    }
-
-    /**
-     * Adds all the plugins from {@code other} to this object.
-     */
-    public void updateFrom(InvocationPlugins other) {
-        this.registrations.putAll(other.registrations);
-        if (other.defaults != null) {
-            updateFrom(other.defaults);
-        }
+    public InvocationPlugins getDefaults() {
+        return defaults;
     }
 
     @Override
@@ -310,4 +333,8 @@
     public MetaAccessProvider getMetaAccess() {
         return metaAccess;
     }
+
+    public int size() {
+        return registrations.size();
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Sun Mar 15 10:52:22 2015 +0100
@@ -71,7 +71,8 @@
      */
     protected final ConcurrentMap<ResolvedJavaMethod, StructuredGraph> graphs;
 
-    public void completeInitialization(GraphBuilderConfiguration.Plugins plugins) {
+    public void setGraphBuilderPlugins(GraphBuilderConfiguration.Plugins plugins) {
+        assert this.graphBuilderPlugins == null;
         this.graphBuilderPlugins = plugins;
     }
 
@@ -640,10 +641,8 @@
                 if (MethodsElidedInSnippets != null && methodToParse.getSignature().getReturnKind() == Kind.Void && MethodFilter.matches(MethodsElidedInSnippets, methodToParse)) {
                     graph.addAfterFixed(graph.start(), graph.add(new ReturnNode(null)));
                 } else {
-                    GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
-                    Plugins plugins = new Plugins(metaAccess).updateFrom(replacements.graphBuilderPlugins, false);
-                    config.setPlugins(plugins);
-                    plugins.getInvocationPlugins().setDefaults(replacements.graphBuilderPlugins.getInvocationPlugins());
+                    Plugins plugins = new Plugins(replacements.graphBuilderPlugins);
+                    GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
                     if (args != null) {
                         plugins.setParameterPlugin(new ConstantBindingParameterPlugin(args, plugins.getParameterPlugin(), metaAccess, replacements.snippetReflection));
                     }
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Sun Mar 15 10:52:22 2015 +0100
@@ -43,8 +43,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.java.*;
-import com.oracle.graal.java.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.phases.*;
 import com.oracle.graal.nodes.*;
@@ -187,15 +185,11 @@
 
     private static CompilationResult compileMethod(ResolvedJavaMethod javaMethod) {
         Providers providers = getGraalProviders();
-        MetaAccessProvider metaAccess = providers.getMetaAccess();
         SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites();
         Suites suites = suitesProvider.createSuites();
         LIRSuites lirSuites = suitesProvider.createLIRSuites();
         removeInliningPhase(suites);
         StructuredGraph graph = new StructuredGraph(javaMethod, AllowAssumptions.NO);
-        GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault();
-        config.setPlugins(new Plugins(metaAccess));
-        new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.ALL, null).apply(graph);
         PhaseSuite<HighTierContext> graphBuilderSuite = getGraphBuilderSuite(suitesProvider);
         CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
         Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Sun Mar 15 10:52:22 2015 +0100
@@ -32,9 +32,10 @@
 public class ExactMathTest extends GraalCompilerTest {
 
     @Override
-    protected void editGraphBuilderPlugins(GraphBuilderConfiguration.Plugins plugins) {
-        TruffleGraphBuilderPlugins.registerExactMathPlugins(plugins.getInvocationPlugins());
-        super.editGraphBuilderPlugins(plugins);
+    protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
+        TruffleGraphBuilderPlugins.registerExactMathPlugins(conf.getPlugins().getInvocationPlugins());
+        super.editGraphBuilderConfiguration(conf);
+        return super.editGraphBuilderConfiguration(conf);
     }
 
     @Test
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Sun Mar 15 10:52:22 2015 +0100
@@ -260,7 +260,7 @@
         callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy()));
         plugins.setInlineInvokePlugin(new InlineInvokePlugin(callTarget.getInlining(), providers.getReplacements()));
         plugins.setLoopExplosionPlugin(new LoopExplosionPlugin());
-        TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), newConfig.getPlugins().getInvocationPlugins());
+        InvocationPlugins invocationPlugins = newConfig.getPlugins().getInvocationPlugins();
         new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig,
                         TruffleCompilerImpl.Optimizations, null).apply(graph);
         Debug.dump(graph, "After FastPE");
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Mar 12 22:19:27 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Sun Mar 15 10:52:22 2015 +0100
@@ -49,6 +49,7 @@
 import com.oracle.graal.printer.*;
 import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.nodes.*;
+import com.oracle.graal.truffle.substitutions.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.*;
 
@@ -89,15 +90,20 @@
         this.lirSuites = backend.getSuites().getDefaultLIRSuites();
 
         ResolvedJavaType[] skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess());
-        GraphBuilderConfiguration eagerConfig = GraphBuilderConfiguration.getEagerDefault().withSkippedExceptionTypes(skippedExceptionTypes);
 
-        this.config = GraphBuilderConfiguration.getDefault().withSkippedExceptionTypes(skippedExceptionTypes);
-        this.config.setPlugins(new Plugins(backendProviders.getMetaAccess()));
+        Plugins plugins;
         if (TruffleCompilerOptions.FastPE.getValue()) {
             GraphBuilderPhase phase = (GraphBuilderPhase) backend.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous();
-            this.config.getPlugins().getInvocationPlugins().setDefaults(phase.getGraphBuilderConfig().getPlugins().getInvocationPlugins());
+            InvocationPlugins invocationPlugins = new InvocationPlugins(phase.getGraphBuilderConfig().getPlugins().getInvocationPlugins());
+            plugins = new Plugins(invocationPlugins);
+            TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), invocationPlugins);
+        } else {
+            plugins = new Plugins(new InvocationPlugins(backendProviders.getMetaAccess()));
         }
 
+        this.config = GraphBuilderConfiguration.getDefault(plugins).withSkippedExceptionTypes(skippedExceptionTypes);
+
+        GraphBuilderConfiguration eagerConfig = GraphBuilderConfiguration.getEagerDefault(plugins).withSkippedExceptionTypes(skippedExceptionTypes);
         this.truffleCache = new TruffleCacheImpl(providers, eagerConfig, TruffleCompilerImpl.Optimizations);
 
         this.partialEvaluator = new PartialEvaluator(providers, config, truffleCache, Graal.getRequiredCapability(SnippetReflectionProvider.class));