changeset 19440:d59f813786f6

Merge and merge fixes.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 17 Feb 2015 01:16:35 +0100
parents 5be35dd0a9dd (current diff) 0725ec2b1f3f (diff)
children a207d92b0b40
files graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.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/InvocationPlugins.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 20 files changed, 294 insertions(+), 149 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Feb 17 01:16:35 2015 +0100
@@ -800,8 +800,10 @@
     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();
+        GraphBuilderConfiguration gbConfCopy = gbConf.copy().copyPluginsFrom(graphBuilderPhase.getGraphBuilderConfig());
         iterator.remove();
-        iterator.add(new GraphBuilderPhase(gbConf));
+        iterator.add(new GraphBuilderPhase(gbConfCopy));
         return suite;
     }
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Feb 17 01:16:35 2015 +0100
@@ -161,6 +161,14 @@
          * ignored and can therefore safely be {@code null}.
          */
         boolean setStampFromReturnType() default false;
+
+        /**
+         * Determines if this intrinsic can be compile-time executed. An attempt to execute a call
+         * (via reflection) to this intrinsic at compile-time will be made if all of its arguments
+         * are compile-time constant. If the execution succeeds without an exception, the result is
+         * inserted as a constant node in the graph.
+         */
+        boolean foldable() default false;
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Feb 17 01:16:35 2015 +0100
@@ -163,7 +163,7 @@
                 disassembler = createDisassembler(runtime);
             }
             try (InitTimer rt = timer("create Suites provider")) {
-                suites = createSuites(runtime);
+                suites = createSuites(runtime, metaAccess, constantReflection, replacements);
             }
             providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection);
         }
@@ -209,8 +209,8 @@
         return new HotSpotMetaAccessProvider(runtime);
     }
 
-    protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime) {
-        return new HotSpotSuitesProvider(runtime);
+    protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) {
+        return new HotSpotSuitesProvider(runtime, metaAccess, constantReflection, replacements);
     }
 
     protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime) {
@@ -248,15 +248,15 @@
         } else {
             /*
              * System V Application Binary Interface, AMD64 Architecture Processor Supplement
-             * 
+             *
              * Draft Version 0.96
-             * 
+             *
              * http://www.uclibc.org/docs/psABI-x86_64.pdf
-             * 
+             *
              * 3.2.1
-             * 
+             *
              * ...
-             * 
+             *
              * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12
              * through %r15 "belong" to the calling function and the called function is required to
              * preserve their values. In other words, a called function must preserve these
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Tue Feb 17 01:16:35 2015 +0100
@@ -64,7 +64,7 @@
         HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime);
         HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), target);
         HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime);
-        HotSpotSuitesProvider suites = new HotSpotSuitesProvider(runtime);
+        HotSpotSuitesProvider suites = new HotSpotSuitesProvider(runtime, metaAccess, constantReflection, replacements);
         HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection);
 
         return new SPARCHotSpotBackend(runtime, providers);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Tue Feb 17 01:16:35 2015 +0100
@@ -69,7 +69,7 @@
         try (InitTimer st = timer("graphBuilderPlugins.initialize")) {
             GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous();
             InvocationPlugins plugins = phase.getGraphBuilderConfig().getInvocationPlugins();
-            registerGraphBuilderPlugins(providers.getMetaAccess(), plugins);
+            registerInvocationPlugins(providers.getMetaAccess(), plugins);
         }
 
         try (InitTimer st = timer("foreignCalls.initialize")) {
@@ -101,8 +101,8 @@
         }
     }
 
-    protected void registerGraphBuilderPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
-        StandardGraphBuilderPlugins.registerPlugins(metaAccess, plugins);
-        HotSpotGraphBuilderPlugins.registerPlugins(metaAccess, plugins);
+    protected void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
+        StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, plugins);
+        HotSpotGraphBuilderPlugins.registerInvocationPlugins(metaAccess, plugins);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Tue Feb 17 01:16:35 2015 +0100
@@ -39,10 +39,10 @@
 import com.oracle.graal.options.*;
 
 /**
- * Provider of HotSpot specific {@link GraphBuilderPlugin}s.
+ * Provides HotSpot specific {@link InvocationPlugin}s.
  */
 public class HotSpotGraphBuilderPlugins {
-    public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
+    public static void registerInvocationPlugins(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	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Tue Feb 17 01:16:35 2015 +0100
@@ -25,15 +25,17 @@
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode;
 import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin;
+import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin;
 import com.oracle.graal.lir.phases.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.options.DerivedOptionValue.OptionSupplier;
 import com.oracle.graal.phases.*;
@@ -69,9 +71,9 @@
 
     }
 
-    public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime) {
+    public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) {
         this.runtime = runtime;
-        this.defaultGraphBuilderSuite = createGraphBuilderSuite();
+        this.defaultGraphBuilderSuite = createGraphBuilderSuite(metaAccess, constantReflection, replacements);
         this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier());
         this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier());
     }
