changeset 11732:03c781923573

made snippet and substitution graphs lower themselves before being inlined
author Doug Simon <doug.simon@oracle.com>
date Thu, 19 Sep 2013 23:41:23 +0200
parents d8f291981d75
children cb5df1879500
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java
diffstat 17 files changed, 84 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Sep 19 23:41:23 2013 +0200
@@ -554,10 +554,9 @@
             assert loadField.kind() != Kind.Illegal;
             BarrierType barrierType = getFieldLoadBarrierType(field);
             ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object)));
+            graph.replaceFixedWithFixed(loadField, memoryRead);
             tool.createNullCheckGuard(memoryRead, object);
 
-            graph.replaceFixedWithFixed(loadField, memoryRead);
-
             if (loadField.isVolatile()) {
                 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ));
                 graph.addBeforeFixed(memoryRead, preMembar);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -74,7 +74,7 @@
             StructuredGraph graph = checkcast.graph();
             ValueNode object = checkcast.object();
 
-            Arguments args = new Arguments(dynamic);
+            Arguments args = new Arguments(dynamic, graph.getGuardsStage());
             args.add("hub", checkcast.hub());
             args.add("object", object);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -215,24 +215,25 @@
 
                 Arguments args;
 
+                StructuredGraph graph = hub.graph();
                 if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet()) {
-                    Hints hints = createHints(hintInfo, runtime, false, hub.graph());
-                    args = new Arguments(instanceofWithProfile);
+                    Hints hints = createHints(hintInfo, runtime, false, graph);
+                    args = new Arguments(instanceofWithProfile, graph.getGuardsStage());
                     args.add("object", object);
                     args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs);
                     args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive);
                 } else if (hintInfo.exact != null) {
-                    args = new Arguments(instanceofExact);
+                    args = new Arguments(instanceofExact, graph.getGuardsStage());
                     args.add("object", object);
-                    args.add("exactHub", ConstantNode.forConstant(((HotSpotResolvedObjectType) hintInfo.exact).klass(), runtime, hub.graph()));
+                    args.add("exactHub", ConstantNode.forConstant(((HotSpotResolvedObjectType) hintInfo.exact).klass(), runtime, graph));
                 } else if (type.isPrimaryType()) {
-                    args = new Arguments(instanceofPrimary);
+                    args = new Arguments(instanceofPrimary, graph.getGuardsStage());
                     args.add("hub", hub);
                     args.add("object", object);
                     args.addConst("superCheckOffset", type.superCheckOffset());
                 } else {
-                    Hints hints = createHints(hintInfo, runtime, false, hub.graph());
-                    args = new Arguments(instanceofSecondary);
+                    Hints hints = createHints(hintInfo, runtime, false, graph);
+                    args = new Arguments(instanceofSecondary, graph.getGuardsStage());
                     args.add("hub", hub);
                     args.add("object", object);
                     args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints.hubs);
@@ -250,7 +251,7 @@
                 InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf;
                 ValueNode object = instanceOf.object();
 
-                Arguments args = new Arguments(instanceofDynamic);
+                Arguments args = new Arguments(instanceofDynamic, instanceOf.graph().getGuardsStage());
                 args.add("mirror", instanceOf.mirror());
                 args.add("object", object);
                 args.add("trueValue", replacer.trueValue);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -78,7 +78,7 @@
                 loadExceptionC.setStateAfter(loadExceptionObject.stateAfter());
                 graph.replaceFixedWithFixed(loadExceptionObject, loadExceptionC);
             } else {
-                Arguments args = new Arguments(loadException);
+                Arguments args = new Arguments(loadException, loadExceptionObject.graph().getGuardsStage());
                 template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args);
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -405,9 +405,9 @@
 
             Arguments args;
             if (useFastLocking) {
-                args = new Arguments(monitorenter);
+                args = new Arguments(monitorenter, graph.getGuardsStage());
             } else {
-                args = new Arguments(monitorenterStub);
+                args = new Arguments(monitorenterStub, graph.getGuardsStage());
             }
             args.add("object", monitorenterNode.object());
             args.addConst("lockDepth", monitorenterNode.getLockDepth());
@@ -430,9 +430,9 @@
 
             Arguments args;
             if (useFastLocking) {
-                args = new Arguments(monitorexit);
+                args = new Arguments(monitorexit, graph.getGuardsStage());
             } else {
-                args = new Arguments(monitorexitStub);
+                args = new Arguments(monitorexitStub, graph.getGuardsStage());
             }
             args.add("object", monitorexitNode.object());
             args.addConst("lockDepth", monitorexitNode.getLockDepth());
