changeset 19050:75da87c96605

initial commit of GraphBuilderPhase plugins
author Doug Simon <doug.simon@oracle.com>
date Sat, 31 Jan 2015 00:30:00 +0100
parents c198e397bb59
children db390d92bb16
files graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.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/ea/EATestBase.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysisTests.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPluginsProvider.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.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/src/com/oracle/graal/truffle/TruffleCacheImpl.java mx/suite.py
diffstat 21 files changed, 470 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Sat Jan 31 00:30:00 2015 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 
 /**
@@ -50,7 +51,7 @@
     private final GraphBuilderConfiguration graphBuilderConfig;
 
     public CompilationResult generate(ResolvedJavaMethod method, int entryBCI, Backend backend, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner,
-                    CompilationResultBuilderFactory factory, OptimisticOptimizations optimisticOpts) {
+                    CompilationResultBuilderFactory factory, OptimisticOptimizations optimisticOpts, Replacements replacements) {
         assert method.getCode() != null : "method must contain bytecodes: " + method;
         TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Sat Jan 31 00:30:00 2015 +0100
@@ -67,7 +67,7 @@
         StructuredGraph graph = new StructuredGraph(javaMethod);
 
         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault();
-        new GraphBuilderPhase.Instance(getMetaAccess(), conf, OptimisticOptimizations.ALL).apply(graph);
+        new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), assumptions, conf, OptimisticOptimizations.ALL).apply(graph);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Sat Jan 31 00:30:00 2015 +0100
@@ -525,7 +525,7 @@
         try (Scope bds = Debug.scope("CompileBaseline", javaMethod, providers.getCodeCache())) {
             BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess());
             OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL;
-            return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default, optimisticOpts);
+            return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default, optimisticOpts, getReplacements());
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Sat Jan 31 00:30:00 2015 +0100
@@ -151,8 +151,8 @@
         ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
         graph = new StructuredGraph(method);
         try (Scope s = Debug.scope(getClass(), graph, method, getCodeCache())) {
-            new GraphBuilderPhase.Instance(getMetaAccess(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
             Assumptions assumptions = new Assumptions(false);
+            new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), assumptions, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
             context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
             new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java	Sat Jan 31 00:30:00 2015 +0100
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
@@ -33,6 +34,7 @@
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
@@ -57,13 +59,16 @@
 public class StaticAnalysis {
     /** Access to type, method, and fields using the Graal API. */
     private final MetaAccessProvider metaAccess;
+    /** Access to platform dependent stamps. */
+    private final StampProvider stampProvider;
     /** The results of the static analysis. */
     private final Results results;
     /** Worklist for fixpoint iteration. */
     private final Deque<WorklistEntry> worklist;
 
-    public StaticAnalysis(MetaAccessProvider metaAccess) {
+    public StaticAnalysis(MetaAccessProvider metaAccess, StampProvider stampProvider) {
         this.metaAccess = metaAccess;
+        this.stampProvider = stampProvider;
         this.results = new Results();
         this.worklist = new ArrayDeque<>();
     }
@@ -231,8 +236,9 @@
                      * wrong.
                      */
                     OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE;
+                    Assumptions assumptions = new Assumptions(false);
 
-                    GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, graphBuilderConfig, optimisticOpts);
+                    GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, assumptions, graphBuilderConfig, optimisticOpts);
                     graphBuilder.apply(graph);
                 } catch (Throwable ex) {
                     Debug.handle(ex);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysisTests.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysisTests.java	Sat Jan 31 00:30:00 2015 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.compiler.test.tutorial.StaticAnalysis.MethodState;
 import com.oracle.graal.compiler.test.tutorial.StaticAnalysis.TypeFlow;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.runtime.*;
 
@@ -58,12 +59,14 @@
         Object f;
     }
 