@@ -103,18 +105,40 @@
         return ret;
     }
 
-    protected PhaseSuite<HighTierContext> createGraphBuilderSuite() {
+    protected PhaseSuite<HighTierContext> createGraphBuilderSuite(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) {
         PhaseSuite<HighTierContext> suite = new PhaseSuite<>();
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault();
-        config.setInlineInvokePlugin(new InlineInvokePlugin() {
-            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;
+        if (InlineDuringParsing.getValue()) {
+            config.setLoadFieldPlugin(new LoadFieldPlugin() {
+                public boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) {
+                    if (receiver.isConstant()) {
+                        JavaConstant asJavaConstant = receiver.asJavaConstant();
+                        return tryConstantFold(builder, metaAccess, constantReflection, field, asJavaConstant);
+                    }
+                    return false;
+                }
+
+                public boolean apply(GraphBuilderContext builder, ResolvedJavaField staticField) {
+                    return tryConstantFold(builder, metaAccess, constantReflection, staticField, null);
                 }
-                return null;
-            }
-        });
+            });
+            config.setInlineInvokePlugin(new InlineInvokePlugin() {
+                public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType, int depth) {
+                    if (builder.parsingReplacement()) {
+                        if (method.getAnnotation(MethodSubstitution.class) != null) {
+                            ResolvedJavaMethod subst = replacements.getMethodSubstitutionMethod(method);
+                            if (subst != null) {
+                                return subst;
+                            }
+                        }
+                    }
+                    if (method.hasBytecodes() && method.getCode().length <= TrivialInliningSize.getValue() && depth < InlineDuringParsingMaxDepth.getValue()) {
+                        return method;
+                    }
+                    return null;
+                }
+            });
+        }
         suite.appendPhase(new GraphBuilderPhase(config));
         return suite;
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Tue Feb 17 01:16:35 2015 +0100
@@ -76,11 +76,17 @@
     protected final MetaAccessProvider metaAccess;
 
     /**
+     * Specifies if the {@linkplain #getMethod() method} being parsed implements the semantics of
+     * another method (i.e., an intrinsic) or bytecode instruction (i.e., a snippet). substitution.
+     */
+    protected final boolean parsingReplacement;
+
+    /**
      * Meters the number of actual bytecodes parsed.
      */
     public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed");
 
