changeset 21501:ce585b0ac3e2

Create different nodes in the graph builder when instanceof and checkcast have a single type profile.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 26 May 2015 21:22:00 +0200
parents ac86179c56ad
children 553445b73d99 fc376e0b80ba
files graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java
diffstat 4 files changed, 80 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Tue May 26 20:48:30 2015 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Tue May 26 21:22:00 2015 +0200
@@ -174,4 +174,22 @@
         }
         return buf.append(String.format("], notRecorded:%.6f>", getNotRecordedProbability())).toString();
     }
+
+    /**
+     * Returns {@code true} if all types seen at this location have been recorded in the profile.
+     */
+    public boolean allTypesRecorded() {
+        return this.getNotRecordedProbability() == 0.0;
+    }
+
+    /**
+     * Returns the single monormorphic type representing this profile or {@code null} if no such
+     * type exists.
+     */
+    public ResolvedJavaType asSingleType() {
+        if (allTypesRecorded() && this.getTypes().length == 1) {
+            return getTypes()[0].getType();
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue May 26 20:48:30 2015 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue May 26 21:22:00 2015 +0200
@@ -3068,7 +3068,26 @@
                     JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
                     TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin();
                     if (typeCheckPlugin == null || !typeCheckPlugin.checkCast(this, object, resolvedType, profile)) {
-                        ValueNode checkCastNode = append(createCheckCast(resolvedType, object, profile, false));
+                        ValueNode checkCastNode = null;
+                        if (profile != null) {
+                            if (profile.getNullSeen().isFalse()) {
+                                object = append(GuardingPiNode.createNullCheck(object));
+                                ResolvedJavaType singleType = profile.asSingleType();
+                                if (singleType != null) {
+                                    LogicNode typeCheck = append(TypeCheckNode.create(singleType, object));
+                                    if (typeCheck.isTautology()) {
+                                        checkCastNode = object;
+                                    } else {
+                                        GuardingPiNode piNode = append(new GuardingPiNode(object, typeCheck, false, DeoptimizationReason.TypeCheckedInliningViolated,
+                                                        DeoptimizationAction.InvalidateReprofile, StampFactory.exactNonNull(singleType)));
+                                        checkCastNode = piNode;
+                                    }
+                                }
+                            }
+                        }
+                        if (checkCastNode == null) {
+                            checkCastNode = append(createCheckCast(resolvedType, object, profile, false));
+                        }
                         frameState.apush(checkCastNode);
                     }
                 } else {
@@ -3085,7 +3104,21 @@
                     JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
                     TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin();
                     if (typeCheckPlugin == null || !typeCheckPlugin.instanceOf(this, object, resolvedType, profile)) {
-                        ValueNode instanceOfNode = createInstanceOf(resolvedType, object, profile);
+                        ValueNode instanceOfNode = null;
+                        if (profile != null) {
+                            if (profile.getNullSeen().isFalse()) {
+                                object = append(GuardingPiNode.createNullCheck(object));
+                                ResolvedJavaType singleType = profile.asSingleType();
+                                if (singleType != null) {
+                                    LogicNode typeCheck = append(TypeCheckNode.create(singleType, object));
+                                    append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
+                                    instanceOfNode = LogicConstantNode.forBoolean(resolvedType.isAssignableFrom(singleType));
+                                }
+                            }
+                        }
+                        if (instanceOfNode == null) {
+                            instanceOfNode = createInstanceOf(resolvedType, object, profile);
+                        }
                         frameState.ipush(append(genConditional(genUnique(instanceOfNode))));
                     }
                 } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Tue May 26 20:48:30 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Tue May 26 21:22:00 2015 +0200
@@ -81,6 +81,15 @@
         this.negated = negateCondition;
     }
 
+    public static ValueNode createNullCheck(ValueNode object) {
+        ObjectStamp objectStamp = (ObjectStamp) object.stamp();
+        if (objectStamp.nonNull()) {
+            return object;
+        } else {
+            return new GuardingPiNode(object);
+        }
+    }
+
     @Override
     public void lower(LoweringTool tool) {
         GuardingNode guard = tool.createGuard(next(), condition, reason, action, negated);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Tue May 26 20:48:30 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Tue May 26 21:22:00 2015 +0200
@@ -55,4 +55,22 @@
     public static LogicNode or(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) {
         return a.graph().unique(new ShortCircuitOrNode(a, negateA, b, negateB, shortCircuitProbability));
     }
+
+    public final boolean isTautology() {
+        if (this instanceof LogicConstantNode) {
+            LogicConstantNode logicConstantNode = (LogicConstantNode) this;
+            return logicConstantNode.getValue();
+        }
+
+        return false;
+    }
+
+    public final boolean isContradiction() {
+        if (this instanceof LogicConstantNode) {
+            LogicConstantNode logicConstantNode = (LogicConstantNode) this;
+            return !logicConstantNode.getValue();
+        }
+
+        return false;
+    }
 }