-    private MetaAccessProvider metaAccess;
+    private final MetaAccessProvider metaAccess;
+    private final StampProvider stampProvider;
 
     public StaticAnalysisTests() {
         Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
         Providers providers = backend.getProviders();
         this.metaAccess = providers.getMetaAccess();
+        this.stampProvider = providers.getStampProvider();
     }
 
     static void test01Entry() {
@@ -73,7 +76,7 @@
 
     @Test
     public void test01() {
-        StaticAnalysis sa = new StaticAnalysis(metaAccess);
+        StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider);
         sa.addMethod(findMethod(StaticAnalysisTests.class, "test01Entry"));
         sa.finish();
 
@@ -94,7 +97,7 @@
 
     @Test
     public void test02() {
-        StaticAnalysis sa = new StaticAnalysis(metaAccess);
+        StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider);
         sa.addMethod(findMethod(StaticAnalysisTests.class, "test02Entry"));
         sa.finish();
 
@@ -121,7 +124,7 @@
 
     @Test
     public void test03() {
-        StaticAnalysis sa = new StaticAnalysis(metaAccess);
+        StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider);
         sa.addMethod(findMethod(StaticAnalysisTests.class, "test03Entry"));
         sa.finish();
 
@@ -151,7 +154,7 @@
 
     @Test
     public void test04() {
-        StaticAnalysis sa = new StaticAnalysis(metaAccess);
+        StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider);
         sa.addMethod(findMethod(StaticAnalysisTests.class, "test04Entry"));
         sa.finish();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Sat Jan 31 00:30:00 2015 +0100
@@ -197,7 +197,7 @@
                     HotSpotProviders providers = backend.getProviders();
                     BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess());
                     OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL;
-                    result = baselineCompiler.generate(method, -1, backend, new CompilationResult(), method, CompilationResultBuilderFactory.Default, optimisticOpts);
+                    result = baselineCompiler.generate(method, -1, backend, new CompilationResult(), method, CompilationResultBuilderFactory.Default, optimisticOpts, providers.getReplacements());
                 } else {
                     Map<ResolvedJavaMethod, StructuredGraph> graphCache = null;
                     if (GraalOptions.CacheGraphs.getValue()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Sat Jan 31 00:30:00 2015 +0100
@@ -31,6 +31,7 @@
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -65,6 +66,15 @@
         HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls();
         final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
 
+        try (InitTimer st = timer("graphBuilderPlugins.initialize")) {
+            GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous();
+            GraphBuilderPlugins plugins = phase.getGraphBuilderPlugins();
+            Iterable<GraphBuilderPluginsProvider> sl = Services.load(GraphBuilderPluginsProvider.class);
+            for (GraphBuilderPluginsProvider p : sl) {
+                p.registerPlugins(providers.getMetaAccess(), plugins);
+            }
+        }
+
         try (InitTimer st = timer("foreignCalls.initialize")) {
             foreignCalls.initialize(providers, config);
         }
@@ -92,6 +102,5 @@
                 throw Debug.handle(e);
             }
         }