@@ -507,7 +507,7 @@
                         invoke.setStateAfter(graph.add(stateAfter));
                         graph.addBeforeFixed(ret, invoke);
 
-                        Arguments args = new Arguments(checkCounter);
+                        Arguments args = new Arguments(checkCounter, graph.getGuardsStage());
                         args.addConst("errMsg", msg);
                         inlineeGraph = template(args).copySpecializedGraph();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -255,7 +255,7 @@
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
             int size = instanceSize(type);
 
-            Arguments args = new Arguments(allocateInstance);
+            Arguments args = new Arguments(allocateInstance, graph.getGuardsStage());
             args.addConst("size", size);
             args.add("hub", hub);
             args.add("prototypeMarkWord", type.prototypeMarkWord());
@@ -278,7 +278,7 @@
             final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind);
             int log2ElementSize = CodeUtil.log2(((HotSpotRuntime) runtime).getScalingFactor(elementKind));
 
-            Arguments args = new Arguments(allocateArray);
+            Arguments args = new Arguments(allocateArray, graph.getGuardsStage());
             args.add("hub", hub);
             args.add("length", newArrayNode.length());
             args.add("prototypeMarkWord", arrayType.prototypeMarkWord());
@@ -292,7 +292,7 @@
         }
 
         public void lower(DynamicNewArrayNode newArrayNode) {
-            Arguments args = new Arguments(allocateArrayDynamic);
+            Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage());
             args.add("elementType", newArrayNode.getElementType());
             args.add("length", newArrayNode.length());
             args.addConst("fillContents", newArrayNode.fillContents());
@@ -311,7 +311,7 @@
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type();
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
 
-            Arguments args = new Arguments(newmultiarray);
+            Arguments args = new Arguments(newmultiarray, graph.getGuardsStage());
             args.add("hub", hub);
             args.addConst("rank", rank);
             args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -279,7 +279,7 @@
                 assert snippet != null : "arraycopy snippet for " + elementKind.name() + " not found";
             }
 
-            Arguments args = new Arguments(snippet);
+            Arguments args = new Arguments(snippet, node.graph().getGuardsStage());
             node.addSnippetArguments(args);
 
             SnippetTemplate template = template(args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -58,7 +58,7 @@
         }
 
         public void lower(UnsafeLoadNode load, @SuppressWarnings("unused") LoweringTool tool) {
-            Arguments args = new Arguments(unsafeLoad);
+            Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage());
             args.add("object", load.object());
             args.add("offset", load.offset());
             args.add("disp", load.displacement());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -340,7 +340,7 @@
         }
 
         public void lower(SerialWriteBarrier writeBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            Arguments args = new Arguments(serialWriteBarrier);
+            Arguments args = new Arguments(serialWriteBarrier, writeBarrier.graph().getGuardsStage());
             args.add("object", writeBarrier.getObject());
             args.add("location", writeBarrier.getLocation());
             args.addConst("usePrecise", writeBarrier.usePrecise());
@@ -349,7 +349,7 @@
         }
 
         public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            Arguments args = new Arguments(serialArrayRangeWriteBarrier);
+            Arguments args = new Arguments(serialArrayRangeWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage());
             args.add("object", arrayRangeWriteBarrier.getObject());
             args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
             args.add("length", arrayRangeWriteBarrier.getLength());
@@ -357,7 +357,7 @@
         }
 
         public void lower(G1PreWriteBarrier writeBarrierPre, @SuppressWarnings("unused") LoweringTool tool) {
-            Arguments args = new Arguments(g1PreWriteBarrier);
+            Arguments args = new Arguments(g1PreWriteBarrier, writeBarrierPre.graph().getGuardsStage());
             args.add("object", writeBarrierPre.getObject());
             args.add("expectedObject", writeBarrierPre.getExpectedObject());
             args.add("location", writeBarrierPre.getLocation());
@@ -368,7 +368,7 @@
         }
 
         public void lower(G1ReferentFieldReadBarrier readBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            Arguments args = new Arguments(g1ReferentReadBarrier);
+            Arguments args = new Arguments(g1ReferentReadBarrier, readBarrier.graph().getGuardsStage());
             args.add("object", readBarrier.getObject());
             args.add("expectedObject", readBarrier.getExpectedObject());
             args.add("location", readBarrier.getLocation());
@@ -379,7 +379,7 @@
         }
 
         public void lower(G1PostWriteBarrier writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) {
-            Arguments args = new Arguments(g1PostWriteBarrier);
+            Arguments args = new Arguments(g1PostWriteBarrier, writeBarrierPost.graph().getGuardsStage());
             args.add("object", writeBarrierPost.getObject());
             args.add("value", writeBarrierPost.getValue());
             args.add("location", writeBarrierPost.getLocation());
@@ -390,7 +390,7 @@
         }
 
         public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            Arguments args = new Arguments(g1ArrayRangePreWriteBarrier);