-    public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
+    public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, boolean isReplacement) {
         this.graphBuilderConfig = graphBuilderConfig;
         this.optimisticOpts = optimisticOpts;
         this.metaAccess = metaAccess;
@@ -88,6 +94,7 @@
         this.profilingInfo = (graphBuilderConfig.getUseProfiling() ? method.getProfilingInfo() : null);
         this.constantPool = method.getConstantPool();
         this.method = method;
+        this.parsingReplacement = isReplacement;
         assert metaAccess != null;
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java	Tue Feb 17 01:16:35 2015 +0100
@@ -32,7 +32,7 @@
 
 public class GraalDirectivePlugins {
 
-    public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
+    public static void registerInvocationPlugins(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	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Tue Feb 17 01:16:35 2015 +0100
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.java.GraphBuilderPlugin.AnnotatedInvocationPlugin;
 import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin;
 import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin;
 import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin;
@@ -44,6 +45,7 @@
     private LoadFieldPlugin loadFieldPlugin;
     private ParameterPlugin parameterPlugin;
     private InlineInvokePlugin inlineInvokePlugin;
+    private AnnotatedInvocationPlugin annotatedInvocationPlugin;
     private LoopExplosionPlugin loopExplosionPlugin;
     private boolean useProfiling;
 
@@ -82,11 +84,8 @@
 
     public GraphBuilderConfiguration copy() {
         GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis);
-        result.loadFieldPlugin = loadFieldPlugin;
-        result.invocationPlugins = invocationPlugins;
-        result.loopExplosionPlugin = loopExplosionPlugin;
-        result.inlineInvokePlugin = inlineInvokePlugin;
         result.useProfiling = useProfiling;
+        result.copyPluginsFrom(this);
         return result;
     }
 
@@ -119,12 +118,20 @@
         return invocationPlugins;
     }
 
+    public AnnotatedInvocationPlugin getAnnotatedInvocationPlugin() {
+        return annotatedInvocationPlugin;
+    }
+
+    public void setAnnotatedInvocationPlugin(AnnotatedInvocationPlugin plugin) {
+        this.annotatedInvocationPlugin = plugin;
+    }
+
     public LoadFieldPlugin getLoadFieldPlugin() {
         return loadFieldPlugin;
     }
 
-    public void setLoadFieldPlugin(LoadFieldPlugin loadFieldPlugin) {
-        this.loadFieldPlugin = loadFieldPlugin;
+    public void setLoadFieldPlugin(LoadFieldPlugin plugin) {
+        this.loadFieldPlugin = plugin;
     }
 
     public ResolvedJavaType[] getSkippedExceptionTypes() {
@@ -180,23 +187,33 @@
         return parameterPlugin;
     }
 
-    public void setParameterPlugin(ParameterPlugin parameterPlugin) {
-        this.parameterPlugin = parameterPlugin;
+    public void setParameterPlugin(ParameterPlugin plugin) {
+        this.parameterPlugin = plugin;
     }
 
     public InlineInvokePlugin getInlineInvokePlugin() {
         return inlineInvokePlugin;
     }
 
-    public void setInlineInvokePlugin(InlineInvokePlugin inlineInvokePlugin) {
-        this.inlineInvokePlugin = inlineInvokePlugin;
+    public void setInlineInvokePlugin(InlineInvokePlugin plugin) {
+        this.inlineInvokePlugin = plugin;
     }
 
     public LoopExplosionPlugin getLoopExplosionPlugin() {
         return loopExplosionPlugin;
     }
 
-    public void setLoopExplosionPlugin(LoopExplosionPlugin loopExplosionPlugin) {
-        this.loopExplosionPlugin = loopExplosionPlugin;
+    public void setLoopExplosionPlugin(LoopExplosionPlugin plugin) {
+        this.loopExplosionPlugin = plugin;
+    }
+
+    public GraphBuilderConfiguration copyPluginsFrom(GraphBuilderConfiguration other) {
+        this.invocationPlugins.updateFrom(other.getInvocationPlugins());
+        this.parameterPlugin = other.parameterPlugin;
+        this.loadFieldPlugin = other.loadFieldPlugin;
+        this.inlineInvokePlugin = other.inlineInvokePlugin;
+        this.loopExplosionPlugin = other.loopExplosionPlugin;
+        this.annotatedInvocationPlugin = other.annotatedInvocationPlugin;
+        return this;
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Tue Feb 17 01:16:35 2015 +0100
@@ -57,6 +57,11 @@
     void push(Kind kind, ValueNode value);
 
     /**
+     * Determines if the graph builder is parsing a snippet or method substitution.
+     */
+    boolean parsingReplacement();
+
+    /**
      * @see GuardingPiNode#nullCheckedValue(ValueNode)
      */
     static ValueNode nullCheckedValue(GraphBuilderContext builder, ValueNode value) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 17 01:16:35 2015 +0100
@@ -26,6 +26,8 @@
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.nodes.StructuredGraph.*;
+import static java.lang.String.*;
 
 import java.util.*;
 
@@ -45,6 +47,7 @@
 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.GraphBuilderPlugin.AnnotatedInvocationPlugin;
 import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin;
 import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin;
 import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin;
@@ -72,7 +75,7 @@
 
     @Override
     protected void run(StructuredGraph graph, HighTierContext context) {
-        new Instance(context.getMetaAccess(), context.getStampProvider(), null, null, context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph);
+        new Instance(context.getMetaAccess(), context.getStampProvider(), null, context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph);
     }
 
     public GraphBuilderConfiguration getGraphBuilderConfig() {
@@ -93,8 +96,6 @@
         private final ConstantReflectionProvider constantReflection;
         private final SnippetReflectionProvider snippetReflectionProvider;
 
-        private final Replacements replacements;
-
         /**
          * Gets the graph being processed by this builder.
          */
@@ -102,21 +103,20 @@
             return currentGraph;
         }
 
-        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, Replacements replacements,
-                        ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
+        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, ConstantReflectionProvider constantReflection,
+                        GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
             this.graphBuilderConfig = graphBuilderConfig;
             this.optimisticOpts = optimisticOpts;
             this.metaAccess = metaAccess;
             this.stampProvider = stampProvider;
             this.constantReflection = constantReflection;
             this.snippetReflectionProvider = snippetReflectionProvider;
-            this.replacements = replacements;
             assert metaAccess != null;
         }
 
         public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig,
                         OptimisticOptimizations optimisticOpts) {
-            this(metaAccess, stampProvider, null, null, constantReflection, graphBuilderConfig, optimisticOpts);
+            this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, optimisticOpts);
         }
 
         @Override
@@ -130,7 +130,7 @@
             frameState.initializeForMethodStart(graphBuilderConfig.eagerResolving(), this.graphBuilderConfig.getParameterPlugin());
             TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
             try {
-                BytecodeParser parser = new BytecodeParser(metaAccess, method, graphBuilderConfig, optimisticOpts, entryBCI);
+                BytecodeParser parser = new BytecodeParser(metaAccess, method, graphBuilderConfig, optimisticOpts, entryBCI, false);
                 parser.build(0, graph.start(), frameState);
 
                 parser.connectLoopEndToBegin();
@@ -198,8 +198,14 @@
             private int returnCount;
             private boolean controlFlowSplit;
 
-            public BytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, int entryBCI) {
-                super(metaAccess, method, graphBuilderConfig, optimisticOpts);
+            /**
+             * @param isReplacement specifies if this object is being used to parse a method that
+             *            implements the semantics of another method (i.e., an intrinsic) or
+             *            bytecode instruction (i.e., a snippet)
+             */
+            public BytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, int entryBCI,
+                            boolean isReplacement) {
+                super(metaAccess, method, graphBuilderConfig, optimisticOpts, isReplacement);
                 this.entryBCI = entryBCI;
 
                 if (graphBuilderConfig.insertNonSafepointDebugInfo()) {
@@ -857,45 +863,30 @@
                     }
                 }
 
-                if (tryUsingInvocationPlugin(args, targetMethod, resultType)) {
+                if (tryInvocationPlugin(args, targetMethod, resultType)) {
                     if (GraalOptions.TraceInlineDuringParsing.getValue()) {
-                        for (int i = 0; i < this.currentDepth; ++i) {
-                            TTY.print(' ');
-                        }
-                        TTY.println("Used invocation plugin for " + targetMethod);
+                        TTY.println(format("%sUsed invocation plugin for %s", nSpaces(currentDepth), 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))) {
+                if (tryAnnotatedInvocationPlugin(args, targetMethod)) {
+                    System.out.println("plugin used for : " + targetMethod);
+                    if (GraalOptions.TraceInlineDuringParsing.getValue()) {
+                        TTY.println(format("%sUsed annotated invocation plugin for %s", nSpaces(currentDepth), targetMethod));
+                    }
+                    return;
+                }
 
-                    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(' ');
-                            }
-                            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;
-                    }
+                if (tryInline(args, targetMethod, invokeKind, returnType)) {
+                    return;
                 }
 
                 MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType));
 
                 // be conservative if information was not recorded (could result in endless
                 // recompiles otherwise)
-                if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) {
+                if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo != null && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) {
                     createInvoke(callTarget, resultType);
                 } else {
                     InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType);
@@ -905,7 +896,7 @@
                 }
             }
 