-
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Sat Jan 31 00:30:00 2015 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.java.*;
-import com.oracle.graal.java.GraphBuilderConfiguration.*;
+import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java	Sat Jan 31 00:30:00 2015 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+@ServiceProvider(GraphBuilderPluginsProvider.class)
+public class HotSpotGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider {
+    public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+        plugins.register(metaAccess, ObjectPlugin.class);
+    }
+
+    enum ObjectPlugin implements GraphBuilderPlugin {
+        getClass() {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                assert args.length == 1;
+                ValueNode rcvr = args[0];
+                GuardingPiNode pi = builder.append(new GuardingPiNode(rcvr));
+                StampProvider stampProvider = builder.getStampProvider();
+                LoadHubNode hub = builder.append(new LoadHubNode(stampProvider, pi));
+                HubGetClassNode mirror = builder.append(new HubGetClassNode(builder.getMetaAccess(), hub));
+                builder.push(Kind.Object, mirror);
+                return true;
+            }
+        };
+
+        public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) {
+            return GraphBuilderPlugin.resolveTarget(metaAccess, Object.class, name());
+        }
+
+        @Override
+        public String toString() {
+            return Object.class.getName() + "." + name() + "()";
+        }
+    }
+}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Sat Jan 31 00:30:00 2015 +0100
@@ -1153,5 +1153,4 @@
         }
         Debug.log("%s", sb);
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPluginsProvider.java	Sat Jan 31 00:30:00 2015 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.java;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+@ServiceProvider(GraphBuilderPluginsProvider.class)
+public class DefaultGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider {
+    public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+        plugins.register(metaAccess, ObjectPlugin.class);
+    }
+
+    enum ObjectPlugin implements GraphBuilderPlugin {
+        init() {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                assert args.length == 1;
+                ValueNode rcvr = args[0];
+                ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp();
+
+                boolean needsCheck = true;
+                if (objectStamp.isExactType()) {
+                    needsCheck = objectStamp.type().hasFinalizer();
+                } else if (objectStamp.type() != null && !objectStamp.type().hasFinalizableSubclass()) {
+                    // if either the declared type of receiver or the holder
+                    // can be assumed to have no finalizers
+                    Assumptions assumptions = builder.getAssumptions();
+                    if (assumptions.useOptimisticAssumptions()) {
+                        assumptions.recordNoFinalizableSubclassAssumption(objectStamp.type());
+                        needsCheck = false;
+                    }
+                }
+
+                if (needsCheck) {
+                    builder.append(new RegisterFinalizerNode(rcvr));
+                }
+                return true;
+            }
+
+            public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) {
+                return GraphBuilderPlugin.resolveTarget(metaAccess, Object.class, "<init>");
+            }
+        };
+
+        @Override
+        public String toString() {
+            return Object.class.getName() + "." + name() + "()";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Sat Jan 31 00:30:00 2015 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.java;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Used by a {@link GraphBuilderPlugin} to interface with a graph builder object.
+ */
+public interface GraphBuilderContext {
+
+    <T extends ControlSinkNode> T append(T fixed);
+
+    <T extends ControlSplitNode> T append(T fixed);
+
+    <T extends FixedWithNextNode> T append(T fixed);
+
+    <T extends FloatingNode> T append(T v);
+
+    StampProvider getStampProvider();
+
+    MetaAccessProvider getMetaAccess();
+
+    Assumptions getAssumptions();
+
+    void push(Kind kind, ValueNode value);
+}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sat Jan 31 00:30:00 2015 +0100
@@ -47,6 +47,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
@@ -58,20 +59,26 @@
 public class GraphBuilderPhase extends BasePhase<HighTierContext> {
 
     private final GraphBuilderConfiguration graphBuilderConfig;
+    private final GraphBuilderPlugins graphBuilderPlugins;
 
-    public GraphBuilderPhase(GraphBuilderConfiguration graphBuilderConfig) {
-        this.graphBuilderConfig = graphBuilderConfig;
+    public GraphBuilderPhase(GraphBuilderConfiguration config) {
+        this.graphBuilderConfig = config;
+        this.graphBuilderPlugins = new GraphBuilderPlugins();
     }
 
     @Override
     protected void run(StructuredGraph graph, HighTierContext context) {
-        new Instance(context.getMetaAccess(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph);
+        new Instance(context.getMetaAccess(), context.getStampProvider(), context.getAssumptions(), graphBuilderConfig, graphBuilderPlugins, context.getOptimisticOptimizations()).run(graph);
     }
 
     public GraphBuilderConfiguration getGraphBuilderConfig() {
         return graphBuilderConfig;
     }
 
+    public GraphBuilderPlugins getGraphBuilderPlugins() {
+        return graphBuilderPlugins;
+    }
+
     public static class Instance extends Phase {
 
         protected StructuredGraph currentGraph;
@@ -81,7 +88,10 @@
         private ResolvedJavaMethod rootMethod;
 
         private final GraphBuilderConfiguration graphBuilderConfig;
+        private final GraphBuilderPlugins graphBuilderPlugins;
         private final OptimisticOptimizations optimisticOpts;
+        private final StampProvider stampProvider;
+        private final Assumptions assumptions;
 
         /**
          * Gets the graph being processed by this builder.
@@ -90,13 +100,21 @@
             return currentGraph;
         }
 
-        public Instance(MetaAccessProvider metaAccess, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
+        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins,
+                        OptimisticOptimizations optimisticOpts) {
             this.graphBuilderConfig = graphBuilderConfig;
             this.optimisticOpts = optimisticOpts;
             this.metaAccess = metaAccess;
+            this.stampProvider = stampProvider;
+            this.assumptions = assumptions;
+            this.graphBuilderPlugins = graphBuilderPlugins;
             assert metaAccess != null;
         }
 
+        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
+            this(metaAccess, stampProvider, assumptions, graphBuilderConfig, null, optimisticOpts);
+        }
+
         @Override
         protected void run(StructuredGraph graph) {
             ResolvedJavaMethod method = graph.method();
@@ -143,7 +161,7 @@
             }
         }
 
-        public class BytecodeParser extends AbstractBytecodeParser<ValueNode, HIRFrameStateBuilder> {
+        public class BytecodeParser extends AbstractBytecodeParser<ValueNode, HIRFrameStateBuilder> implements GraphBuilderContext {
 
             private BciBlock[] loopHeaders;
             private LocalLiveness liveness;
@@ -752,38 +770,49 @@
                         args[0] = TypeProfileProxyNode.proxify(args[0], profile);
                     }
                 }
+                if (GraalOptions.InlineDuringParsing.getValue() && invokeKind.isDirect()) {
 
-                if (GraalOptions.InlineDuringParsing.getValue() && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes()) {
-                    if (targetMethod.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && currentDepth < GraalOptions.InlineDuringParsingMaxDepth.getValue() &&
-                                    graphBuilderConfig.shouldInlineTrivial()) {
-                        BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, StructuredGraph.INVOCATION_ENTRY_BCI);
-                        final FrameState[] lazyFrameState = new FrameState[1];
-                        HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, () -> {
-                            if (lazyFrameState[0] == null) {
-                                lazyFrameState[0] = frameState.create(bci());
-                            }
-                            return lazyFrameState[0];
-                        });
-                        startFrameState.initializeFromArgumentsArray(args);
-                        parser.build(currentDepth + 1, this.lastInstr, startFrameState);
-
-                        FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode();
-                        this.lastInstr = calleeBeforeReturnNode;
-                        if (calleeBeforeReturnNode != null) {
-                            ValueNode calleeReturnValue = parser.getReturnValue();
-                            if (calleeReturnValue != null) {
-                                frameState.push(calleeReturnValue.getKind().getStackKind(), calleeReturnValue);
+                    if (graphBuilderPlugins != null) {
+                        GraphBuilderPlugin plugin = graphBuilderPlugins.getPlugin(targetMethod);
+                        if (plugin != null) {
+                            if (plugin.handleInvocation(this, args)) {
+                                return;
                             }
                         }
+                    }
 
-                        FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
-                        if (calleeBeforeUnwindNode != null) {
-                            ValueNode calleeUnwindValue = parser.getUnwindValue();
-                            assert calleeUnwindValue != null;
-                            calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
+                    if (targetMethod.canBeInlined() && targetMethod.hasBytecodes()) {
+                        if (targetMethod.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && currentDepth < GraalOptions.InlineDuringParsingMaxDepth.getValue() &&
+                                        graphBuilderConfig.shouldInlineTrivial()) {
+                            BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, StructuredGraph.INVOCATION_ENTRY_BCI);
+                            final FrameState[] lazyFrameState = new FrameState[1];
+                            HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, () -> {
+                                if (lazyFrameState[0] == null) {
+                                    lazyFrameState[0] = frameState.create(bci());
+                                }
+                                return lazyFrameState[0];
+                            });
+                            startFrameState.initializeFromArgumentsArray(args);
+                            parser.build(currentDepth + 1, this.lastInstr, startFrameState);
+
+                            FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode();
+                            this.lastInstr = calleeBeforeReturnNode;
+                            if (calleeBeforeReturnNode != null) {
+                                ValueNode calleeReturnValue = parser.getReturnValue();
+                                if (calleeReturnValue != null) {
+                                    frameState.push(calleeReturnValue.getKind().getStackKind(), calleeReturnValue);
+                                }
+                            }
+
+                            FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
+                            if (calleeBeforeUnwindNode != null) {
+                                ValueNode calleeUnwindValue = parser.getUnwindValue();
+                                assert calleeUnwindValue != null;
+                                calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
+                            }
+
+                            return;
                         }
-
-                        return;
                     }
                 }
 
@@ -937,7 +966,7 @@
                 throw GraalInternalError.shouldNotReachHere("Can not append Node of type: " + v.getClass().getName());
             }
 
-            private <T extends ControlSinkNode> T append(T fixed) {
+            public <T extends ControlSinkNode> T append(T fixed) {
                 assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet";
                 assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
                 T added = currentGraph.add(fixed);
@@ -946,7 +975,7 @@
                 return added;
             }
 
-            private <T extends ControlSplitNode> T append(T fixed) {
+            public <T extends ControlSplitNode> T append(T fixed) {
                 assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet";
                 assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
                 T added = currentGraph.add(fixed);
@@ -955,7 +984,7 @@
                 return added;
             }
 
-            protected <T extends FixedWithNextNode> T append(T fixed) {
+            public <T extends FixedWithNextNode> T append(T fixed) {
                 assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet";
                 assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
                 T added = currentGraph.add(fixed);
@@ -964,7 +993,7 @@
                 return added;
             }
 
-            private <T extends FloatingNode> T append(T v) {
+            public <T extends FloatingNode> T append(T v) {
                 assert !(v instanceof ConstantNode);
                 T added = currentGraph.unique(v);
                 return added;
@@ -1456,6 +1485,22 @@
                 append(ifNode);
             }
 
+            public StampProvider getStampProvider() {
+                return stampProvider;
+            }
+
+            public MetaAccessProvider getMetaAccess() {
+                return metaAccess;
+            }
+
+            public Assumptions getAssumptions() {
+                return assumptions;
+            }
+
+            public void push(Kind kind, ValueNode value) {
+                frameState.push(kind, value);
+            }
+
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java	Sat Jan 31 00:30:00 2015 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.java;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Extensions for handling certain bytecode instructions while building a
+ * {@linkplain StructuredGraph graph} from a bytecode stream.
+ */
+public interface GraphBuilderPlugin {
+
+    /**
+     * Processes an invocation parsed in a bytecode stream and add nodes to a graph being
+     * constructed that implement the semantics of the invocation.
+     *
+     * @param builder object being used to build a graph
+     * @param args the arguments to the invocation
+     */
+    boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args);
+
+    /**
+     * Gets the target method handled by {@link #handleInvocation(GraphBuilderContext, ValueNode[])}
+     * .
+     */
+    ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess);
+
+    static ResolvedJavaMethod resolveTarget(MetaAccessProvider metaAccess, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
+        try {
+            return metaAccess.lookupJavaMethod(methodName.equals("<init>") ? clazz.getDeclaredConstructor(parameterTypes) : clazz.getDeclaredMethod(methodName, parameterTypes));
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Sat Jan 31 00:30:00 2015 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.java;
+
+import java.util.*;
+import java.util.stream.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * A repository of {@link GraphBuilderPlugin}s.
+ */
+public class GraphBuilderPlugins {
+
+    private final Map<ResolvedJavaMethod, GraphBuilderPlugin> map = new HashMap<>();
+
+    /**
+     * Registers all the constants of an enum that implements {@link GraphBuilderPlugin}.
+     */
+    public <T extends Enum<T> & GraphBuilderPlugin> void register(MetaAccessProvider metaAccess, Class<T> enumClass) {
+        assert Enum.class.isAssignableFrom(enumClass);
+        Object[] enumConstants = enumClass.getEnumConstants();
+        for (Object o : enumConstants) {
+            GraphBuilderPlugin gbp = (GraphBuilderPlugin) o;
+            ResolvedJavaMethod target = gbp.getInvocationTarget(metaAccess);
+            GraphBuilderPlugin oldValue = map.put(target, gbp);
+            assert oldValue == null;
+        }
+    }
+
+    /**
+     * Gets the plugin for a given method registered in the object.
+     *
+     * @param method the method to lookup
+     * @return the plugin associated with {@code method} or {@code null} if none exists
+     */
+    public GraphBuilderPlugin getPlugin(ResolvedJavaMethod method) {
+        return map.get(method);
+    }
+
+    @Override
+    public String toString() {
+        return map.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", "));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.java	Sat Jan 31 00:30:00 2015 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.java;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+
+/**
+ * Interface for providers of {@link GraphBuilderPlugin}s.
+ */
+public interface GraphBuilderPluginsProvider extends Service {
+    /**
+     * Registers the plugins provided by this object with a plugins registry.
+     *
+     * @param plugins registry of plugins
+     */
+    void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins);
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Sat Jan 31 00:30:00 2015 +0100
@@ -605,7 +605,8 @@
                 if (MethodsElidedInSnippets != null && methodToParse.getSignature().getReturnKind() == Kind.Void && MethodFilter.matches(MethodsElidedInSnippets, methodToParse)) {
                     graph.addAfterFixed(graph.start(), graph.add(new ReturnNode(null)));
                 } else {
-                    createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
+                    createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.assumptions, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(
+                                    graph);
                 }
                 afterParsing(graph);
 
@@ -618,8 +619,9 @@
             return graph;
         }
 
-        protected Instance createGraphBuilder(MetaAccessProvider metaAccess, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
-            return new GraphBuilderPhase.Instance(metaAccess, graphBuilderConfig, optimisticOpts);
+        protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, GraphBuilderConfiguration graphBuilderConfig,
+                        OptimisticOptimizations optimisticOpts) {
+            return new GraphBuilderPhase.Instance(metaAccess, stampProvider, assumptions, graphBuilderConfig, optimisticOpts);
         }
 
         protected void afterParsing(StructuredGraph graph) {
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Sat Jan 31 00:30:00 2015 +0100
@@ -177,7 +177,7 @@
         Suites suites = suitesProvider.createSuites();
         removeInliningPhase(suites);
         StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+        new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), new Assumptions(false), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).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/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Sat Jan 31 00:19:34 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Sat Jan 31 00:30:00 2015 +0100
@@ -94,13 +94,13 @@
 
     public StructuredGraph createInlineGraph(String name) {
         StructuredGraph graph = new StructuredGraph(name, callInlinedMethod);
-        new GraphBuilderPhase.Instance(providers.getMetaAccess(), config, TruffleCompilerImpl.Optimizations).apply(graph);
+        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), config, TruffleCompilerImpl.Optimizations).apply(graph);
         return graph;
     }
 
     public StructuredGraph createRootGraph(String name) {
         StructuredGraph graph = new StructuredGraph(name, callRootMethod);
-        new GraphBuilderPhase.Instance(providers.getMetaAccess(), configForRoot, TruffleCompilerImpl.Optimizations).apply(graph);
+        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), configForRoot, TruffleCompilerImpl.Optimizations).apply(graph);
         return graph;
     }
 
@@ -294,7 +294,7 @@
 
     protected StructuredGraph parseGraph(final ResolvedJavaMethod method, final PhaseContext phaseContext) {
         final StructuredGraph graph = new StructuredGraph(method);
-        new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), config, optimisticOptimizations).apply(graph);
+        new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), phaseContext.getStampProvider(), phaseContext.getAssumptions(), config, optimisticOptimizations).apply(graph);
         return graph;
     }
 
--- a/mx/suite.py	Sat Jan 31 00:19:34 2015 +0100
+++ b/mx/suite.py	Sat Jan 31 00:30:00 2015 +0100
@@ -818,6 +818,7 @@
         "com.oracle.graal.phases",
       ],
       "checkstyle" : "com.oracle.graal.graph",
+      "annotationProcessors" : ["com.oracle.graal.service.processor"],
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,Java",
     },