changeset 20123:81d08c81b2a7

Introduce TypeCheckNode.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 01 Apr 2015 17:43:06 +0200
parents 45d46b136777
children a9c8df485789
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java
diffstat 3 files changed, 191 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Apr 01 16:36:28 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Apr 01 17:43:06 2015 +0200
@@ -112,6 +112,10 @@
             if (graph.getGuardsStage().areDeoptsFixed()) {
                 instanceofSnippets.lower((InstanceOfNode) n, tool);
             }
+        } else if (n instanceof TypeCheckNode) {
+            if (graph.getGuardsStage().areDeoptsFixed()) {
+                instanceofSnippets.lower((TypeCheckNode) n, tool);
+            }
         } else if (n instanceof InstanceOfDynamicNode) {
             if (graph.getGuardsStage().areDeoptsFixed()) {
                 instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Apr 01 16:36:28 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Apr 01 17:43:06 2015 +0200
@@ -267,6 +267,13 @@
                 }
                 return args;
 
+            } else if (replacer.instanceOf instanceof TypeCheckNode) {
+                TypeCheckNode typeCheck = (TypeCheckNode) replacer.instanceOf;
+                ValueNode object = typeCheck.getValue();
+                Arguments args = new Arguments(instanceofExact, typeCheck.graph().getGuardsStage(), tool.getLoweringStage());
+                args.add("object", object);
+                args.add("exactHub", ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) typeCheck.type()).klass(), providers.getMetaAccess(), typeCheck.graph()));
+                return args;
             } else if (replacer.instanceOf instanceof InstanceOfDynamicNode) {
                 InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf;
                 ValueNode object = instanceOf.object();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java	Wed Apr 01 17:43:06 2015 +0200
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.java;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.Assumptions.AssumptionResult;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * The {@code TypeCheckNode} represents a test equivalent to (o != null && o.getClass() == type).
+ */
+@NodeInfo
+public final class TypeCheckNode extends UnaryOpLogicNode implements Lowerable, Virtualizable {
+    public static final NodeClass<TypeCheckNode> TYPE = NodeClass.create(TypeCheckNode.class);
+
+    protected final ResolvedJavaType type;
+
+    protected TypeCheckNode(ResolvedJavaType type, ValueNode object) {
+        super(TYPE, object);
+        this.type = type;
+        assert type != null;
+        assert type.isConcrete();
+    }
+
+    public static LogicNode create(ResolvedJavaType type, ValueNode object) {
+        ObjectStamp objectStamp = (ObjectStamp) object.stamp();
+        LogicNode constantValue = findSynonym(type, objectStamp.type(), objectStamp.nonNull(), objectStamp.isExactType());
+        if (constantValue != null) {
+            return constantValue;
+        } else {
+            return new TypeCheckNode(type, object);
+        }
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (!(forValue.stamp() instanceof ObjectStamp)) {
+            return this;
+        }
+        ObjectStamp objectStamp = (ObjectStamp) forValue.stamp();
+        if (objectStamp.alwaysNull()) {
+            return LogicConstantNode.contradiction();
+        }
+
+        ResolvedJavaType stampType = objectStamp.type();
+        if (stampType != null) {
+            ValueNode result = check(forValue, stampType, objectStamp.nonNull(), objectStamp.isExactType());
+            if (result != null) {
+                return result;
+            }
+            Assumptions assumptions = graph().getAssumptions();
+            if (assumptions != null) {
+                AssumptionResult<ResolvedJavaType> leafConcreteSubtype = stampType.findLeafConcreteSubtype();
+                if (leafConcreteSubtype != null) {
+                    result = check(forValue, leafConcreteSubtype.getResult(), objectStamp.nonNull(), true);
+                    if (result != null) {
+                        assumptions.record(leafConcreteSubtype);
+                        return result;
+                    }
+                }
+            }
+        }
+        return this;
+    }
+
+    private ValueNode check(ValueNode forValue, ResolvedJavaType inputType, boolean nonNull, boolean exactType) {
+        ValueNode result = findSynonym(type(), inputType, nonNull, exactType);
+        if (result != null) {
+            return result;
+        }
+        if (type().equals(inputType)) {
+            if (!nonNull) {
+                // the instanceof matches if the object is non-null, so return true
+                // depending on the null-ness.
+                return LogicNegationNode.create(new IsNullNode(forValue));
+            }
+        }
+        return null;
+    }
+
+    public static LogicNode findSynonym(ResolvedJavaType type, ResolvedJavaType inputType, boolean nonNull, boolean exactType) {
+        if (inputType == null) {
+            return null;
+        }
+        if (type.equals(inputType)) {
+            if (nonNull) {
+                // the type matches, so return true
+                return LogicConstantNode.tautology();
+            }
+        } else {
+            if (exactType) {
+                // since this type check failed for an exact type we know that it can never
+                // succeed at run time. we also don't care about null values, since they will
+                // also make the check fail.
+                return LogicConstantNode.contradiction();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets the type being tested.
+     */
+    public ResolvedJavaType type() {
+        return type;
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(getValue());
+        if (state != null) {
+            tool.replaceWithValue(LogicConstantNode.forBoolean(type().equals(state.getVirtualObject().type()), graph()));
+        }
+    }
+
+    @Override
+    public Stamp getSucceedingStampForValue(boolean negated) {
+        if (negated) {
+            return null;
+        } else {
+            return StampFactory.exactNonNull(type);
+        }
+    }
+
+    @Override
+    public TriState tryFold(Stamp valueStamp) {
+        if (valueStamp instanceof ObjectStamp) {
+            ObjectStamp objectStamp = (ObjectStamp) valueStamp;
+            if (objectStamp.alwaysNull()) {
+                return TriState.FALSE;
+            }
+
+            ResolvedJavaType objectType = objectStamp.type();
+            if (objectType != null) {
+                ResolvedJavaType instanceofType = type;
+                if (instanceofType.equals(objectType)) {
+                    if (objectStamp.nonNull()) {
+                        return TriState.TRUE;
+                    }
+                } else {
+                    if (objectStamp.isExactType()) {
+                        return TriState.FALSE;
+                    }
+                }
+            }
+        }
+        return TriState.UNKNOWN;
+    }
+}