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;
+    }
 }