# HG changeset patch # User Gilles Duboscq # Date 1363801108 -3600 # Node ID 24ddd568aa0cc8b3063a9cdd629dc1414deb6937 # Parent a007cbe2be305b3d2a40e08cd034cb7b9dbf02eb Refactor GuardLoweringPhase: use the same iterator code for implict null checks and guard lowering diff -r a007cbe2be30 -r 24ddd568aa0c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Wed Mar 20 16:27:07 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Wed Mar 20 18:38:28 2013 +0100 @@ -37,124 +37,60 @@ public class GuardLoweringPhase extends Phase { - private TargetDescription target; + private abstract static class ScheduledNodeIterator { - public GuardLoweringPhase(TargetDescription target) { - this.target = target; - } + private FixedWithNextNode lastFixed; + private FixedWithNextNode reconnect; + private ListIterator iterator; - @Override - protected void run(StructuredGraph graph) { - SchedulePhase schedule = new SchedulePhase(); - schedule.apply(graph); + public void processNodes(List nodes, FixedWithNextNode begin) { + assert begin != null; + lastFixed = begin; + reconnect = null; + iterator = nodes.listIterator(); + while (iterator.hasNext()) { + Node node = iterator.next(); + if (!node.isAlive()) { + continue; + } + if (reconnect != null && node instanceof FixedNode) { + reconnect.setNext((FixedNode) node); + reconnect = null; + } + if (node instanceof FixedWithNextNode) { + lastFixed = (FixedWithNextNode) node; + } + processNode(node); + } + } - for (Block block : schedule.getCFG().getBlocks()) { - processBlock(block, schedule, graph, target); + protected void insert(FixedNode start, FixedWithNextNode end) { + this.lastFixed.setNext(start); + this.lastFixed = end; + this.reconnect = end; } + + protected void replaceCurrent(FixedWithNextNode newNode) { + Node current = iterator.previous(); + iterator.next(); // needed because of the previous() call + current.replaceAndDelete(newNode); + insert(newNode, newNode); + iterator.set(newNode); + } + + protected abstract void processNode(Node node); } - private static void processBlock(Block block, SchedulePhase schedule, StructuredGraph graph, TargetDescription target) { - List nodes = schedule.nodesFor(block); - if (GraalOptions.OptImplicitNullChecks && target.implicitNullCheckLimit > 0) { - useImplicitNullChecks(block.getBeginNode(), nodes, target); - } - FixedWithNextNode lastFixed = block.getBeginNode(); - FixedWithNextNode lastFastPath = null; - for (Node node : nodes) { - if (!node.isAlive()) { - continue; - } - if (lastFastPath != null && node instanceof FixedNode) { - lastFastPath.setNext((FixedNode) node); - lastFastPath = null; - } - if (node instanceof FixedWithNextNode) { - lastFixed = (FixedWithNextNode) node; - } else if (node instanceof GuardNode) { - GuardNode guard = (GuardNode) node; - if (guard.negated() && guard.condition() instanceof IsNullNode) { - IsNullNode isNull = (IsNullNode) guard.condition(); - NullCheckNode nullCheck = graph.add(new NullCheckNode(isNull.object())); - guard.replaceAndDelete(nullCheck); - lastFixed.setNext(nullCheck); - lastFixed = nullCheck; - lastFastPath = nullCheck; - } else { - BeginNode fastPath = graph.add(new BeginNode()); - BeginNode trueSuccessor; - BeginNode falseSuccessor; - DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason())); - BeginNode deoptBranch = BeginNode.begin(deopt); - Loop loop = block.getLoop(); - while (loop != null) { - LoopExitNode exit = graph.add(new LoopExitNode(loop.loopBegin())); - graph.addBeforeFixed(deopt, exit); - loop = loop.parent; - } - if (guard.negated()) { - trueSuccessor = deoptBranch; - falseSuccessor = fastPath; - } else { - trueSuccessor = fastPath; - falseSuccessor = deoptBranch; - } - IfNode ifNode = graph.add(new IfNode(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0)); - guard.replaceAndDelete(fastPath); - lastFixed.setNext(ifNode); - lastFixed = fastPath; - lastFastPath = fastPath; - } - } - } - } + private class UseImplicitNullChecks extends ScheduledNodeIterator { + + private final IdentityHashMap nullGuarded = new IdentityHashMap<>(); - private static void useImplicitNullChecks(BeginNode begin, List nodes, TargetDescription target) { - ListIterator iterator = nodes.listIterator(); - IdentityHashMap nullGuarded = new IdentityHashMap<>(); - FixedWithNextNode lastFixed = begin; - FixedWithNextNode reconnect = null; - while (iterator.hasNext()) { - Node node = iterator.next(); - - if (reconnect != null && node instanceof FixedNode) { - reconnect.setNext((FixedNode) node); - reconnect = null; - } - if (node instanceof FixedWithNextNode) { - lastFixed = (FixedWithNextNode) node; - } - + @Override + protected void processNode(Node node) { if (node instanceof GuardNode) { - GuardNode guard = (GuardNode) node; - if (guard.negated() && guard.condition() instanceof IsNullNode) { - ValueNode obj = ((IsNullNode) guard.condition()).object(); - nullGuarded.put(obj, guard); - } + processGuard(node); } else if (node instanceof Access) { - Access access = (Access) node; - GuardNode guard = nullGuarded.get(access.object()); - if (guard != null && isImplicitNullCheck(access.nullCheckLocation(), target)) { - NodeInputList dependencies = ((ValueNode) access).dependencies(); - dependencies.remove(guard); - if (access instanceof FloatingAccessNode) { - Access fixedRead = ((FloatingAccessNode) access).asFixedNode(); - node.replaceAndDelete(fixedRead.node()); - access = fixedRead; - FixedWithNextNode fixedAccess = (FixedWithNextNode) fixedRead.node(); - lastFixed.setNext(fixedAccess); - lastFixed = fixedAccess; - reconnect = fixedAccess; - iterator.set(fixedAccess); - } - assert access instanceof FixedNode; - access.setNullCheck(true); - LogicNode condition = guard.condition(); - guard.replaceAndDelete(access.node()); - if (condition.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(condition); - } - nullGuarded.remove(access.object()); - } + processAccess((Access) node); } if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) { nullGuarded.clear(); @@ -169,9 +105,119 @@ } } } + + private void processAccess(Access access) { + GuardNode guard = nullGuarded.get(access.object()); + if (guard != null && isImplicitNullCheck(access.nullCheckLocation())) { + NodeInputList dependencies = ((ValueNode) access).dependencies(); + dependencies.remove(guard); + Access fixedAccess = access; + if (access instanceof FloatingAccessNode) { + fixedAccess = ((FloatingAccessNode) access).asFixedNode(); + replaceCurrent((FixedWithNextNode) fixedAccess.node()); + } + assert fixedAccess instanceof FixedNode; + fixedAccess.setNullCheck(true); + LogicNode condition = guard.condition(); + guard.replaceAndDelete(fixedAccess.node()); + if (condition.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(condition); + } + nullGuarded.remove(fixedAccess.object()); + } + } + + private void processGuard(Node node) { + GuardNode guard = (GuardNode) node; + if (guard.negated() && guard.condition() instanceof IsNullNode) { + ValueNode obj = ((IsNullNode) guard.condition()).object(); + nullGuarded.put(obj, guard); + } + } } - private static boolean isImplicitNullCheck(LocationNode location, TargetDescription target) { + private class LowerGuards extends ScheduledNodeIterator { + + private final Block block; + + public LowerGuards(Block block) { + this.block = block; + } + + @Override + protected void processNode(Node node) { + if (node instanceof GuardNode) { + GuardNode guard = (GuardNode) node; + if (guard.negated() && guard.condition() instanceof IsNullNode) { + lowerToNullCheck(guard); + } else { + lowerToIf(guard); + } + } + } + + private void lowerToIf(GuardNode guard) { + StructuredGraph graph = (StructuredGraph) guard.graph(); + BeginNode fastPath = graph.add(new BeginNode()); + DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason())); + BeginNode deoptBranch = BeginNode.begin(deopt); + BeginNode trueSuccessor; + BeginNode falseSuccessor; + insertLoopExits(deopt); + if (guard.negated()) { + trueSuccessor = deoptBranch; + falseSuccessor = fastPath; + } else { + trueSuccessor = fastPath; + falseSuccessor = deoptBranch; + } + IfNode ifNode = graph.add(new IfNode(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0)); + guard.replaceAndDelete(fastPath); + insert(ifNode, fastPath); + } + + private void lowerToNullCheck(GuardNode guard) { + IsNullNode isNull = (IsNullNode) guard.condition(); + NullCheckNode nullCheck = guard.graph().add(new NullCheckNode(isNull.object())); + replaceCurrent(nullCheck); + } + + private void insertLoopExits(DeoptimizeNode deopt) { + Loop loop = block.getLoop(); + StructuredGraph graph = (StructuredGraph) deopt.graph(); + while (loop != null) { + LoopExitNode exit = graph.add(new LoopExitNode(loop.loopBegin())); + graph.addBeforeFixed(deopt, exit); + loop = loop.parent; + } + } + } + + private TargetDescription target; + + public GuardLoweringPhase(TargetDescription target) { + this.target = target; + } + + @Override + protected void run(StructuredGraph graph) { + SchedulePhase schedule = new SchedulePhase(); + schedule.apply(graph); + + for (Block block : schedule.getCFG().getBlocks()) { + processBlock(block, schedule); + } + } + + private void processBlock(Block block, SchedulePhase schedule) { + List nodes = schedule.nodesFor(block); + if (GraalOptions.OptImplicitNullChecks && target.implicitNullCheckLimit > 0) { + new UseImplicitNullChecks().processNodes(nodes, block.getBeginNode()); + } + new LowerGuards(block).processNodes(nodes, block.getBeginNode()); + } + + private boolean isImplicitNullCheck(LocationNode location) { return !(location instanceof IndexedLocationNode) && location.displacement() < target.implicitNullCheckLimit; } }