-            private boolean tryUsingInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) {
+            private boolean tryInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) {
                 InvocationPlugin plugin = graphBuilderConfig.getInvocationPlugins().lookupInvocation(targetMethod);
                 if (plugin != null) {
                     int beforeStackSize = frameState.stackSize;
@@ -923,6 +914,11 @@
                 return false;
             }
 
+            private boolean tryAnnotatedInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod) {
+                AnnotatedInvocationPlugin plugin = graphBuilderConfig.getAnnotatedInvocationPlugin();
+                return plugin != null && plugin.apply(this, targetMethod, args);
+            }
+
             private boolean containsNullCheckOf(NodeIterable<Node> nodes, Node value) {
                 for (Node n : nodes) {
                     if (n instanceof GuardingPiNode) {
@@ -935,8 +931,28 @@
                 return false;
             }
 
-            private void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args) {
-                BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, StructuredGraph.INVOCATION_ENTRY_BCI);
+            private boolean tryInline(ValueNode[] args, ResolvedJavaMethod targetMethod, InvokeKind invokeKind, JavaType returnType) {
+                InlineInvokePlugin plugin = graphBuilderConfig.getInlineInvokePlugin();
+                if (plugin == null || !invokeKind.isDirect() || !targetMethod.canBeInlined()) {
+                    return false;
+                }
+                ResolvedJavaMethod inlinedMethod = plugin.getInlinedMethod(this, targetMethod, args, returnType, currentDepth);
+                if (inlinedMethod != null && inlinedMethod.hasBytecodes()) {
+                    if (TraceInlineDuringParsing.getValue()) {
+                        int bci = this.bci();
+                        StackTraceElement ste = this.method.asStackTraceElement(bci);
+                        TTY.println(format("%s%s (%s:%d) inlining call to %s", nSpaces(currentDepth), method.getName(), ste.getFileName(), ste.getLineNumber(), inlinedMethod.format("%h.%n(%p)")));
+                    }
+                    parseAndInlineCallee(inlinedMethod, args, parsingReplacement || !inlinedMethod.equals(targetMethod));
+                    plugin.postInline(inlinedMethod);
+                    return true;
+                }
+
+                return false;
+            }
+
+            private void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, boolean isReplacement) {
+                BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, INVOCATION_ENTRY_BCI, isReplacement);
                 final FrameState[] lazyFrameState = new FrameState[1];
                 HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, () -> {
                     if (lazyFrameState[0] == null) {
@@ -1249,7 +1265,7 @@
                                 // time mark the context loop begin as hit during the current
                                 // iteration.
                                 context.targetPeelIteration = nextPeelIteration++;
-                                if (nextPeelIteration > GraalOptions.MaximumLoopExplosionCount.getValue()) {
+                                if (nextPeelIteration > MaximumLoopExplosionCount.getValue()) {
                                     throw new BailoutException("too many loop explosion interations - does the explosion not terminate?");
                                 }
                             }
@@ -1824,6 +1840,13 @@
                 return snippetReflectionProvider;
             }
 
+            public boolean parsingReplacement() {
+                return parsingReplacement;
+            }
         }
     }