+            Arguments args = new Arguments(g1ArrayRangePreWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage());
             args.add("object", arrayRangeWriteBarrier.getObject());
             args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
             args.add("length", arrayRangeWriteBarrier.getLength());
@@ -398,7 +398,7 @@
         }
 
         public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            Arguments args = new Arguments(g1ArrayRangePostWriteBarrier);
+            Arguments args = new Arguments(g1ArrayRangePostWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage());
             args.add("object", arrayRangeWriteBarrier.getObject());
             args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
             args.add("length", arrayRangeWriteBarrier.getLength());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Thu Sep 19 23:41:23 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.StructuredGraph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -66,7 +67,7 @@
         Constant intArrayHub = intArrayType.klass();
         intArrayHub = Constant.forIntegerKind(graalRuntime().getTarget().wordKind, intArrayHub.asLong(), null);
 
-        Arguments args = new Arguments(stub);
+        Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS);
         args.add("hub", null);
         args.add("length", null);
         args.addConst("intArrayHub", intArrayHub);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Thu Sep 19 23:41:23 2013 +0200
@@ -37,6 +37,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.StructuredGraph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -67,7 +68,7 @@
         Constant intArrayHub = intArrayType.klass();
         intArrayHub = Constant.forIntegerKind(graalRuntime().getTarget().wordKind, intArrayHub.asLong(), null);
 
-        Arguments args = new Arguments(stub);
+        Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS);
         args.add("hub", null);
         args.addConst("intArrayHub", intArrayHub);
         return args;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Thu Sep 19 23:41:23 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
@@ -79,7 +80,7 @@
      * Adds the arguments to this snippet stub.
      */
     protected Arguments makeArguments(SnippetInfo stub) {
-        Arguments args = new Arguments(stub);
+        Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS);
         for (int i = 0; i < stub.getParameterCount(); i++) {
             args.add(stub.getParameterName(i), null);
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Sep 19 23:41:23 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
@@ -77,10 +78,17 @@
                 // Short cut creation of null check guard if the object is known to be non-null.
                 return null;
             }
-            GuardingNode guard = createGuard(object.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
-            assert guardedNode.getGuard() == null;
-            guardedNode.setGuard(guard);
-            return guard;
+            StructuredGraph graph = object.graph();
+            if (graph.getGuardsStage().ordinal() > GuardsStage.FLOATING_GUARDS.ordinal()) {
+                NullCheckNode nullCheck = graph.add(new NullCheckNode(object));
+                graph.addBeforeFixed((FixedNode) guardedNode, nullCheck);
+                return nullCheck;
+            } else {
+                GuardingNode guard = createGuard(graph.unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
+                assert guardedNode.getGuard() == null;
+                guardedNode.setGuard(guard);
+                return guard;
+            }
         }
 
         @Override
@@ -202,7 +210,9 @@
 
             if (parentAnchor == null && OptEliminateGuards.getValue()) {
                 for (GuardNode guard : anchor.asNode().usages().filter(GuardNode.class)) {
-                    activeGuards.clear(guard);
+                    if (activeGuards.contains(guard)) {
+                        activeGuards.clear(guard);
+                    }
                 }
             }
         }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -174,7 +174,7 @@
 
             LocalNode replacee = graph.addWithoutUnique(new LocalNode(Integer.MAX_VALUE, convert.stamp()));
             convert.replaceAtUsages(replacee);
-            Arguments args = new Arguments(key);
+            Arguments args = new Arguments(key, graph.getGuardsStage());
             args.add("input", convert.value());
             args.add("result", convert.graph().unique(new AMD64ConvertNode(convert.opcode, convert.value())));
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Thu Sep 19 23:41:23 2013 +0200
@@ -220,7 +220,7 @@
             if (canonical != null && !AOTCompilation.getValue()) {
                 box.graph().replaceFloating(box, canonical);
             } else {
-                Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()));
+                Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()), box.graph().getGuardsStage());
                 args.add("value", box.getValue());
 
                 SnippetTemplate template = template(args);
