44 import org.graalvm.compiler.debug.GraalError; |
44 import org.graalvm.compiler.debug.GraalError; |
45 import org.graalvm.compiler.graph.Graph.Mark; |
45 import org.graalvm.compiler.graph.Graph.Mark; |
46 import org.graalvm.compiler.graph.Node; |
46 import org.graalvm.compiler.graph.Node; |
47 import org.graalvm.compiler.graph.NodeBitMap; |
47 import org.graalvm.compiler.graph.NodeBitMap; |
48 import org.graalvm.compiler.graph.NodeClass; |
48 import org.graalvm.compiler.graph.NodeClass; |
|
49 import org.graalvm.compiler.graph.NodeMap; |
49 import org.graalvm.compiler.graph.NodeSourcePosition; |
50 import org.graalvm.compiler.graph.NodeSourcePosition; |
50 import org.graalvm.compiler.graph.iterators.NodeIterable; |
51 import org.graalvm.compiler.graph.iterators.NodeIterable; |
51 import org.graalvm.compiler.nodeinfo.InputType; |
52 import org.graalvm.compiler.nodeinfo.InputType; |
52 import org.graalvm.compiler.nodeinfo.NodeInfo; |
53 import org.graalvm.compiler.nodeinfo.NodeInfo; |
53 import org.graalvm.compiler.nodes.AbstractBeginNode; |
54 import org.graalvm.compiler.nodes.AbstractBeginNode; |
129 |
130 |
130 private final CoreProviders context; |
131 private final CoreProviders context; |
131 private final NodeBitMap activeGuards; |
132 private final NodeBitMap activeGuards; |
132 private AnchoringNode guardAnchor; |
133 private AnchoringNode guardAnchor; |
133 private FixedWithNextNode lastFixedNode; |
134 private FixedWithNextNode lastFixedNode; |
134 |
135 private NodeMap<Block> nodeMap; |
135 LoweringToolImpl(CoreProviders context, AnchoringNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode) { |
136 |
|
137 LoweringToolImpl(CoreProviders context, AnchoringNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode, NodeMap<Block> nodeMap) { |
136 this.context = context; |
138 this.context = context; |
137 this.guardAnchor = guardAnchor; |
139 this.guardAnchor = guardAnchor; |
138 this.activeGuards = activeGuards; |
140 this.activeGuards = activeGuards; |
139 this.lastFixedNode = lastFixedNode; |
141 this.lastFixedNode = lastFixedNode; |
|
142 this.nodeMap = nodeMap; |
140 } |
143 } |
141 |
144 |
142 @Override |
145 @Override |
143 public LoweringStage getLoweringStage() { |
146 public LoweringStage getLoweringStage() { |
144 return loweringStage; |
147 return loweringStage; |
197 public GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, Speculation speculation, boolean negated, |
200 public GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, Speculation speculation, boolean negated, |
198 NodeSourcePosition noDeoptSucccessorPosition) { |
201 NodeSourcePosition noDeoptSucccessorPosition) { |
199 StructuredGraph graph = before.graph(); |
202 StructuredGraph graph = before.graph(); |
200 if (OptEliminateGuards.getValue(graph.getOptions())) { |
203 if (OptEliminateGuards.getValue(graph.getOptions())) { |
201 for (Node usage : condition.usages()) { |
204 for (Node usage : condition.usages()) { |
202 if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).isNegated() == negated) { |
205 if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).isNegated() == negated && |
|
206 (!before.graph().hasValueProxies() || nodeMap.get(((GuardNode) usage).getAnchor().asNode()).isInSameOrOuterLoopOf(nodeMap.get(before)))) { |
203 return (GuardNode) usage; |
207 return (GuardNode) usage; |
204 } |
208 } |
205 } |
209 } |
206 } |
210 } |
207 if (!condition.graph().getGuardsStage().allowsFloatingGuards()) { |
211 if (!condition.graph().getGuardsStage().allowsFloatingGuards()) { |
308 * checkpoint. This is only OK if the locations involved don't affect the memory |
312 * checkpoint. This is only OK if the locations involved don't affect the memory |
309 * graph or if the new kill location doesn't connect into the existing graph. |
313 * graph or if the new kill location doesn't connect into the existing graph. |
310 */ |
314 */ |
311 boolean isAny = false; |
315 boolean isAny = false; |
312 if (n instanceof MemoryCheckpoint.Single) { |
316 if (n instanceof MemoryCheckpoint.Single) { |
313 isAny = ((MemoryCheckpoint.Single) n).getLocationIdentity().isAny(); |
317 isAny = ((MemoryCheckpoint.Single) n).getKilledLocationIdentity().isAny(); |
314 } else { |
318 } else { |
315 for (LocationIdentity ident : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) { |
319 for (LocationIdentity ident : ((MemoryCheckpoint.Multi) n).getKilledLocationIdentities()) { |
316 if (ident.isAny()) { |
320 if (ident.isAny()) { |
317 isAny = true; |
321 isAny = true; |
318 } |
322 } |
319 } |
323 } |
320 } |
324 } |
445 } |
449 } |
446 |
450 |
447 @SuppressWarnings("try") |
451 @SuppressWarnings("try") |
448 private AnchoringNode process(final Block b, final NodeBitMap activeGuards, final AnchoringNode startAnchor) { |
452 private AnchoringNode process(final Block b, final NodeBitMap activeGuards, final AnchoringNode startAnchor) { |
449 |
453 |
450 final LoweringToolImpl loweringTool = new LoweringToolImpl(context, startAnchor, activeGuards, b.getBeginNode()); |
454 final LoweringToolImpl loweringTool = new LoweringToolImpl(context, startAnchor, activeGuards, b.getBeginNode(), this.schedule.getNodeToBlockMap()); |
451 |
455 |
452 // Lower the instructions of this block. |
456 // Lower the instructions of this block. |
453 List<Node> nodes = schedule.nodesFor(b); |
457 List<Node> nodes = schedule.nodesFor(b); |
454 for (Node node : nodes) { |
458 for (Node node : nodes) { |
455 |
459 |
611 } |
615 } |
612 state = nextState; |
616 state = nextState; |
613 } |
617 } |
614 } |
618 } |
615 |
619 |
616 public static void processBlockBounded(final Frame<?> rootFrame) { |
|
617 ProcessBlockState state = ST_PROCESS; |
|
618 Frame<?> f = rootFrame; |
|
619 while (f != null) { |
|
620 ProcessBlockState nextState; |
|
621 if (state == ST_PROCESS || state == ST_PROCESS_ALWAYS_REACHED) { |
|
622 f.preprocess(); |
|
623 nextState = state == ST_PROCESS_ALWAYS_REACHED ? ST_ENTER : ST_ENTER_ALWAYS_REACHED; |
|
624 } else if (state == ST_ENTER_ALWAYS_REACHED) { |
|
625 if (f.alwaysReachedBlock != null && f.alwaysReachedBlock.getDominator() == f.block) { |
|
626 Frame<?> continueRecur = f.enterAlwaysReached(f.alwaysReachedBlock); |
|
627 if (continueRecur == null) { |
|
628 // stop recursion here |
|
629 f.postprocess(); |
|
630 f = f.parent; |
|
631 state = ST_ENTER; |
|
632 continue; |
|
633 } |
|
634 f = continueRecur; |
|
635 nextState = ST_PROCESS; |
|
636 } else { |
|
637 nextState = ST_ENTER; |
|
638 } |
|
639 } else if (state == ST_ENTER) { |
|
640 if (f.dominated != null) { |
|
641 Block n = f.dominated; |
|
642 f.dominated = n.getDominatedSibling(); |
|
643 if (n == f.alwaysReachedBlock) { |
|
644 if (f.dominated != null) { |
|
645 n = f.dominated; |
|
646 f.dominated = n.getDominatedSibling(); |
|
647 } else { |
|
648 n = null; |
|
649 } |
|
650 } |
|
651 if (n == null) { |
|
652 nextState = ST_LEAVE; |
|
653 } else { |
|
654 Frame<?> continueRecur = f.enter(n); |
|
655 if (continueRecur == null) { |
|
656 // stop recursion here |
|
657 f.postprocess(); |
|
658 f = f.parent; |
|
659 state = ST_ENTER; |
|
660 continue; |
|
661 } |
|
662 f = continueRecur; |
|
663 nextState = ST_PROCESS; |
|
664 } |
|
665 } else { |
|
666 nextState = ST_LEAVE; |
|
667 } |
|
668 } else if (state == ST_LEAVE) { |
|
669 f.postprocess(); |
|
670 f = f.parent; |
|
671 nextState = ST_ENTER; |
|
672 } else { |
|
673 throw GraalError.shouldNotReachHere(); |
|
674 } |
|
675 state = nextState; |
|
676 } |
|
677 } |
|
678 |
|
679 public abstract static class Frame<T extends Frame<?>> { |
620 public abstract static class Frame<T extends Frame<?>> { |
680 protected final Block block; |
621 protected final Block block; |
681 final T parent; |
622 final T parent; |
682 Block dominated; |
623 Block dominated; |
683 final Block alwaysReachedBlock; |
624 final Block alwaysReachedBlock; |