+
+    static String nSpaces(int n) {
+        return n == 0 ? "" : format("%" + n + "s", "");
+    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java	Tue Feb 17 01:16:35 2015 +0100
@@ -181,6 +181,16 @@
         return old;
     }
 
+    /**
+     * Adds all the plugins from {@code other} to this object.
+     */
+    public void updateFrom(InvocationPlugins other) {
+        this.plugins.putAll(other.plugins);
+        if (other.defaults != null) {
+            updateFrom(other.defaults);
+        }
+    }
+
     @Override
     public String toString() {
         return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")) + " / defaults: " + this.defaults;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java	Tue Feb 17 01:16:35 2015 +0100
@@ -34,10 +34,10 @@
 import com.oracle.graal.nodes.java.*;
 
 /**
- * Provider of non-runtime specific {@link GraphBuilderPlugin}s.
+ * Provides non-runtime specific {@link InvocationPlugin}s.
  */
 public class StandardGraphBuilderPlugins {
-    public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
+    public static void registerInvocationPlugins(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) {
@@ -75,7 +75,7 @@
             }
         }
 
-        GraalDirectivePlugins.registerPlugins(metaAccess, plugins);
+        GraalDirectivePlugins.registerInvocationPlugins(metaAccess, plugins);
     }
 
     static class BoxPlugin implements InvocationPlugin {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Tue Feb 17 01:16:35 2015 +0100
@@ -73,6 +73,13 @@
     StructuredGraph getMethodSubstitution(ResolvedJavaMethod method);
 
     /**
+     * Gets the method that is a substitution for a given method.
+     *
+     * @return the method, if any, that is a substitution for {@code method}
+     */
+    ResolvedJavaMethod getMethodSubstitutionMethod(ResolvedJavaMethod method);
+
+    /**
      * Gets the node class with which a method invocation should be replaced.
      *
      * @param method target of an invocation
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Feb 17 01:16:35 2015 +0100
@@ -80,21 +80,12 @@
 
         NodeIntrinsic intrinsic = getIntrinsic(target);
         if (intrinsic != null) {
-            assert target.getAnnotation(Fold.class) == null;
-            assert target.isStatic() : "node intrinsic must be static: " + target;
-
-            ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass);
-
-            // Prepare the arguments for the reflective constructor call on the node class.
-            Object[] nodeConstructorArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false);
-            if (nodeConstructorArguments == null) {
+            Stamp stamp = methodCallTargetNode.invoke().asNode().stamp();
+            Node newInstance = createIntrinsicNode(methodCallTargetNode.arguments(), stamp, target, graph, intrinsic);
+            if (newInstance == null) {
                 return false;
             }
 
-            // Create the new node instance.
-            ResolvedJavaType c = getNodeClass(target, intrinsic);
-            Node newInstance = createNodeInstance(graph, c, parameterTypes, methodCallTargetNode.invoke().asNode().stamp(), intrinsic.setStampFromReturnType(), nodeConstructorArguments);
-
             // Replace the invoke with the new node.
             newInstance = graph.addOrUnique(newInstance);
             methodCallTargetNode.invoke().intrinsify(newInstance);
@@ -103,21 +94,10 @@
             cleanUpReturnList.add(newInstance);
         } else if (isFoldable(target)) {
             ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass);
-
-            // Prepare the arguments for the reflective method call
-            JavaConstant[] arguments = (JavaConstant[]) prepareArguments(methodCallTargetNode, parameterTypes, target, true);
-            if (arguments == null) {
+            JavaConstant constant = tryFold(methodCallTargetNode.arguments(), parameterTypes, target);
+            if (constant != null && constant.equals(COULD_NOT_FOLD)) {
                 return false;
             }
-            JavaConstant receiver = null;
-            if (!methodCallTargetNode.isStatic()) {
-                receiver = arguments[0];
-                arguments = Arrays.copyOfRange(arguments, 1, arguments.length);
-                parameterTypes = Arrays.copyOfRange(parameterTypes, 1, parameterTypes.length);
-            }
-
-            // Call the method
-            JavaConstant constant = target.invoke(receiver, arguments);
 
             if (constant != null) {
                 // Replace the invoke with the result of the call
@@ -134,6 +114,72 @@
         return true;
     }
 
+    @SuppressWarnings("serial") private static final JavaConstant COULD_NOT_FOLD = new PrimitiveConstant(Kind.Illegal, 100) {
+        @Override
+        public boolean equals(Object o) {
+            return this == o;
+        }
+    };
+
+    public JavaConstant tryFold(List<ValueNode> args, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target) {
+        JavaConstant[] reflectArgs = (JavaConstant[]) prepareArguments(args, parameterTypes, target, true);
+        if (reflectArgs == null) {
+            return COULD_NOT_FOLD;
+        }
+        JavaConstant receiver = null;
+        if (!target.isStatic()) {
+            receiver = reflectArgs[0];
+            reflectArgs = Arrays.copyOfRange(reflectArgs, 1, reflectArgs.length);
+        }
+
+        // Call the method
+        return target.invoke(receiver, reflectArgs);
+    }
+
+    private static boolean areAllConstant(List<ValueNode> arguments) {
+        for (ValueNode arg : arguments) {
+            if (!arg.isConstant()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Attempts to create a node to replace a call to a {@link NodeIntrinsic} annotated method.
+     *
+     * @param arguments the arguments of the call
+     * @param stamp the stamp to use for the returned node
+     * @param method the method annotated with {@link NodeIntrinsic}
+     * @param graph the graph into which the created node will be added
+     * @return a {@link ConstantNode} if the intrinsic could be
+     *         {@linkplain NodeIntrinsic#foldable() folded}, {@code null} if intrinsification could
+     *         not (yet) be performed, otherwise the node representing the intrinsic
+     */
+    public ValueNode createIntrinsicNode(List<ValueNode> arguments, Stamp stamp, ResolvedJavaMethod method, StructuredGraph graph, NodeIntrinsic intrinsic) {
+        assert method.getAnnotation(Fold.class) == null;
+        assert method.isStatic() : "node intrinsic must be static: " + method;
+
+        ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass());
+
+        if (intrinsic.foldable() && areAllConstant(arguments)) {
+            JavaConstant res = tryFold(arguments, parameterTypes, method);
+            if (!res.equals(COULD_NOT_FOLD)) {
+                return ConstantNode.forConstant(res, providers.getMetaAccess());
+            }
+        }
+
+        // Prepare the arguments for the reflective constructor call on the node class.
+        Object[] nodeConstructorArguments = prepareArguments(arguments, parameterTypes, method, false);
+        if (nodeConstructorArguments == null) {
+            return null;
+        }
+
+        // Create the new node instance.
+        ResolvedJavaType c = getNodeClass(method, intrinsic);
+        return createNodeInstance(graph, c, parameterTypes, stamp, intrinsic.setStampFromReturnType(), nodeConstructorArguments);
+    }
+
     /**
      * Permits a subclass to override the default definition of "intrinsic".
      */
