Mercurial > hg > graal-compiler
changeset 8295:60f90b4b6a12
Implement implicit null check on HIR during guard lowering
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Thu, 14 Mar 2013 21:36:28 +0100 |
parents | 5439cc2d73af |
children | ec8ed9925f5a |
files | graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java |
diffstat | 5 files changed, 106 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Thu Mar 14 14:02:23 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Thu Mar 14 21:36:28 2013 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes; +import java.util.*; + import com.oracle.graal.nodes.type.*; public abstract class FixedNode extends ValueNode { @@ -32,6 +34,10 @@ super(stamp); } + public FixedNode(Stamp stamp, List<ValueNode> dependencies) { + super(stamp, dependencies); + } + public FixedNode(Stamp stamp, ValueNode... dependencies) { super(stamp, dependencies); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Thu Mar 14 14:02:23 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Thu Mar 14 21:36:28 2013 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes; +import java.util.*; + import com.oracle.graal.nodes.type.*; /** @@ -43,6 +45,10 @@ super(stamp); } + public FixedWithNextNode(Stamp stamp, List<ValueNode> dependencies) { + super(stamp, dependencies); + } + public FixedWithNextNode(Stamp stamp, ValueNode... dependencies) { super(stamp, dependencies); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Thu Mar 14 14:02:23 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Thu Mar 14 21:36:28 2013 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.extended; +import java.util.*; + import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -58,6 +60,12 @@ this.location = location; } + public AccessNode(ValueNode object, ValueNode location, Stamp stamp, List<ValueNode> dependencies) { + super(stamp, dependencies); + this.object = object; + this.location = location; + } + public AccessNode(ValueNode object, ValueNode location, Stamp stamp, ValueNode... dependencies) { super(stamp, dependencies); this.object = object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu Mar 14 14:02:23 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu Mar 14 21:36:28 2013 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.extended; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -37,6 +39,10 @@ super(object, location, stamp); } + public ReadNode(ValueNode object, ValueNode location, Stamp stamp, List<ValueNode> dependencies) { + super(object, location, stamp, dependencies); + } + private ReadNode(ValueNode object, int displacement, Object locationIdentity, Kind kind) { super(object, object.graph().add(new LocationNode(locationIdentity, kind, displacement)), StampFactory.forKind(kind)); }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Thu Mar 14 14:02:23 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Thu Mar 14 21:36:28 2013 +0100 @@ -23,30 +23,46 @@ package com.oracle.graal.phases.common; import java.util.*; +import java.util.Map.Entry; +import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.schedule.*; public class GuardLoweringPhase extends Phase { + 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, graph); + processBlock(block, schedule, graph, target); } } - private static void processBlock(Block block, SchedulePhase schedule, StructuredGraph graph) { + private static void processBlock(Block block, SchedulePhase schedule, StructuredGraph graph, TargetDescription target) { List<ScheduledNode> nodes = schedule.nodesFor(block); + if (GraalOptions.OptImplicitNullChecks && target.implicitNullCheckLimit > 0) { + useImplicitNullChecks(block.getBeginNode(), nodes, graph, target); + } FixedWithNextNode lastFixed = block.getBeginNode(); BeginNode lastFastPath = null; for (Node node : nodes) { + if (!node.isAlive()) { + continue; + } if (lastFastPath != null && node instanceof FixedNode) { lastFastPath.setNext((FixedNode) node); lastFastPath = null; @@ -81,4 +97,66 @@ } } } + + private static void useImplicitNullChecks(BeginNode begin, List<ScheduledNode> nodes, StructuredGraph graph, TargetDescription target) { + ListIterator<ScheduledNode> iterator = nodes.listIterator(); + IdentityHashMap<ValueNode, GuardNode> 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; + } + + 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); + } + } else if (node instanceof Access) { + Access access = (Access) node; + GuardNode guard = nullGuarded.get(access.object()); + if (guard != null && isImplicitNullCheck(access.location(), target)) { + if (access instanceof FloatingReadNode) { + NodeInputList<ValueNode> dependencies = ((FloatingReadNode) access).dependencies(); + dependencies.remove(guard); + ReadNode read = graph.add(new ReadNode(access.object(), access.location(), ((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); + guard.replaceAndDelete(access.node()); + nullGuarded.remove(access.object()); + } + } + if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) { + nullGuarded.clear(); + } else { + Iterator<Entry<ValueNode, GuardNode>> it = nullGuarded.entrySet().iterator(); + while (it.hasNext()) { + Entry<ValueNode, GuardNode> entry = it.next(); + GuardNode guard = entry.getValue(); + if (guard.usages().contains(node)) { + it.remove(); + } + } + } + } + } + + private static boolean isImplicitNullCheck(LocationNode location, TargetDescription target) { + return !(location instanceof IndexedLocationNode) && location.displacement() < target.implicitNullCheckLimit; + } }