# HG changeset patch # User Christian Haeubl # Date 1373385302 -7200 # Node ID 853a894e0d97f6818eb1727bd231475e2905b05e # Parent d59e7f94f28de9cf5f3c3a95c1e19d7a0f5f1ba7# Parent 69089865435acb2f94176917c6d6e6bb8d57d3af Merge. diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Tue Jul 09 17:55:02 2013 +0200 @@ -30,9 +30,7 @@ public class LowTier extends PhaseSuite { public LowTier() { - appendPhase(new LoweringPhase(LoweringType.AFTER_GUARDS)); - - appendPhase(new FrameStateAssignmentPhase()); + appendPhase(new LoweringPhase(LoweringType.AFTER_FSA)); appendPhase(new ExpandLogicPhase()); diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Tue Jul 09 17:55:02 2013 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.loop.phases.*; +import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -77,6 +78,10 @@ appendPhase(new GuardLoweringPhase()); + appendPhase(new LoweringPhase(LoweringType.AFTER_GUARDS)); + + appendPhase(new FrameStateAssignmentPhase()); + if (OptCanonicalizer.getValue()) { appendPhase(canonicalizer); } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Jul 09 17:55:02 2013 +0200 @@ -178,7 +178,8 @@ // record where preserved registers are saved for (Map.Entry e : gen.calleeSaveInfo.entrySet()) { AMD64RegistersPreservationOp save = e.getValue(); - save.update(definedRegisters, e.getKey().debugInfo(), frameMap); + DebugInfo info = e.getKey() == null ? null : e.getKey().debugInfo(); + save.update(definedRegisters, info, frameMap); } } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Jul 09 17:55:02 2013 +0200 @@ -239,8 +239,9 @@ * cannot be re-executed. * @param killedLocations the memory locations killed by the foreign call */ - private void linkForeignCall(Replacements replacements, ForeignCallDescriptor descriptor, long address, boolean prependThread, boolean reexecutable, LocationIdentity... killedLocations) { - ForeignCallStub stub = new ForeignCallStub(this, replacements, address, descriptor, prependThread, reexecutable, killedLocations); + private void linkForeignCall(Replacements replacements, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, + LocationIdentity... killedLocations) { + ForeignCallStub stub = new ForeignCallStub(this, replacements, address, descriptor, prependThread, transition, reexecutable, killedLocations); HotSpotForeignCallLinkage linkage = stub.getLinkage(); HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); linkage.setCompiledStub(stub); @@ -283,22 +284,22 @@ link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, ANY_LOCATION))); link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, NO_LOCATIONS))); - linkForeignCall(r, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_REEXECUTABLE, MARK_WORD_LOCATION); - linkForeignCall(r, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(r, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(r, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(r, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, NOT_REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(r, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(r, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, MARK_WORD_LOCATION); + linkForeignCall(r, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF, NOT_REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); if (IntrinsifyObjectMethods.getValue()) { r.registerSubstitutions(ObjectSubstitutions.class); } @@ -766,15 +767,15 @@ } else if (n instanceof InstanceOfDynamicNode) { instanceofSnippets.lower((InstanceOfDynamicNode) n, tool); } else if (n instanceof NewInstanceNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (tool.getLoweringType() == LoweringType.AFTER_FSA) { newObjectSnippets.lower((NewInstanceNode) n); } } else if (n instanceof NewArrayNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (tool.getLoweringType() == LoweringType.AFTER_FSA) { newObjectSnippets.lower((NewArrayNode) n); } } else if (n instanceof DynamicNewArrayNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (tool.getLoweringType() == LoweringType.AFTER_FSA) { newObjectSnippets.lower((DynamicNewArrayNode) n); } } else if (n instanceof MonitorEnterNode) { @@ -798,7 +799,7 @@ } else if (n instanceof G1ArrayRangePostWriteBarrier) { writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool); } else if (n instanceof NewMultiArrayNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (tool.getLoweringType() == LoweringType.AFTER_FSA) { newObjectSnippets.lower((NewMultiArrayNode) n); } } else if (n instanceof LoadExceptionObjectNode) { diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Tue Jul 09 17:55:02 2013 +0200 @@ -56,7 +56,10 @@ private static void addReadNodeBarriers(ReadNode node, StructuredGraph graph) { if (node.getWriteBarrierType() == WriteBarrierType.PRECISE) { assert useG1GC(); - graph.addAfterFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node, node.location(), false))); + G1PreWriteBarrier barrier = graph.add(new G1PreWriteBarrier(node.object(), node, node.location(), false, node.getNullCheck())); + barrier.setDeoptimizationState(node.getDeoptimizationState()); + node.setNullCheck(false); + graph.addAfterFixed(node, barrier); } else { assert node.getWriteBarrierType() == WriteBarrierType.NONE : "Non precise write barrier has been attached to read node."; } @@ -66,14 +69,20 @@ WriteBarrierType barrierType = node.getWriteBarrierType(); if (barrierType == WriteBarrierType.PRECISE) { if (useG1GC()) { - graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true))); + G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck())); + preBarrier.setDeoptimizationState(node.getDeoptimizationState()); + node.setNullCheck(false); + graph.addBeforeFixed(node, preBarrier); graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.value(), node.location(), true))); } else { graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), true))); } } else if (barrierType == WriteBarrierType.IMPRECISE) { if (useG1GC()) { - graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true))); + G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck())); + preBarrier.setDeoptimizationState(node.getDeoptimizationState()); + node.setNullCheck(false); + graph.addBeforeFixed(node, preBarrier); graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.value(), node.location(), false))); } else { graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), false))); @@ -88,14 +97,14 @@ WriteBarrierType barrierType = node.getWriteBarrierType(); if (barrierType == WriteBarrierType.PRECISE) { if (useG1GC()) { - graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false))); + graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false, false))); graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.newValue(), node.getLocation(), true))); } else { graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getLocation(), true))); } } else if (barrierType == WriteBarrierType.IMPRECISE) { if (useG1GC()) { - graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false))); + graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false, false))); graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.newValue(), node.getLocation(), false))); } else { graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getLocation(), false))); diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Tue Jul 09 17:55:02 2013 +0200 @@ -325,7 +325,7 @@ args.add("expectedObject", writeBarrierPre.getExpectedObject()); args.add("location", writeBarrierPre.getLocation()); args.addConst("doLoad", writeBarrierPre.doLoad()); - args.addConst("nullCheck", !writeBarrierPre.getObject().stamp().nonNull()); + args.addConst("nullCheck", writeBarrierPre.getNullCheck()); args.addConst("trace", traceBarrier()); template(args).instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, args); } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Tue Jul 09 17:55:02 2013 +0200 @@ -84,13 +84,13 @@ * be re-executed. * @param killedLocations the memory locations killed by the stub call */ - public ForeignCallStub(HotSpotRuntime runtime, Replacements replacements, long address, ForeignCallDescriptor descriptor, boolean prependThread, boolean reexecutable, + public ForeignCallStub(HotSpotRuntime runtime, Replacements replacements, long address, ForeignCallDescriptor descriptor, boolean prependThread, Transition transition, boolean reexecutable, LocationIdentity... killedLocations) { - super(runtime, replacements, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations)); + super(runtime, replacements, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, transition, reexecutable, killedLocations)); this.prependThread = prependThread; Class[] targetParameterTypes = createTargetParameters(descriptor); ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes); - target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NOT_LEAF, reexecutable, killedLocations); + target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, transition, reexecutable, killedLocations); } /** diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Tue Jul 09 17:55:02 2013 +0200 @@ -99,7 +99,9 @@ } } assert mapIndex == preserved; - debugInfo.setCalleeSaveInfo(new RegisterSaveLayout(keys, values)); + if (debugInfo != null) { + debugInfo.setCalleeSaveInfo(new RegisterSaveLayout(keys, values)); + } } } } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Jul 09 17:55:02 2013 +0200 @@ -31,7 +31,7 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}") -public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable, GuardingNode { +public final class FixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable, GuardingNode { @Input private LogicNode condition; private final DeoptimizationReason reason; @@ -106,6 +106,7 @@ FixedNode next = next(); setNext(null); DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason)); + deopt.setDeoptimizationState(getDeoptimizationState()); IfNode ifNode; if (negated) { ifNode = graph().add(new IfNode(condition, deopt, next, 0)); @@ -128,4 +129,14 @@ public FixedGuardNode asNode() { return this; } + + @Override + public boolean canDeoptimize() { + return true; + } + + @Override + public DeoptimizationReason getDeoptimizationReason() { + return reason; + } } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java Tue Jul 09 17:55:02 2013 +0200 @@ -22,13 +22,17 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.extended.*; -public class G1PreWriteBarrier extends WriteBarrier { +public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode { @Input private ValueNode expectedObject; private final boolean doLoad; + @Input private FrameState deoptimizationState; + private final boolean nullCheck; + public ValueNode getExpectedObject() { return expectedObject; } @@ -37,9 +41,35 @@ return doLoad; } - public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) { + public boolean getNullCheck() { + return nullCheck; + } + + public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) { super(object, location, true); this.doLoad = doLoad; + this.nullCheck = nullCheck; this.expectedObject = expectedObject; } + + @Override + public boolean canDeoptimize() { + return nullCheck; + } + + @Override + public FrameState getDeoptimizationState() { + return deoptimizationState; + } + + @Override + public void setDeoptimizationState(FrameState state) { + updateUsages(deoptimizationState, state); + deoptimizationState = state; + } + + @Override + public DeoptimizationReason getDeoptimizationReason() { + return DeoptimizationReason.NullCheckException; + } } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java Tue Jul 09 17:55:02 2013 +0200 @@ -54,7 +54,7 @@ @Override public void lower(LoweringTool generator, LoweringType loweringType) { - assert loweringType == LoweringType.AFTER_GUARDS; + assert loweringType == LoweringType.AFTER_FSA; generator.getRuntime().lower(this, generator); } } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Tue Jul 09 17:55:02 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -30,7 +31,7 @@ /** * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations. */ -public class AbstractNewArrayNode extends FixedWithNextNode implements Canonicalizable, Lowerable, ArrayLengthProvider, Node.IterableNodeType { +public class AbstractNewArrayNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, ArrayLengthProvider, Node.IterableNodeType { @Input private ValueNode length; private final boolean fillContents; @@ -88,4 +89,14 @@ public void lower(LoweringTool tool, LoweringType loweringType) { tool.getRuntime().lower(this, tool); } + + @Override + public boolean canDeoptimize() { + return true; + } + + @Override + public DeoptimizationReason getDeoptimizationReason() { + return DeoptimizationReason.RuntimeConstraint; + } } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Tue Jul 09 17:55:02 2013 +0200 @@ -33,7 +33,7 @@ * The {@code NewInstanceNode} represents the allocation of an instance class object. */ @NodeInfo(nameTemplate = "New {p#instanceClass/s}") -public final class NewInstanceNode extends FixedWithNextNode implements Node.IterableNodeType, Canonicalizable, Lowerable, VirtualizableAllocation { +public final class NewInstanceNode extends DeoptimizingFixedWithNextNode implements Node.IterableNodeType, Canonicalizable, Lowerable, VirtualizableAllocation { private final ResolvedJavaType instanceClass; private final boolean fillContents; @@ -95,4 +95,14 @@ tool.replaceWithVirtual(virtualObject); } } + + @Override + public boolean canDeoptimize() { + return true; + } + + @Override + public DeoptimizationReason getDeoptimizationReason() { + return DeoptimizationReason.RuntimeConstraint; + } } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Tue Jul 09 17:55:02 2013 +0200 @@ -31,7 +31,7 @@ /** * The {@code NewMultiArrayNode} represents an allocation of a multi-dimensional object array. */ -public final class NewMultiArrayNode extends FixedWithNextNode implements Lowerable { +public final class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable { @Input private final NodeInputList dimensions; private final ResolvedJavaType type; @@ -69,4 +69,14 @@ public ResolvedJavaType type() { return type; } + + @Override + public boolean canDeoptimize() { + return true; + } + + @Override + public DeoptimizationReason getDeoptimizationReason() { + return DeoptimizationReason.RuntimeConstraint; + } } diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java Tue Jul 09 17:55:02 2013 +0200 @@ -25,7 +25,7 @@ public interface Lowerable { public enum LoweringType { - BEFORE_GUARDS, AFTER_GUARDS + BEFORE_GUARDS, AFTER_GUARDS, AFTER_FSA } void lower(LoweringTool tool, LoweringType loweringType); diff -r d59e7f94f28d -r 853a894e0d97 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue Jul 09 17:54:48 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue Jul 09 17:55:02 2013 +0200 @@ -488,6 +488,7 @@ // Remove all frame states from inlined snippet graph. Snippets must be atomic (i.e. free // of side-effects that prevent deoptimizing to a point before the snippet). ArrayList curSideEffectNodes = new ArrayList<>(); + ArrayList curDeoptNodes = new ArrayList<>(); ArrayList curStampNodes = new ArrayList<>(); for (Node node : snippetCopy.getNodes()) { if (node instanceof ValueNode && ((ValueNode) node).stamp() == StampFactory.forNodeIntrinsic()) { @@ -503,6 +504,12 @@ stateSplit.setStateAfter(null); } } + if (node instanceof DeoptimizingNode) { + DeoptimizingNode deoptNode = (DeoptimizingNode) node; + if (deoptNode.canDeoptimize()) { + curDeoptNodes.add(deoptNode); + } + } } new DeadCodeEliminationPhase().apply(snippetCopy); @@ -528,6 +535,7 @@ } this.sideEffectNodes = curSideEffectNodes; + this.deoptNodes = curDeoptNodes; this.stampNodes = curStampNodes; this.returnNode = retNode; } @@ -589,6 +597,12 @@ private final ArrayList sideEffectNodes; /** + * Nodes that inherit the {@link DeoptimizingNode#getDeoptimizationState()} from the replacee + * during insantiation. + */ + private final ArrayList deoptNodes; + + /** * The nodes that inherit the {@link ValueNode#stamp()} from the replacee during instantiation. */ private final ArrayList stampNodes; @@ -743,6 +757,17 @@ ((StateSplit) sideEffectDup).setStateAfter(((StateSplit) replacee).stateAfter()); } } + + if (replacee instanceof DeoptimizingNode) { + DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee; + FrameState state = replaceeDeopt.getDeoptimizationState(); + for (DeoptimizingNode deoptNode : deoptNodes) { + DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode); + assert replaceeDeopt.canDeoptimize() || !deoptDup.canDeoptimize(); + deoptDup.setDeoptimizationState(state); + } + } + for (ValueNode stampNode : stampNodes) { Node stampDup = duplicates.get(stampNode); ((ValueNode) stampDup).setStamp(((ValueNode) replacee).stamp());