@@ -156,12 +202,11 @@
      * @return the arguments for the reflective invocation or null if an argument of {@code invoke}
      *         that is expected to be constant isn't
      */
-    private Object[] prepareArguments(MethodCallTargetNode methodCallTargetNode, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
-        NodeInputList<ValueNode> arguments = methodCallTargetNode.arguments();
+    private Object[] prepareArguments(List<ValueNode> arguments, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
         Object[] reflectionCallArguments = folding ? new JavaConstant[arguments.size()] : new Object[arguments.size()];
         for (int i = 0; i < reflectionCallArguments.length; ++i) {
             int parameterIndex = i;
-            if (!methodCallTargetNode.isStatic()) {
+            if (!target.isStatic()) {
                 parameterIndex--;
             }
             ValueNode argument = arguments.get(i);
@@ -226,7 +271,7 @@
         return result;
     }
 
-    protected Node createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType,
+    protected ValueNode createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType,
                     Object[] nodeConstructorArguments) {
         ResolvedJavaMethod constructor = null;
         Object[] arguments = null;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Feb 17 01:16:35 2015 +0100
@@ -64,6 +64,7 @@
     public final Providers providers;
     public final SnippetReflectionProvider snippetReflection;
     public final TargetDescription target;
+    public final NodeIntrinsificationPhase nodeIntrinsificationPhase;
 
     /**
      * The preprocessed replacement graphs.
@@ -227,6 +228,7 @@
         this.target = target;
         this.graphs = new ConcurrentHashMap<>();
         this.snippetTemplateCache = CollectionsFactory.newMap();
+        this.nodeIntrinsificationPhase = createNodeIntrinsificationPhase();
     }
 
     private static final boolean UseSnippetGraphCache = Boolean.parseBoolean(System.getProperty("graal.useSnippetGraphCache", "true"));
@@ -285,7 +287,7 @@
 
         // Do deferred intrinsification of node intrinsics
 
-        createNodeIntrinsificationPhase().apply(specializedSnippet);
+        nodeIntrinsificationPhase.apply(specializedSnippet);
         new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers));
         NodeIntrinsificationVerificationPhase.verify(specializedSnippet);
     }
@@ -531,7 +533,7 @@
          * Does final processing of a snippet graph.
          */
         protected void finalizeGraph(StructuredGraph graph) {
-            replacements.createNodeIntrinsificationPhase().apply(graph);
+            replacements.nodeIntrinsificationPhase.apply(graph);
             if (!SnippetTemplate.hasConstantParameter(method)) {
                 NodeIntrinsificationVerificationPhase.verify(graph);
             }
@@ -666,7 +668,7 @@
          * Called after all inlining for a given graph is complete.
          */
         protected void afterInlining(StructuredGraph graph) {
-            replacements.createNodeIntrinsificationPhase().apply(graph);
+            replacements.nodeIntrinsificationPhase.apply(graph);
             new DeadCodeEliminationPhase(Optional).apply(graph);
             if (OptCanonicalizer.getValue()) {
                 new CanonicalizerPhase(true).apply(graph, new PhaseContext(replacements.providers));
@@ -828,6 +830,12 @@
     }
 
     @Override
+    public ResolvedJavaMethod getMethodSubstitutionMethod(ResolvedJavaMethod original) {
+        ClassReplacements cr = getClassReplacements(original.getDeclaringClass().getName());
+        return cr == null ? null : cr.methodSubstitutions.get(original);
+    }
+
+    @Override
     public void registerSnippetTemplateCache(SnippetTemplateCache templates) {
         assert snippetTemplateCache.get(templates.getClass().getName()) == null;
         snippetTemplateCache.put(templates.getClass().getName(), templates);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Feb 17 01:16:35 2015 +0100
@@ -152,17 +152,7 @@
         public boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) {
             if (receiver.isConstant()) {
                 JavaConstant asJavaConstant = receiver.asJavaConstant();
-                return tryConstantFold(builder, field, asJavaConstant);
-            }
-            return false;
-        }
-
-        private boolean tryConstantFold(GraphBuilderContext builder, ResolvedJavaField field, JavaConstant asJavaConstant) {
-            JavaConstant result = providers.getConstantReflection().readConstantFieldValue(field, asJavaConstant);
-            if (result != null) {
-                ConstantNode constantNode = builder.append(ConstantNode.forConstant(result, providers.getMetaAccess()));
-                builder.push(constantNode.getKind().getStackKind(), constantNode);
-                return true;
+                return tryConstantFold(builder, providers.getMetaAccess(), providers.getConstantReflection(), field, asJavaConstant);
             }
             return false;
         }
@@ -173,7 +163,7 @@
                 builder.push(trueNode.getKind().getStackKind(), trueNode);
                 return true;
             }
-            return tryConstantFold(builder, staticField, null);
+            return tryConstantFold(builder, providers.getMetaAccess(), providers.getConstantReflection(), staticField, null);
         }
     }
 
@@ -197,16 +187,21 @@
 
         private Stack<TruffleInlining> inlining;
         private OptimizedDirectCallNode lastDirectCallNode;
+        private final Replacements replacements;
 
-        public InlineInvokePlugin(TruffleInlining inlining) {
+        public InlineInvokePlugin(TruffleInlining inlining, Replacements replacements) {
             this.inlining = new Stack<>();
             this.inlining.push(inlining);
+            this.replacements = replacements;
         }
 
         public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType, int depth) {
             if (original.getAnnotation(TruffleBoundary.class) != null) {
                 return null;
             }
+            if (replacements != null && (replacements.getMethodSubstitutionMethod(original) != null || replacements.getMacroSubstitution(original) != null)) {
+                return null;
+            }
             if (original.equals(callSiteProxyMethod)) {
                 ValueNode arg1 = arguments[0];
                 if (!arg1.isConstant()) {
@@ -252,12 +247,11 @@
         newConfig.setLoadFieldPlugin(new InterceptLoadFieldPlugin());
         newConfig.setParameterPlugin(new InterceptReceiverPlugin(callTarget));
         callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy()));
-        newConfig.setInlineInvokePlugin(new InlineInvokePlugin(callTarget.getInlining()));
+        newConfig.setInlineInvokePlugin(new InlineInvokePlugin(callTarget.getInlining(), providers.getReplacements()));
         newConfig.setLoopExplosionPlugin(new LoopExplosionPlugin());
-        TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), newConfig.getInvocationPlugins());
+        TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), newConfig.getInvocationPlugins());
         long ms = System.currentTimeMillis();