@@ -231,7 +231,7 @@
         }
 
         public void lower(UnboxNode unbox, LoweringTool tool) {
-            Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()));
+            Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()), unbox.graph().getGuardsStage());
             args.add("value", unbox.getValue());
 
             SnippetTemplate template = template(args);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Thu Sep 19 23:41:23 2013 +0200
@@ -34,6 +34,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -58,7 +59,7 @@
     /**
      * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the
      * method that needs to be computed only once. The {@link SnippetInfo} should be created once
-     * per snippet an then cached.
+     * per snippet and then cached.
      */
     public static class SnippetInfo {
 
@@ -149,9 +150,9 @@
 
         protected int nextParamIdx;
 
-        public Arguments(SnippetInfo info) {
+        public Arguments(SnippetInfo info, GuardsStage guardsStage) {
             this.info = info;
-            this.cacheKey = new CacheKey(info);
+            this.cacheKey = new CacheKey(info, guardsStage);
             this.values = new Object[info.getParameterCount()];
         }
 
@@ -268,10 +269,12 @@
 
         private final ResolvedJavaMethod method;
         private final Object[] values;
+        private final GuardsStage guardsStage;
         private int hash;
 
-        protected CacheKey(SnippetInfo info) {
+        protected CacheKey(SnippetInfo info, GuardsStage guardsStage) {
             this.method = info.method;
+            this.guardsStage = guardsStage;
             this.values = new Object[info.getParameterCount()];
             this.hash = info.method.hashCode();
         }
@@ -290,6 +293,9 @@
             if (method != other.method) {
                 return false;
             }
+            if (guardsStage != other.guardsStage) {
+                return false;
+            }
             for (int i = 0; i < values.length; i++) {
                 if (values[i] != null && !values[i].equals(other.values[i])) {
                     return false;
@@ -493,7 +499,12 @@
             }
         } while (exploded);
 
-        // Remove all frame states from inlined snippet graph. Snippets must be atomic (i.e. free
+        // Perform lowering on the snippet
+        snippetCopy.setGuardsStage(args.cacheKey.guardsStage);
+        PhaseContext c = new PhaseContext(runtime, new Assumptions(false), replacements);
+        new LoweringPhase(new CanonicalizerPhase(true)).apply(snippetCopy, c);
+
+        // Remove all frame states from snippet graph. Snippets must be atomic (i.e. free
         // of side-effects that prevent deoptimizing to a point before the snippet).
         ArrayList<StateSplit> curSideEffectNodes = new ArrayList<>();
         ArrayList<DeoptimizingNode> curDeoptNodes = new ArrayList<>();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Thu Sep 19 15:06:50 2013 -0400
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Thu Sep 19 23:41:23 2013 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class MacroNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single {
 
@@ -63,7 +64,8 @@
     }
 
     /**
-     * Gets a snippet to be used for lowering this macro node.
+     * Gets a snippet to be used for lowering this macro node. The returned graph (if non-null) is
+     * not shared and can be modified by the caller.
      */
     @SuppressWarnings("unused")
     protected StructuredGraph getSnippetGraph(LoweringTool tool) {
@@ -72,10 +74,15 @@
 
     /**
      * Gets a normal method substitution to be used for lowering this macro node. This is only
-     * called if {@link #getSnippetGraph(LoweringTool)} return nulls.
+     * called if {@link #getSnippetGraph(LoweringTool)} returns null. The returned graph (if
+     * non-null) is not shared and can be modified by the caller.
      */
     protected StructuredGraph getSubstitutionGraph(LoweringTool tool) {
-        return tool.getReplacements().getMethodSubstitution(getTargetMethod());
+        StructuredGraph methodSubstitution = tool.getReplacements().getMethodSubstitution(getTargetMethod());
+        if (methodSubstitution != null) {
+            methodSubstitution = methodSubstitution.copy();
+        }
+        return methodSubstitution;
     }
 
     @Override
@@ -91,6 +98,10 @@
         assert invoke.verify();
 
         if (replacementGraph != null) {
+            // Lower the (non-shared) replacement graph
+            replacementGraph.setGuardsStage(graph().getGuardsStage());
+            PhaseContext c = new PhaseContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements());
+            new LoweringPhase(new CanonicalizerPhase(true)).apply(replacementGraph, c);
             InliningUtil.inline(invoke, replacementGraph, nullCheck);
         }
     }