# HG changeset patch # User Doug Simon # Date 1363855487 -3600 # Node ID 7e281cb9ea1028549a9dd1485601d9939dc0c299 # Parent 102b5249e97ee41cb5f914294a350038e12c6442# Parent 743d0ac1fc816311079bf227eacdadacd5802188 Merge. diff -r 102b5249e97e -r 7e281cb9ea10 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Wed Mar 20 22:30:33 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Thu Mar 21 09:44:47 2013 +0100 @@ -1073,7 +1073,11 @@ } private static boolean optimizeMethodArgument(Value value) { - return isStackSlot(value) && asStackSlot(value).isInCallerFrame() && (GraalOptions.IncomingMethodArgumentsGCSafe || value.getKind() != Kind.Object); + /* + * Object method arguments that are passed on the stack are currently not optimized because + * this requires that the runtime visits method arguments during stack walking. + */ + return isStackSlot(value) && asStackSlot(value).isInCallerFrame() && value.getKind() != Kind.Object; } /** diff -r 102b5249e97e -r 7e281cb9ea10 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Wed Mar 20 22:30:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Thu Mar 21 09:44:47 2013 +0100 @@ -77,4 +77,6 @@ public Node node() { return this; } + + public abstract Access asFixedNode(); } diff -r 102b5249e97e -r 7e281cb9ea10 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Wed Mar 20 22:30:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Thu Mar 21 09:44:47 2013 +0100 @@ -60,4 +60,9 @@ public ValueNode canonical(CanonicalizerTool tool) { return ReadNode.canonicalizeRead(this, location(), object(), tool); } + + @Override + public Access asFixedNode() { + return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), dependencies())); + } } diff -r 102b5249e97e -r 7e281cb9ea10 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 22:30:33 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Thu Mar 21 09:44:47 2013 +0100 @@ -37,123 +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, graph, 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, StructuredGraph graph, 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 FloatingReadNode) { - ReadNode read = graph.add(new ReadNode(access.object(), access.nullCheckLocation(), ((FloatingReadNode) access).stamp(), dependencies)); - node.replaceAndDelete(read); - access = read; - lastFixed.setNext(read); - lastFixed = read; - reconnect = read; - iterator.set(read); - } - assert access instanceof AccessNode; - 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(); @@ -168,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; } } diff -r 102b5249e97e -r 7e281cb9ea10 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Mar 20 22:30:33 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Mar 21 09:44:47 2013 +0100 @@ -211,12 +211,6 @@ public static boolean IntrinsifyAESMethods = true; /** - * Method arguments that are passed on the stack can be optimized by the register allocator to avoid spilling - * and reloading. However, this requires that the runtime visits method arguments during stack walking. - */ - public static boolean IncomingMethodArgumentsGCSafe = true; - - /** * Counts the various paths taken through snippets. */ public static boolean SnippetCounters = false; diff -r 102b5249e97e -r 7e281cb9ea10 src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java --- a/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Wed Mar 20 22:30:33 2013 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Thu Mar 21 09:44:47 2013 +0100 @@ -207,12 +207,16 @@ InputNode nodeTo = inputNodeMap.get(a.getNode(to)); char fromIndex = e.getFromIndex(); char toIndex = e.getToIndex(); - - InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); - if (!newEdges.contains(newEdge)) { - markAsDeleted(newEdge); - newEdges.add(newEdge); - graph.addEdge(newEdge); + + if (nodeFrom == null || nodeTo == null) { + System.out.println("Unexpected edge : " + from + " -> " + to); + } else { + InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); + if (!newEdges.contains(newEdge)) { + markAsDeleted(newEdge); + newEdges.add(newEdge); + graph.addEdge(newEdge); + } } } @@ -224,17 +228,21 @@ char fromIndex = e.getFromIndex(); char toIndex = e.getToIndex(); - InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); - if (!newEdges.contains(newEdge)) { - markAsNew(newEdge); - newEdges.add(newEdge); - graph.addEdge(newEdge); + if (nodeFrom == null || nodeTo == null) { + System.out.println("Unexpected edge : " + from + " -> " + to); } else { - newEdges.remove(newEdge); - graph.removeEdge(newEdge); - markAsSame(newEdge); - newEdges.add(newEdge); - graph.addEdge(newEdge); + InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); + if (!newEdges.contains(newEdge)) { + markAsNew(newEdge); + newEdges.add(newEdge); + graph.addEdge(newEdge); + } else { + newEdges.remove(newEdge); + graph.removeEdge(newEdge); + markAsSame(newEdge); + newEdges.add(newEdge); + graph.addEdge(newEdge); + } } }