-        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getReplacements(), providers.getConstantReflection(), newConfig,
-                        TruffleCompilerImpl.Optimizations).apply(graph);
+        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig, 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	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Feb 17 01:16:35 2015 +0100
@@ -81,8 +81,12 @@
         this.compilationNotify = graalTruffleRuntime.getCompilationNotify();
         this.backend = runtime.getHostBackend();
         Replacements truffleReplacements = graalTruffleRuntime.getReplacements();
-        ConstantReflectionProvider constantReflection = new TruffleConstantReflectionProvider(backend.getProviders().getConstantReflection(), backend.getProviders().getMetaAccess());
-        this.providers = backend.getProviders().copyWith(truffleReplacements).copyWith(constantReflection);
+        Providers backendProviders = backend.getProviders();
+        ConstantReflectionProvider constantReflection = new TruffleConstantReflectionProvider(backendProviders.getConstantReflection(), backendProviders.getMetaAccess());
+        if (!TruffleCompilerOptions.FastPE.getValue()) {
+            backendProviders = backendProviders.copyWith(truffleReplacements);
+        }
+        this.providers = backendProviders.copyWith(constantReflection);
         this.suites = backend.getSuites().getDefaultSuites();
         this.lirSuites = backend.getSuites().getDefaultLIRSuites();
 
@@ -93,6 +97,7 @@
         if (TruffleCompilerOptions.FastPE.getValue()) {
             GraphBuilderPhase phase = (GraphBuilderPhase) backend.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous();
             this.config.getInvocationPlugins().setDefaults(phase.getGraphBuilderConfig().getInvocationPlugins());
+            System.out.println("!!" + config.getInvocationPlugins());
         }
 
         this.truffleCache = new TruffleCacheImpl(providers, eagerConfig, TruffleCompilerImpl.Optimizations);
@@ -209,16 +214,6 @@
         return result;
     }
 
-    static class GraphBuilderSuiteInfo {
-        final PhaseSuite<HighTierContext> suite;
-        final InvocationPlugins plugins;
-
-        public GraphBuilderSuiteInfo(PhaseSuite<HighTierContext> suite, InvocationPlugins plugins) {
-            this.suite = suite;
-            this.plugins = plugins;
-        }
-    }
-
     private PhaseSuite<HighTierContext> createGraphBuilderSuite() {
         PhaseSuite<HighTierContext> suite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
         ListIterator<BasePhase<? super HighTierContext>> iterator = suite.findPhase(GraphBuilderPhase.class);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Tue Feb 17 00:22:26 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Tue Feb 17 01:16:35 2015 +0100
@@ -47,10 +47,10 @@
 import com.oracle.truffle.api.frame.*;
 
 /**
- * Provider of {@link GraphBuilderPlugin}s for Truffle classes.
+ * Provides {@link InvocationPlugin}s for Truffle classes.
  */
 public class TruffleGraphBuilderPlugins {
-    public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
+    public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
 
         // OptimizedAssumption.class
         Registration r = new Registration(plugins, metaAccess, OptimizedAssumption.class);