changeset 11265:ef6915cf1e59

Add illegal stamp Remove ValueNode.(object|integer)Stamp: use explicit tests/casts Fix ObjectStamp.join Introduce ObjectStamp.castTo Add some tests for ObjectStamp.join
author Gilles Duboscq <duboscq@ssw.jku.at>
date Thu, 08 Aug 2013 18:17:47 +0200
parents 7894695caee6
children 2290f6b53429
files graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXPhase.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerStampTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/StampTest.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java mx/projects
diffstat 75 files changed, 711 insertions(+), 306 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Thu Aug 08 18:17:47 2013 +0200
@@ -126,8 +126,8 @@
         @Override
         protected void run(StructuredGraph graph) {
             for (LocalNode local : graph.getNodes(LocalNode.class)) {
-                if (local.kind() == Kind.Object) {
-                    local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type()));
+                if (local.stamp() instanceof ObjectStamp) {
+                    local.setStamp(StampFactory.declaredNonNull(((ObjectStamp) local.stamp()).type()));
                 }
             }
         }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXPhase.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXPhase.java	Thu Aug 08 18:17:47 2013 +0200
@@ -22,23 +22,21 @@
  */
 package com.oracle.graal.compiler.ptx.test;
 
-import com.oracle.graal.api.meta.Kind;
-import com.oracle.graal.nodes.LocalNode;
-import com.oracle.graal.nodes.StructuredGraph;
-import com.oracle.graal.nodes.type.StampFactory;
-import com.oracle.graal.phases.Phase;
-
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
 
 public class PTXPhase extends Phase {
+
     @Override
     protected void run(StructuredGraph graph) {
         /*
-         * Assume that null checks would be done on the CPU caller side prior
-         * to copying data onto the GPU.
+         * Assume that null checks would be done on the CPU caller side prior to copying data onto
+         * the GPU.
          */
         for (LocalNode local : graph.getNodes(LocalNode.class)) {
-            if (local.kind() == Kind.Object) {
-                local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type()));
+            if (local.stamp() instanceof ObjectStamp) {
+                local.setStamp(StampFactory.declaredNonNull(((ObjectStamp) local.stamp()).type()));
             }
         }
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerStampTest.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerStampTest.java	Thu Aug 08 18:17:47 2013 +0200
@@ -42,51 +42,51 @@
 
     @Test
     public void testBooleanConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 1, 1, 0x1), ConstantNode.forBoolean(true, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forBoolean(false, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 1, 1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
     }
 
     @Test
     public void testByteConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forByte((byte) 0, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 16, 16, 0x10), ConstantNode.forByte((byte) 16, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, -16, -16, 0xf0), ConstantNode.forByte((byte) -16, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 127, 127, 0x7f), ConstantNode.forByte((byte) 127, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0x80), ConstantNode.forByte((byte) -128, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 16, 16, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, -16, -16, 0xf0), ConstantNode.forByte((byte) -16, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 127, 127, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0x80), ConstantNode.forByte((byte) -128, graph).stamp());
     }
 
     @Test
     public void testShortConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forShort((short) 0, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forShort((short) 128, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xff80), ConstantNode.forShort((short) -128, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 32767, 32767, 0x7fff), ConstantNode.forShort((short) 32767, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, -32768, -32768, 0x8000), ConstantNode.forShort((short) -32768, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xff80), ConstantNode.forShort((short) -128, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 32767, 32767, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, -32768, -32768, 0x8000), ConstantNode.forShort((short) -32768, graph).stamp());
     }
 
     @Test
     public void testCharConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forChar((char) 0, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 'A', 'A', 'A'), ConstantNode.forChar('A', graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forChar((char) 128, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 65535, 65535, 0xffff), ConstantNode.forChar((char) 65535, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 65535, 65535, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
     }
 
     @Test
     public void testIntConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forInt(0, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forInt(128, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xffffff80L), ConstantNode.forInt(-128, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Int, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forInt(0, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forInt(128, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Int, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testLongConstant() {
-        assertEquals(new IntegerStamp(Kind.Long, 0, 0, 0x0), ConstantNode.forLong(0, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Long, 128, 128, 0x80), ConstantNode.forLong(128, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Long, -128, -128, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Long, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).integerStamp());
-        assertEquals(new IntegerStamp(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Long, 0, 0, 0x0), ConstantNode.forLong(0, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Long, 128, 128, 0x80), ConstantNode.forLong(128, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Long, -128, -128, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Long, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Thu Aug 08 18:17:47 2013 +0200
@@ -68,7 +68,7 @@
                 for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) {
                     if (rn.location() instanceof ConstantLocationNode && rn.object().stamp() instanceof ObjectStamp) {
                         long disp = ((ConstantLocationNode) rn.location()).getDisplacement();
-                        ResolvedJavaType receiverType = rn.object().objectStamp().type();
+                        ResolvedJavaType receiverType = ObjectStamp.typeOrNull(rn.object());
                         ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp);
 
                         if (field != null) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Aug 08 18:17:47 2013 +0200
@@ -46,6 +46,7 @@
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.util.*;
 
@@ -365,6 +366,9 @@
     }
 
     protected void emitNode(ValueNode node) {
+        if (Debug.isLogEnabled() && node.stamp() == StampFactory.illegal()) {
+            Debug.log("This node has invalid type, we are emitting dead code(?): %s", node);
+        }
         ((LIRLowerable) node).generate(this);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Aug 08 18:17:47 2013 +0200
@@ -513,7 +513,7 @@
                 NodeInputList<ValueNode> parameters = callTarget.arguments();
                 ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
                 GuardingNode receiverNullCheck = null;
-                if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) {
+                if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !ObjectStamp.isObjectNonNull(receiver)) {
                     receiverNullCheck = tool.createNullCheckGuard(invoke, receiver);
                 }
                 JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
@@ -608,10 +608,10 @@
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index());
             ValueNode value = storeIndexed.value();
             ValueNode array = storeIndexed.array();
-            if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) {
+            if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) {
                 // Store check!
-                ResolvedJavaType arrayType = array.objectStamp().type();
-                if (arrayType != null && array.objectStamp().isExactType()) {
+                ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array);
+                if (arrayType != null && ObjectStamp.isExactType(array)) {
                     ResolvedJavaType elementType = arrayType.getComponentType();
                     if (!MetaUtil.isJavaLangObject(elementType)) {
                         CheckCastNode checkcast = graph.add(new CheckCastNode(elementType, value, null, true));
@@ -854,8 +854,15 @@
     }
 
     private static boolean addReadBarrier(UnsafeLoadNode load) {
-        return useG1GC() && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object && !load.object().objectStamp().alwaysNull() && load.object().objectStamp().type() != null &&
-                        !(load.object().objectStamp().type().isArray());
+        if (useG1GC()) {
+            if (load.object().kind() == Kind.Object && load.accessKind() == Kind.Object && !ObjectStamp.isObjectAlwaysNull(load.object())) {
+                ResolvedJavaType type = ObjectStamp.typeOrNull(load.object());
+                if (type != null && !type.isArray()) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     private static ReadNode createReadVirtualMethod(StructuredGraph graph, Kind wordKind, ValueNode hub, ResolvedJavaMethod method) {
@@ -910,7 +917,7 @@
     private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) {
         BarrierType barrierType = BarrierType.NONE;
         if (store.value().kind() == Kind.Object) {
-            ResolvedJavaType type = store.object().objectStamp().type();
+            ResolvedJavaType type = ObjectStamp.typeOrNull(store.object());
             if (type != null && !type.isArray()) {
                 barrierType = BarrierType.IMPRECISE;
             } else {
@@ -923,7 +930,7 @@
     private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
         BarrierType barrierType = BarrierType.NONE;
         if (cas.expected().kind() == Kind.Object) {
-            ResolvedJavaType type = cas.object().objectStamp().type();
+            ResolvedJavaType type = ObjectStamp.typeOrNull(cas.object());
             if (type != null && !type.isArray()) {
                 barrierType = BarrierType.IMPRECISE;
             } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -44,7 +44,7 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.java.SelfReplacingMethodCallTargetNode;
 import com.oracle.graal.nodes.spi.Canonicalizable;
-import com.oracle.graal.nodes.type.StampFactory;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.nodes.MacroNode;
 
 /**
@@ -200,7 +200,7 @@
 
         // Try to get the most accurate receiver type
         if (this instanceof MethodHandleLinkToVirtualNode || this instanceof MethodHandleLinkToInterfaceNode) {
-            ResolvedJavaType receiverType = getReceiver().objectStamp().type();
+            ResolvedJavaType receiverType = ObjectStamp.typeOrNull(getReceiver().stamp());
             if (receiverType != null) {
                 ResolvedJavaMethod concreteMethod = receiverType.findUniqueConcreteMethod(targetMethod);
                 if (concreteMethod != null) {
@@ -233,7 +233,7 @@
             ResolvedJavaType targetType = (ResolvedJavaType) type;
             if (!targetType.isPrimitive()) {
                 ValueNode argument = arguments.get(index);
-                ResolvedJavaType argumentType = argument.objectStamp().type();
+                ResolvedJavaType argumentType = ObjectStamp.typeOrNull(argument.stamp());
                 if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) {
                     PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType)));
                     arguments.set(index, piNode);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -62,13 +63,13 @@
     }
 
     private StructuredGraph selectSnippet(LoweringTool tool, Replacements replacements) {
-        ResolvedJavaType srcType = getSource().objectStamp().type();
-        ResolvedJavaType destType = getDestination().objectStamp().type();
+        ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp());
+        ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp());
 
         if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) {
             return null;
         }
-        if (!destType.getComponentType().isAssignableFrom(srcType.getComponentType()) || !getDestination().objectStamp().isExactType()) {
+        if (!destType.getComponentType().isAssignableFrom(srcType.getComponentType()) || !ObjectStamp.isExactType(getDestination().stamp())) {
             return null;
         }
         Kind componentKind = srcType.getComponentType().getKind();
@@ -126,10 +127,10 @@
                     if (state.getState() == EscapeState.Virtual) {
                         type = state.getVirtualObject().type();
                     } else {
-                        type = state.getMaterializedValue().objectStamp().type();
+                        type = ObjectStamp.typeOrNull(state.getMaterializedValue());
                     }
                 } else {
-                    type = entry.objectStamp().type();
+                    type = ObjectStamp.typeOrNull(entry);
                 }
                 if (type == null || !destComponentType.isAssignableFrom(type)) {
                     return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Thu Aug 08 18:17:47 2013 +0200
@@ -78,7 +78,7 @@
             Arguments args = new Arguments(dynamic);
             args.add("hub", checkcast.hub());
             args.add("object", object);
-            args.addConst("checkNull", !object.stamp().nonNull());
+            args.addConst("checkNull", !ObjectStamp.isObjectNonNull(object.stamp()));
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Thu Aug 08 18:17:47 2013 +0200
@@ -242,7 +242,7 @@
                 }
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
-                args.addConst("checkNull", !object.stamp().nonNull());
+                args.addConst("checkNull", !ObjectStamp.isObjectNonNull(object.stamp()));
                 if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet()) {
                     args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE);
                 }
@@ -258,7 +258,7 @@
                 args.add("object", object);
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
-                args.addConst("checkNull", !object.stamp().nonNull());
+                args.addConst("checkNull", !ObjectStamp.isObjectNonNull(object.stamp()));
                 return args;
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Thu Aug 08 18:17:47 2013 +0200
@@ -44,6 +44,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -409,7 +410,7 @@
             }
             args.add("object", monitorenterNode.object());
             args.addConst("lockDepth", monitorenterNode.getLockDepth());
-            args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull());
+            args.addConst("checkNull", !ObjectStamp.isObjectNonNull(monitorenterNode.object().stamp()));
             boolean tracingEnabledForMethod = stateAfter != null && (isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
             args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || tracingEnabledForMethod);
 
@@ -448,7 +449,7 @@
         }
 
         static boolean isTracingEnabledForType(ValueNode object) {
-            ResolvedJavaType type = object.objectStamp().type();
+            ResolvedJavaType type = ObjectStamp.typeOrNull(object.stamp());
             if (TRACE_TYPE_FILTER == null) {
                 return false;
             } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -56,7 +56,7 @@
             return null;
         }
 
-        ResolvedJavaType type = getObject().objectStamp().type();
+        ResolvedJavaType type = ObjectStamp.typeOrNull(getObject());
         Method method;
         /*
          * The first condition tests if the parameter is an array, the second condition tests if the
@@ -81,13 +81,17 @@
         return type != null && metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type);
     }
 
-    private static ResolvedJavaType getConcreteType(ObjectStamp stamp, Assumptions assumptions) {
-        if (stamp.isExactType() || stamp.type() == null) {
-            return stamp.type();
+    private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions) {
+        if (!(stamp instanceof ObjectStamp)) {
+            return null;
+        }
+        ObjectStamp objectStamp = (ObjectStamp) stamp;
+        if (objectStamp.isExactType() || objectStamp.type() == null) {
+            return objectStamp.type();
         } else {
-            ResolvedJavaType type = stamp.type().findUniqueConcreteSubtype();
+            ResolvedJavaType type = objectStamp.type().findUniqueConcreteSubtype();
             if (type != null) {
-                assumptions.recordConcreteSubtype(stamp.type(), type);
+                assumptions.recordConcreteSubtype(objectStamp.type(), type);
             }
             return type;
         }
@@ -114,7 +118,7 @@
             } else {
                 obj = tool.getReplacedValue(getObject());
             }
-            ResolvedJavaType type = getConcreteType(obj.objectStamp(), tool.getAssumptions());
+            ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions());
             if (isCloneableType(type, tool.getMetaAccessProvider())) {
                 if (!type.isArray()) {
                     VirtualInstanceNode newVirtual = new VirtualInstanceNode(type);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -64,13 +64,15 @@
         if (usages().isEmpty()) {
             return null;
         } else {
-            ObjectStamp stamp = getObject().objectStamp();
-            if (stamp.isExactType()) {
-                Constant clazz = stamp.type().getEncoding(Representation.JavaClass);
-                return ConstantNode.forConstant(clazz, tool.runtime(), graph());
-            } else {
-                return this;
+            Stamp stamp = getObject().stamp();
+            if (stamp instanceof ObjectStamp) {
+                ObjectStamp objectStamp = (ObjectStamp) stamp;
+                if (objectStamp.isExactType()) {
+                    Constant clazz = objectStamp.type().getEncoding(Representation.JavaClass);
+                    return ConstantNode.forConstant(clazz, tool.runtime(), graph());
+                }
             }
+            return this;
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Thu Aug 08 18:17:47 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -343,7 +344,7 @@
             args.add("object", writeBarrier.getObject());
             args.add("location", writeBarrier.getLocation());
             args.addConst("usePrecise", writeBarrier.usePrecise());
-            args.addConst("alwaysNull", writeBarrier.getValue().objectStamp().alwaysNull());
+            args.addConst("alwaysNull", ObjectStamp.isObjectAlwaysNull(writeBarrier.getValue()));
             template(args).instantiate(runtime, writeBarrier, DEFAULT_REPLACER, args);
         }
 
@@ -383,7 +384,7 @@
             args.add("value", writeBarrierPost.getValue());
             args.add("location", writeBarrierPost.getLocation());
             args.addConst("usePrecise", writeBarrierPost.usePrecise());
-            args.addConst("alwaysNull", writeBarrierPost.getValue().objectStamp().alwaysNull());
+            args.addConst("alwaysNull", ObjectStamp.isObjectAlwaysNull(writeBarrierPost.getValue()));
             args.addConst("trace", traceBarrier());
             template(args).instantiate(runtime, writeBarrierPost, DEFAULT_REPLACER, args);
         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Aug 08 18:17:47 2013 +0200
@@ -914,7 +914,7 @@
     }
 
     private void emitNullCheck(ValueNode receiver) {
-        if (receiver.stamp().nonNull()) {
+        if (ObjectStamp.isObjectNonNull(receiver.stamp())) {
             return;
         }
         BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
@@ -1103,8 +1103,11 @@
         }
         // 1. check if the exact type of the receiver can be determined
         ResolvedJavaType exact = klass.asExactType();
-        if (exact == null && receiver.objectStamp().isExactType()) {
-            exact = receiver.objectStamp().type();
+        if (exact == null && receiver.stamp() instanceof ObjectStamp) {
+            ObjectStamp receiverStamp = (ObjectStamp) receiver.stamp();
+            if (receiverStamp.isExactType()) {
+                exact = receiverStamp.type();
+            }
         }
         if (exact != null) {
             // either the holder class is exact, or the receiver object has an exact type
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/StampTest.java	Thu Aug 08 18:17:47 2013 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013, 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.type.*;
+
+public class StampTest extends GraalCompilerTest {
+
+    private static class A {
+
+    }
+
+    private static class B extends A {
+
+    }
+
+    private static class C extends B implements I {
+
+    }
+
+    private static class D extends A {
+
+    }
+
+    private interface I {
+
+    }
+
+    @Test
+    public void testJoin0() {
+        Stamp a = StampFactory.declared(getType(A.class));
+        Stamp b = StampFactory.declared(getType(B.class));
+        Assert.assertEquals(b, join(a, b));
+    }
+
+    @Test
+    public void testJoin1() {
+        Stamp aNonNull = StampFactory.declaredNonNull(getType(A.class));
+        Stamp b = StampFactory.declared(getType(B.class));
+        Stamp bNonNull = StampFactory.declaredNonNull(getType(B.class));
+        Assert.assertEquals(bNonNull, join(aNonNull, b));
+    }
+
+    @Test
+    public void testJoin2() {
+        Stamp aExact = StampFactory.exactNonNull(getType(A.class));
+        Stamp b = StampFactory.declared(getType(B.class));
+        Assert.assertEquals(StampFactory.illegal(), join(aExact, b));
+    }
+
+    @Test
+    public void testJoin3() {
+        Stamp d = StampFactory.declared(getType(D.class));
+        Stamp c = StampFactory.declared(getType(C.class));
+        Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join(c, d)));
+    }
+
+    @Test
+    public void testJoin4() {
+        Stamp dExactNonNull = StampFactory.exactNonNull(getType(D.class));
+        Stamp c = StampFactory.declared(getType(C.class));
+        Assert.assertEquals(StampFactory.illegal(), join(c, dExactNonNull));
+    }
+
+    @Test
+    public void testJoin5() {
+        Stamp dExact = StampFactory.exact(getType(D.class));
+        Stamp c = StampFactory.declared(getType(C.class));
+        Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join(c, dExact)));
+    }
+
+    @Test
+    public void testJoin6() {
+        Stamp dExactNonNull = StampFactory.exactNonNull(getType(D.class));
+        Stamp allwaysNull = StampFactory.alwaysNull();
+        Stamp join = join(allwaysNull, dExactNonNull);
+        Assert.assertFalse(ObjectStamp.isObjectNonNull(join));
+        Assert.assertFalse(ObjectStamp.isObjectAlwaysNull(join));
+    }
+
+    @Test
+    public void testJoinInterface0() {
+        Stamp a = StampFactory.declared(getType(A.class));
+        Stamp b = StampFactory.declared(getType(I.class));
+        Assert.assertNotSame(StampFactory.illegal(), join(a, b));
+    }
+
+    @Test
+    public void testJoinInterface1() {
+        Stamp aNonNull = StampFactory.declaredNonNull(getType(A.class));
+        Stamp i = StampFactory.declared(getType(I.class));
+        Stamp join = join(aNonNull, i);
+        Assert.assertTrue(join instanceof ObjectStamp);
+        Assert.assertTrue(((ObjectStamp) join).nonNull());
+    }
+
+    @Test
+    public void testJoinInterface2() {
+        Stamp bExact = StampFactory.exactNonNull(getType(B.class));
+        Stamp i = StampFactory.declared(getType(I.class));
+        Stamp join = join(i, bExact);
+        Assert.assertEquals(StampFactory.illegal(), join);
+    }
+
+    private static Stamp join(Stamp a, Stamp b) {
+        Stamp ab = a.join(b);
+        Stamp ba = b.join(a);
+        Assert.assertEquals(ab, ba);
+        return ab;
+    }
+
+    private ResolvedJavaType getType(Class<?> clazz) {
+        return runtime().lookupJavaType(clazz);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Thu Aug 08 18:17:47 2013 +0200
@@ -381,7 +381,7 @@
     public boolean verify() {
         for (ValueNode value : values) {
             assert assertTrue(value == null || !value.isDeleted(), "frame state must not contain deleted nodes");
-            assert assertTrue(value == null || value instanceof VirtualObjectNode || (value.kind() != Kind.Void && value.kind() != Kind.Illegal), "unexpected value: %s", value);
+            assert assertTrue(value == null || value instanceof VirtualObjectNode || (value.kind() != Kind.Void), "unexpected value: %s", value);
         }
         return super.verify();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -60,7 +60,10 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(stamp().join(object().stamp()));
+        if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) {
+            return updateStamp(((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp()));
+        }
+        return updateStamp(object().stamp().join(stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -124,11 +124,6 @@
     public boolean verify() {
         assertTrue(merge() != null, "missing merge");
         assertTrue(merge().phiPredecessorCount() == valueCount(), "mismatch between merge predecessor count and phi value count: %d != %d", merge().phiPredecessorCount(), valueCount());
-        if (type == PhiType.Value) {
-            for (ValueNode v : values()) {
-                assertTrue(v.kind() == kind(), "all phi values must have same kind");
-            }
-        }
         return super.verify();
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * A node that attaches a type profile to a proxied input node.
@@ -71,7 +72,7 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (object.objectStamp().isExactType()) {
+        if (ObjectStamp.isExactType(object)) {
             // The profile is useless - we know the type!
             return object;
         } else if (object instanceof TypeProfileProxyNode) {
@@ -92,8 +93,8 @@
                 Debug.log("Improved profile via other profile.");
                 return TypeProfileProxyNode.create(object, newProfile);
             }
-        } else if (object.objectStamp().type() != null) {
-            ResolvedJavaType type = object.objectStamp().type();
+        } else if (ObjectStamp.typeOrNull(object) != null) {
+            ResolvedJavaType type = ObjectStamp.typeOrNull(object);
             ResolvedJavaType uniqueConcrete = type.findUniqueConcreteSubtype();
             if (uniqueConcrete != null) {
                 // Profile is useless => remove.
@@ -105,7 +106,7 @@
                 return this;
             }
             lastCheckedType = type;
-            JavaTypeProfile newProfile = this.profile.restrict(type, object.objectStamp().nonNull());
+            JavaTypeProfile newProfile = this.profile.restrict(type, ObjectStamp.isObjectNonNull(object));
             if (newProfile != this.profile) {
                 Debug.log("Improved profile via static type information.");
                 if (newProfile.getTypes().length == 0) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -134,21 +134,6 @@
         return true;
     }
 
-    public final ObjectStamp objectStamp() {
-        assert verifyStamp(ObjectStamp.class);
-        return (ObjectStamp) stamp();
-    }
-
-    public final IntegerStamp integerStamp() {
-        assert verifyStamp(IntegerStamp.class);
-        return (IntegerStamp) stamp();
-    }
-
-    public final FloatStamp floatStamp() {
-        assert verifyStamp(FloatStamp.class);
-        return (FloatStamp) stamp();
-    }
-
     @Override
     public boolean verify() {
         assertTrue(kind() != null, "Should have a valid kind");
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.and(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.and(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -66,10 +66,8 @@
         if (x().isConstant() && y().isConstant() && condition instanceof IntegerEqualsNode) {
             IntegerEqualsNode equals = (IntegerEqualsNode) condition;
             if (equals.y().isConstant() && equals.y().asConstant().equals(Constant.INT_0)) {
-                if (equals.x().integerStamp().mask() == 1) {
-                    if (x().asConstant().equals(Constant.INT_0) && y().asConstant().equals(Constant.INT_1)) {
-                        return equals.x();
-                    }
+                if (x().asConstant().equals(Constant.INT_0) && y().asConstant().equals(Constant.INT_1)) {
+                    return equals.x();
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -202,22 +202,30 @@
 
     @Override
     public boolean inferStamp() {
+        Stamp stamp = value.stamp();
+        if (!(stamp instanceof IntegerStamp)) {
+            if (stamp instanceof FloatStamp) {
+                return false;
+            }
+            return updateStamp(StampFactory.illegal());
+        }
         Stamp newStamp;
+        IntegerStamp integerStamp = (IntegerStamp) stamp;
         switch (opcode) {
             case I2L:
-                newStamp = StampTool.intToLong(value().integerStamp());
+                newStamp = StampTool.intToLong(integerStamp);
                 break;
             case L2I:
-                newStamp = StampTool.longToInt(value().integerStamp());
+                newStamp = StampTool.longToInt(integerStamp);
                 break;
             case I2B:
-                newStamp = StampTool.intToByte(value().integerStamp());
+                newStamp = StampTool.intToByte(integerStamp);
                 break;
             case I2C:
-                newStamp = StampTool.intToChar(value().integerStamp());
+                newStamp = StampTool.intToChar(integerStamp);
                 break;
             case I2S:
-                newStamp = StampTool.intToShort(value().integerStamp());
+                newStamp = StampTool.intToShort(integerStamp);
                 break;
             default:
                 return false;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.add(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.add(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -58,13 +58,15 @@
         if (x() == y()) {
             return LogicConstantNode.contradiction(graph());
         } else {
-            IntegerStamp xStamp = x().integerStamp();
-            IntegerStamp yStamp = y().integerStamp();
-            if (yStamp.isPositive()) {
-                if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
-                    return LogicConstantNode.tautology(graph());
-                } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
-                    return LogicConstantNode.contradiction(graph());
+            if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
+                IntegerStamp xStamp = (IntegerStamp) x().stamp();
+                IntegerStamp yStamp = (IntegerStamp) y().stamp();
+                if (yStamp.isPositive()) {
+                    if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
+                        return LogicConstantNode.tautology(graph());
+                    } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
+                        return LogicConstantNode.contradiction(graph());
+                    }
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -38,7 +38,7 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.div(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.div(x().stamp(), y().stamp()));
     }
 
     @Override
@@ -63,9 +63,9 @@
                 return graph().unique(new NegateNode(x()));
             }
             long abs = Math.abs(c);
-            if (CodeUtil.isPowerOf2(abs)) {
+            if (CodeUtil.isPowerOf2(abs) && x().stamp() instanceof IntegerStamp) {
                 ValueNode dividend = x();
-                IntegerStamp stampX = x().integerStamp();
+                IntegerStamp stampX = (IntegerStamp) x().stamp();
                 int log2 = CodeUtil.log2(abs);
                 // no rounding if dividend is positive or if its low bits are always 0
                 if (stampX.canBeNegative() || (stampX.mask() & (abs - 1)) != 0) {
@@ -121,6 +121,6 @@
 
     @Override
     public boolean canDeoptimize() {
-        return y().integerStamp().contains(0);
+        return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -71,7 +71,7 @@
     public LogicNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return LogicConstantNode.tautology(graph());
-        } else if (x().integerStamp().alwaysDistinct(y().integerStamp())) {
+        } else if (x().stamp().alwaysDistinct(y().stamp())) {
             return LogicConstantNode.contradiction(graph());
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -73,13 +73,18 @@
     public LogicNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return LogicConstantNode.contradiction(graph());
-        } else if (x().integerStamp().upperBound() < y().integerStamp().lowerBound()) {
-            return LogicConstantNode.tautology(graph());
-        } else if (x().integerStamp().lowerBound() >= y().integerStamp().upperBound()) {
-            return LogicConstantNode.contradiction(graph());
         }
-        if (IntegerStamp.sameSign(x().integerStamp(), y().integerStamp())) {
-            return graph().unique(new IntegerBelowThanNode(x(), y()));
+        if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) x().stamp();
+            IntegerStamp yStamp = (IntegerStamp) y().stamp();
+            if (xStamp.upperBound() < yStamp.lowerBound()) {
+                return LogicConstantNode.tautology(graph());
+            } else if (xStamp.lowerBound() >= yStamp.upperBound()) {
+                return LogicConstantNode.contradiction(graph());
+            }
+            if (IntegerStamp.sameSign(xStamp, yStamp)) {
+                return graph().unique(new IntegerBelowThanNode(x(), y()));
+            }
         }
         return super.canonical(tool);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "%")
 public class IntegerRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -52,7 +53,7 @@
             long c = y().asConstant().asLong();
             if (c == 1 || c == -1) {
                 return ConstantNode.forIntegerKind(kind(), 0, graph());
-            } else if (c > 0 && CodeUtil.isPowerOf2(c) && x().integerStamp().isPositive()) {
+            } else if (c > 0 && CodeUtil.isPowerOf2(c) && x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) {
                 return graph().unique(new AndNode(kind(), x(), ConstantNode.forIntegerKind(kind(), c - 1, graph())));
             }
         }
@@ -71,6 +72,6 @@
 
     @Override
     public boolean canDeoptimize() {
-        return y().integerStamp().contains(0);
+        return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.sub(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.sub(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * This node will perform a "test" operation on its arguments. Its result is equivalent to the
@@ -64,8 +65,12 @@
         if (x().isConstant() && y().isConstant()) {
             return LogicConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph());
         }
-        if ((x().integerStamp().mask() & y().integerStamp().mask()) == 0) {
-            return LogicConstantNode.tautology(graph());
+        if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) x().stamp();
+            IntegerStamp yStamp = (IntegerStamp) y().stamp();
+            if ((xStamp.mask() & yStamp.mask()) == 0) {
+                return LogicConstantNode.tautology(graph());
+            }
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -44,7 +44,6 @@
      * @param object the instruction producing the object to check against null
      */
     public IsNullNode(ValueNode object) {
-        assert object.kind() == Kind.Object : object;
         this.object = object;
     }
 
@@ -56,7 +55,7 @@
     @Override
     public boolean verify() {
         assertTrue(object() != null, "is null input must not be null");
-        assertTrue(object().kind() == Kind.Object, "is null input must be an object");
+        assertTrue(object().stamp() instanceof ObjectStamp || object().stamp() == StampFactory.illegal(), "is null input must be an object");
         return super.verify();
     }
 
@@ -67,7 +66,7 @@
             assert constant.getKind() == Kind.Object;
             return LogicConstantNode.forBoolean(constant.isNull(), graph());
         }
-        if (object.objectStamp().nonNull()) {
+        if (ObjectStamp.isObjectNonNull(object.stamp())) {
             return LogicConstantNode.contradiction(graph());
         }
         return this;
@@ -82,9 +81,9 @@
 
     @Override
     public boolean push(PiNode parent) {
-        ObjectStamp piStamp = parent.objectStamp();
-        if (parent.object().kind() == Kind.Object) {
-            ObjectStamp piValueStamp = parent.object().objectStamp();
+        if (parent.stamp() instanceof ObjectStamp && parent.object().stamp() instanceof ObjectStamp) {
+            ObjectStamp piStamp = (ObjectStamp) parent.stamp();
+            ObjectStamp piValueStamp = (ObjectStamp) parent.object().stamp();
             if (piStamp.nonNull() == piValueStamp.nonNull() && piStamp.alwaysNull() == piValueStamp.alwaysNull()) {
                 replaceFirstInput(parent, parent.object());
                 return true;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.leftShift(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.leftShift(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "==")
 public final class ObjectEqualsNode extends CompareNode implements Virtualizable {
@@ -58,9 +59,9 @@
             return LogicConstantNode.tautology(graph());
         }
 
-        if (x().objectStamp().alwaysNull()) {
+        if (ObjectStamp.isObjectAlwaysNull(x())) {
             return graph().unique(new IsNullNode(y()));
-        } else if (y().objectStamp().alwaysNull()) {
+        } else if (ObjectStamp.isObjectAlwaysNull(y())) {
             return graph().unique(new IsNullNode(x()));
         }
         if (x().stamp().alwaysDistinct(y().stamp())) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.or(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.or(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (x().integerStamp().isPositive()) {
+        if (x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) {
             return graph().unique(new UnsignedRightShiftNode(kind(), x(), y()));
         }
         if (y().isConstant()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "|/|")
 public class UnsignedDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -72,6 +73,6 @@
 
     @Override
     public boolean canDeoptimize() {
-        return y().integerStamp().contains(0);
+        return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "|%|")
 public class UnsignedRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -71,6 +72,6 @@
 
     @Override
     public boolean canDeoptimize() {
-        return y().integerStamp().contains(0);
+        return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.unsignedRightShift(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.unsignedRightShift(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.xor(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.xor(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -72,7 +72,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         ValueNode v = tool.getReplacedValue(getValue());
-        ResolvedJavaType type = objectStamp().type();
+        ResolvedJavaType type = ObjectStamp.typeOrNull(stamp());
 
         VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind);
         assert newVirtual.getFields().length == 1;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -111,8 +111,8 @@
             }
             tool.addToWorkList(blockSuccessor(survivingEdge));
             graph().removeSplit(this, blockSuccessor(survivingEdge));
-        } else if (value() != null) {
-            IntegerStamp stamp = value().integerStamp();
+        } else if (value().stamp() instanceof IntegerStamp) {
+            IntegerStamp stamp = (IntegerStamp) value().stamp();
             if (!stamp.isUnrestricted()) {
                 int validKeys = 0;
                 for (int i = 0; i < keyCount(); i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -65,8 +65,8 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
-        if (runtime != null) {
-            ObjectStamp stamp = object.objectStamp();
+        if (runtime != null && object.stamp() instanceof ObjectStamp) {
+            ObjectStamp stamp = (ObjectStamp) object.stamp();
 
             ResolvedJavaType exactType;
             if (stamp.isExactType()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -107,15 +107,15 @@
         if (location() instanceof ConstantLocationNode) {
             long displacement = ((ConstantLocationNode) location()).getDisplacement();
             if (parent.stamp() instanceof ObjectStamp) {
-                ObjectStamp piStamp = parent.objectStamp();
+                ObjectStamp piStamp = (ObjectStamp) parent.stamp();
                 ResolvedJavaType receiverType = piStamp.type();
                 if (receiverType != null) {
                     ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement);
 
                     if (field != null) {
                         ResolvedJavaType declaringClass = field.getDeclaringClass();
-                        if (declaringClass.isAssignableFrom(receiverType) && declaringClass != receiverType) {
-                            ObjectStamp piValueStamp = parent.object().objectStamp();
+                        if (declaringClass.isAssignableFrom(receiverType) && declaringClass != receiverType && parent.object().stamp() instanceof ObjectStamp) {
+                            ObjectStamp piValueStamp = (ObjectStamp) parent.object().stamp();
                             if (piStamp.nonNull() == piValueStamp.nonNull() && piStamp.alwaysNull() == piValueStamp.alwaysNull()) {
                                 replaceFirstInput(parent, parent.object());
                                 return true;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -65,18 +65,14 @@
             long constantOffset = offset().asConstant().asLong();
 
             // Try to canonicalize to a field access.
-            if (object().stamp() instanceof ObjectStamp) {
-                // TODO (gd) remove that once UnsafeAccess only have an object base
-                ObjectStamp receiverStamp = object().objectStamp();
-                ResolvedJavaType receiverType = receiverStamp.type();
-                if (receiverType != null) {
-                    ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement() + constantOffset);
-                    // No need for checking that the receiver is non-null. The field access includes
-                    // the null check and if a field is found, the offset is so small that this is
-                    // never a valid access of an arbitrary address.
-                    if (field != null && field.getKind() == this.accessKind()) {
-                        return cloneAsFieldAccess(field);
-                    }
+            ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object());
+            if (receiverType != null) {
+                ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement() + constantOffset);
+                // No need for checking that the receiver is non-null. The field access includes
+                // the null check and if a field is found, the offset is so small that this is
+                // never a valid access of an arbitrary address.
+                if (field != null && field.getKind() == this.accessKind()) {
+                    return cloneAsFieldAccess(field);
                 }
             }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -45,18 +45,18 @@
     }
 
     public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
-        this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || object.stamp().nonNull()) : StampFactory.forKind(toType.getKind()));
+        this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind()));
     }
 
     @Override
     public boolean inferStamp() {
-        if (kind() != Kind.Object || object().kind() != Kind.Object) {
-            return false;
-        }
         if (stamp() == StampFactory.forNodeIntrinsic()) {
             return false;
         }
-        return updateStamp(stamp().join(object().stamp()));
+        if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) {
+            return updateStamp(((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp()));
+        }
+        return false;
     }
 
     @Override
@@ -65,9 +65,9 @@
             return this;
         }
 
-        if (kind() == Kind.Object) {
-            ObjectStamp my = objectStamp();
-            ObjectStamp other = object().objectStamp();
+        if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) {
+            ObjectStamp my = (ObjectStamp) stamp();
+            ObjectStamp other = (ObjectStamp) object().stamp();
 
             if (my.type() == null || other.type() == null) {
                 return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -78,11 +78,13 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (usages().isEmpty() && length.integerStamp().isPositive()) {
-            return null;
-        } else {
-            return this;
+        if (usages().isEmpty()) {
+            Stamp stamp = length.stamp();
+            if (stamp instanceof IntegerStamp && ((IntegerStamp) stamp).isPositive()) {
+                return null;
+            }
         }
+        return this;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -65,18 +65,14 @@
 
     @Override
     public boolean inferStamp() {
-        if (object().stamp().nonNull() && !stamp().nonNull()) {
-            setStamp(StampFactory.objectNonNull());
-            return true;
-        }
-        return super.inferStamp();
+        return updateStamp(object().stamp());
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        if (object().objectStamp().alwaysNull()) {
+        if (ObjectStamp.isObjectAlwaysNull(object())) {
             return object();
         }
         if (hub.isConstant() && hub.kind() == Kind.Object && hub.asConstant().asObject() instanceof Class) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -98,13 +98,16 @@
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
         InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile));
-        Stamp stamp = StampFactory.declared(type).join(object.stamp());
+        Stamp stamp = StampFactory.declared(type);
+        if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) {
+            stamp = ((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp);
+        }
         ValueNode condition;
-        if (stamp == null) {
+        if (stamp == StampFactory.illegal()) {
             // This is a check cast that will always fail
             condition = LogicConstantNode.contradiction(graph());
             stamp = StampFactory.declared(type);
-        } else if (object.stamp().nonNull()) {
+        } else if (ObjectStamp.isObjectNonNull(object)) {
             condition = typeTest;
         } else {
             if (profile != null && profile.getNullSeen() == TriState.FALSE) {
@@ -124,14 +127,17 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(stamp().join(object().stamp()));
+        if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) {
+            return updateStamp(((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp()));
+        }
+        return false;
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        ResolvedJavaType objectType = object().objectStamp().type();
+        ResolvedJavaType objectType = ObjectStamp.typeOrNull(object());
         if (objectType != null && type.isAssignableFrom(objectType)) {
             // we don't have to check for null types here because they will also pass the
             // checkcast.
@@ -150,7 +156,7 @@
             }
         }
 
-        if (object().objectStamp().alwaysNull()) {
+        if (ObjectStamp.isObjectAlwaysNull(object())) {
             return object();
         }
         if (tool.assumptions().useOptimisticAssumptions()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code InstanceOfDynamicNode} represents a type check where the type being checked is not
@@ -46,8 +47,8 @@
         this.mirror = mirror;
         this.object = object;
         assert mirror.kind() == Kind.Object : mirror.kind();
-        assert mirror.objectStamp().isExactType();
-        assert mirror.objectStamp().type().getName().equals("Ljava/lang/Class;");
+        assert mirror.stamp() instanceof ObjectStamp;
+        assert ((ObjectStamp) mirror.stamp()).type().getName().equals("Ljava/lang/Class;");
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -58,19 +58,20 @@
 
     @Override
     public LogicNode canonical(CanonicalizerTool tool) {
-        assert object() != null : this;
-
-        ObjectStamp stamp = object().objectStamp();
-        if (object().objectStamp().alwaysNull()) {
+        Stamp stamp = object().stamp();
+        if (!(stamp instanceof ObjectStamp)) {
+            return this;
+        }
+        ObjectStamp objectStamp = (ObjectStamp) stamp;
+        if (objectStamp.alwaysNull()) {
             return LogicConstantNode.contradiction(graph());
         }
 
-        ResolvedJavaType stampType = stamp.type();
-        if (stamp.isExactType() || stampType != null) {
+        ResolvedJavaType stampType = objectStamp.type();
+        if (stampType != null) {
             boolean subType = type().isAssignableFrom(stampType);
-
             if (subType) {
-                if (stamp.nonNull()) {
+                if (objectStamp.nonNull()) {
                     // the instanceOf matches, so return true
                     return LogicConstantNode.tautology(graph());
                 } else {
@@ -80,7 +81,7 @@
                     return graph().unique(new IsNullNode(object()));
                 }
             } else {
-                if (stamp.isExactType()) {
+                if (objectStamp.isExactType()) {
                     // 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.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -45,8 +45,9 @@
     }
 
     private static Stamp createStamp(ValueNode array, Kind kind) {
-        if (kind == Kind.Object && array.objectStamp().type() != null) {
-            return StampFactory.declared(array.objectStamp().type().getComponentType());
+        ResolvedJavaType type = ObjectStamp.typeOrNull(array);
+        if (kind == Kind.Object && type != null) {
+            return StampFactory.declared(type.getComponentType());
         } else {
             return StampFactory.forKind(kind);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -128,9 +128,9 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         if (!isStatic()) {
             ValueNode receiver = receiver();
-            if (receiver != null && receiver.objectStamp().isExactType()) {
+            if (receiver != null && ObjectStamp.isExactType(receiver)) {
                 if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
-                    ResolvedJavaMethod method = receiver.objectStamp().type().resolveMethod(targetMethod);
+                    ResolvedJavaMethod method = ObjectStamp.typeOrNull(receiver).resolveMethod(targetMethod);
                     if (method != null) {
                         invokeKind = InvokeKind.Special;
                         targetMethod = method;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -56,7 +56,11 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        ObjectStamp stamp = object.objectStamp();
+        if (!(object.stamp() instanceof ObjectStamp)) {
+            return this;
+        }
+
+        ObjectStamp stamp = (ObjectStamp) object.stamp();
 
         boolean needsCheck = true;
         if (stamp.isExactType()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -74,7 +74,7 @@
             int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1;
             if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) {
                 ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType();
-                if (componentType.isPrimitive() || value.objectStamp().alwaysNull() || (value.objectStamp().type() != null && componentType.isAssignableFrom(value.objectStamp().type()))) {
+                if (componentType.isPrimitive() || ObjectStamp.isObjectAlwaysNull(value) || (ObjectStamp.typeOrNull(value) != null && componentType.isAssignableFrom(ObjectStamp.typeOrNull(value)))) {
                     tool.setVirtualEntry(arrayState, index, value());
                     tool.delete();
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -97,8 +97,8 @@
             tool.addToWorkList(blockSuccessor(survivingEdge));
             graph().removeSplit(this, blockSuccessor(survivingEdge));
         }
-        if (value() instanceof LoadHubNode) {
-            ObjectStamp stamp = ((LoadHubNode) value()).object().objectStamp();
+        if (value() instanceof LoadHubNode && ((LoadHubNode) value()).object().stamp() instanceof ObjectStamp) {
+            ObjectStamp stamp = (ObjectStamp) ((LoadHubNode) value()).object().stamp();
             if (stamp.type() != null) {
                 int validKeys = 0;
                 for (int i = 0; i < keyCount(); i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Thu Aug 08 18:17:47 2013 +0200
@@ -95,6 +95,15 @@
 
     @Override
     public Stamp meet(Stamp otherStamp) {
+        if (otherStamp == this) {
+            return this;
+        }
+        if (otherStamp instanceof IllegalStamp) {
+            return otherStamp.meet(this);
+        }
+        if (!(otherStamp instanceof FloatStamp)) {
+            return StampFactory.illegal();
+        }
         FloatStamp other = (FloatStamp) otherStamp;
         assert kind() == other.kind();
         double meetUpperBound = Math.max(upperBound, other.upperBound);
@@ -111,6 +120,15 @@
 
     @Override
     public Stamp join(Stamp otherStamp) {
+        if (otherStamp == this) {
+            return this;
+        }
+        if (otherStamp instanceof IllegalStamp) {
+            return otherStamp.join(this);
+        }
+        if (!(otherStamp instanceof FloatStamp)) {
+            return StampFactory.illegal();
+        }
         FloatStamp other = (FloatStamp) otherStamp;
         assert kind() == other.kind();
         double joinUpperBound = Math.min(upperBound, other.upperBound);
@@ -120,6 +138,8 @@
             return this;
         } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) {
             return other;
+        } else if (joinLowerBound > joinUpperBound) {
+            return StampFactory.illegal();
         } else {
             return new FloatStamp(kind(), joinLowerBound, joinUpperBound, joinNonNaN);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Thu Aug 08 18:17:47 2013 +0200
@@ -58,13 +58,23 @@
 
     @Override
     public Stamp meet(Stamp other) {
-        assert ((GenericStamp) other).type == type;
+        if (other instanceof IllegalStamp) {
+            return other.join(this);
+        }
+        if (!(other instanceof GenericStamp) || ((GenericStamp) other).type != type) {
+            return StampFactory.illegal();
+        }
         return this;
     }
 
     @Override
     public Stamp join(Stamp other) {
-        assert ((GenericStamp) other).type == type;
+        if (other instanceof IllegalStamp) {
+            return other.join(this);
+        }
+        if (!(other instanceof GenericStamp) || ((GenericStamp) other).type != type) {
+            return StampFactory.illegal();
+        }
         return this;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java	Thu Aug 08 18:17:47 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, 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.type;
+
+import com.oracle.graal.api.meta.*;
+
+public final class IllegalStamp extends Stamp {
+
+    public static final IllegalStamp ILLEGAL = new IllegalStamp();
+
+    private IllegalStamp() {
+        super(Kind.Illegal);
+    }
+
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        return null;
+    }
+
+    @Override
+    public boolean alwaysDistinct(Stamp other) {
+        return true;
+    }
+
+    @Override
+    public Stamp meet(Stamp other) {
+        return other;
+    }
+
+    @Override
+    public Stamp join(Stamp other) {
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return "ILLEGAL";
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Thu Aug 08 18:17:47 2013 +0200
@@ -143,6 +143,15 @@
 
     @Override
     public Stamp meet(Stamp otherStamp) {
+        if (otherStamp == this) {
+            return this;
+        }
+        if (otherStamp instanceof IllegalStamp) {
+            return otherStamp.meet(this);
+        }
+        if (!(otherStamp instanceof IntegerStamp)) {
+            return StampFactory.illegal();
+        }
         IntegerStamp other = (IntegerStamp) otherStamp;
         assert kind() == other.kind();
         long meetUpperBound = Math.max(upperBound, other.upperBound);
@@ -159,6 +168,15 @@
 
     @Override
     public Stamp join(Stamp otherStamp) {
+        if (otherStamp == this) {
+            return this;
+        }
+        if (otherStamp instanceof IllegalStamp) {
+            return otherStamp.join(this);
+        }
+        if (!(otherStamp instanceof IntegerStamp)) {
+            return StampFactory.illegal();
+        }
         IntegerStamp other = (IntegerStamp) otherStamp;
         assert kind() == other.kind();
         long joinUpperBound = Math.min(upperBound, other.upperBound);
@@ -168,6 +186,8 @@
             return this;
         } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinMask == other.mask) {
             return other;
+        } else if (joinLowerBound > joinUpperBound) {
+            return StampFactory.illegal();
         } else {
             return new IntegerStamp(kind(), joinLowerBound, joinUpperBound, joinMask);
         }
@@ -237,4 +257,11 @@
         return s1.isPositive() && s2.isPositive() || s1.isStrictlyNegative() && s2.isStrictlyNegative();
     }
 
+    @Override
+    public Constant asConstant() {
+        if (lowerBound == upperBound) {
+            return Constant.forIntegerKind(kind(), lowerBound, null);
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Thu Aug 08 18:17:47 2013 +0200
@@ -25,6 +25,7 @@
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
 
 public class ObjectStamp extends Stamp {
 
@@ -35,29 +36,12 @@
 
     public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
         super(Kind.Object);
-        assert isValid(type, exactType, nonNull, alwaysNull);
         this.type = type;
         this.exactType = exactType;
         this.nonNull = nonNull;
         this.alwaysNull = alwaysNull;
     }
 
-    public static boolean isValid(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
-        if (exactType && type == null) {
-            return false;
-        }
-
-        if (exactType && Modifier.isAbstract(type.getModifiers()) && !type.isArray()) {
-            return false;
-        }
-
-        if (nonNull && alwaysNull) {
-            return false;
-        }
-
-        return true;
-    }
-
     @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
         if (type != null) {
@@ -66,7 +50,6 @@
         return metaAccess.lookupJavaType(Object.class);
     }
 
-    @Override
     public boolean nonNull() {
         return nonNull;
     }
@@ -92,26 +75,16 @@
     }
 
     @Override
-    public boolean alwaysDistinct(Stamp otherStamp) {
-        ObjectStamp other = (ObjectStamp) otherStamp;
-        if ((alwaysNull && other.nonNull) || (nonNull && other.alwaysNull)) {
-            return true;
-        }
-        if (other.type == null || type == null) {
-            // We have no type information for one of the values.
-            return false;
-        } else if (other.nonNull || nonNull) {
-            // One of the two values cannot be null.
-            return !other.type.isInterface() && !type.isInterface() && !type.isAssignableFrom(other.type) && !other.type.isAssignableFrom(type);
-        }
-        return false;
-    }
-
-    @Override
     public Stamp meet(Stamp otherStamp) {
         if (this == otherStamp) {
             return this;
         }
+        if (otherStamp instanceof IllegalStamp) {
+            return otherStamp.meet(this);
+        }
+        if (!(otherStamp instanceof ObjectStamp)) {
+            return StampFactory.illegal();
+        }
         ObjectStamp other = (ObjectStamp) otherStamp;
         ResolvedJavaType meetType;
         boolean meetExactType;
@@ -144,44 +117,82 @@
     }
 
     @Override
-    public ObjectStamp join(Stamp otherStamp) {
+    public Stamp join(Stamp otherStamp) {
+        return join0(otherStamp, false);
+    }
+
+    public Stamp castTo(ObjectStamp to) {
+        return join0(to, true);
+    }
+
+    public Stamp join0(Stamp otherStamp, boolean castToOther) {
         if (this == otherStamp) {
             return this;
         }
+        if (otherStamp instanceof IllegalStamp) {
+            return otherStamp.join(this);
+        }
+        if (!(otherStamp instanceof ObjectStamp)) {
+            return StampFactory.illegal();
+        }
         ObjectStamp other = (ObjectStamp) otherStamp;
         ResolvedJavaType joinType;
-        boolean joinExactType = exactType || other.exactType;
+        boolean joinAlwaysNull = alwaysNull || other.alwaysNull;
         boolean joinNonNull = nonNull || other.nonNull;
-        boolean joinAlwaysNull = alwaysNull || other.alwaysNull;
+        if (joinAlwaysNull && joinNonNull) {
+            return StampFactory.illegal();
+        }
+        boolean joinExactType = exactType || other.exactType;
         if (type == other.type) {
             joinType = type;
         } else if (type == null && other.type == null) {
             joinType = null;
+            if (joinExactType) {
+                return StampFactory.illegal();
+            }
         } else if (type == null) {
             joinType = other.type;
         } else if (other.type == null) {
             joinType = type;
         } else {
-            // both types are != null
+            // both types are != null and different
             if (type.isAssignableFrom(other.type)) {
                 joinType = other.type;
+                if (exactType) {
+                    joinAlwaysNull = true;
+                }
+            } else if (other.type.isAssignableFrom(type)) {
+                joinType = type;
+                if (other.exactType) {
+                    joinAlwaysNull = true;
+                }
             } else {
-                joinType = type;
+                if (castToOther) {
+                    joinType = other.type;
+                    joinExactType = other.exactType;
+                } else {
+                    joinType = null;
+                    if (joinExactType || (!type.isInterface() && !other.type.isInterface())) {
+                        joinAlwaysNull = true;
+                    }
+                }
             }
         }
-
+        if (joinAlwaysNull) {
+            if (joinNonNull) {
+                return StampFactory.illegal();
+            }
+            joinExactType = false;
+            joinType = null;
+        } else if (joinExactType && Modifier.isAbstract(joinType.getModifiers()) && !joinType.isArray()) {
+            return StampFactory.illegal();
+        }
         if (joinType == type && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) {
             return this;
         } else if (joinType == other.type && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) {
             return other;
         } else {
-            if (isValid(joinType, joinExactType, joinNonNull, joinAlwaysNull)) {
-                return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
-            } else {
-                // This situation can happen in case the compiler wants to join two contradicting
-                // stamps.
-                return null;
-            }
+            return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
         }
     }
 
@@ -201,6 +212,7 @@
         int result = 1;
         result = prime * result + (exactType ? 1231 : 1237);
         result = prime * result + (nonNull ? 1231 : 1237);
+        result = prime * result + (alwaysNull ? 1231 : 1237);
         result = prime * result + ((type == null) ? 0 : type.hashCode());
         return result;
     }
@@ -214,7 +226,7 @@
             return false;
         }
         ObjectStamp other = (ObjectStamp) obj;
-        if (exactType != other.exactType || nonNull != other.nonNull) {
+        if (exactType != other.exactType || nonNull != other.nonNull || alwaysNull != other.alwaysNull) {
             return false;
         }
         if (type == null) {
@@ -226,4 +238,42 @@
         }
         return true;
     }
+
+    public static boolean isObjectAlwaysNull(ValueNode node) {
+        return isObjectAlwaysNull(node.stamp());
+    }
+
+    public static boolean isObjectAlwaysNull(Stamp stamp) {
+        return (stamp instanceof ObjectStamp && ((ObjectStamp) stamp).alwaysNull());
+    }
+
+    public static boolean isObjectNonNull(ValueNode node) {
+        return isObjectNonNull(node.stamp());
+    }
+
+    public static boolean isObjectNonNull(Stamp stamp) {
+        return (stamp instanceof ObjectStamp && ((ObjectStamp) stamp).nonNull());
+    }
+
+    public static ResolvedJavaType typeOrNull(ValueNode node) {
+        return typeOrNull(node.stamp());
+    }
+
+    public static ResolvedJavaType typeOrNull(Stamp stamp) {
+        if (stamp instanceof ObjectStamp) {
+            return ((ObjectStamp) stamp).type();
+        }
+        return null;
+    }
+
+    public static boolean isExactType(ValueNode node) {
+        return isExactType(node.stamp());
+    }
+
+    public static boolean isExactType(Stamp stamp) {
+        if (stamp instanceof ObjectStamp) {
+            return ((ObjectStamp) stamp).isExactType();
+        }
+        return false;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Thu Aug 08 18:17:47 2013 +0200
@@ -46,15 +46,10 @@
      */
     public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess);
 
-    /**
-     * Determines if the stamped value is guaranteed to be non-null.
-     */
-    public boolean nonNull() {
-        return false;
+    public boolean alwaysDistinct(Stamp other) {
+        return join(other) == StampFactory.illegal();
     }
 
-    public abstract boolean alwaysDistinct(Stamp other);
-
     /**
      * Returns the union of this stamp and the given stamp. Typically used to create stamps for
      * {@link PhiNode}s.
@@ -71,4 +66,15 @@
      * @return The intersection of this stamp and the given stamp.
      */
     public abstract Stamp join(Stamp other);
+
+    /**
+     * If this stamp represents a single value, the methods returns this single value. It returns
+     * null otherwise.
+     * 
+     * @return the constant corresponding to the single value of this stamp and null if this tamp
+     *         can represent less or more than one value.
+     */
+    public Constant asConstant() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Aug 08 18:17:47 2013 +0200
@@ -113,6 +113,10 @@
         return positiveInt;
     }
 
+    public static Stamp illegal() {
+        return IllegalStamp.ILLEGAL;
+    }
+
     public static Stamp forInteger(Kind kind, long lowerBound, long upperBound, long mask) {
         return new IntegerStamp(kind, lowerBound, upperBound, mask);
     }
@@ -199,4 +203,8 @@
     public static Stamp exactNonNull(ResolvedJavaType type) {
         return new ObjectStamp(type, true, true, false);
     }
+
+    public static Stamp exact(ResolvedJavaType type) {
+        return new ObjectStamp(type, true, false, false);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Thu Aug 08 18:17:47 2013 +0200
@@ -57,6 +57,13 @@
         }
     }
 
+    public static Stamp add(Stamp stamp1, Stamp stamp2) {
+        if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
+            return add((IntegerStamp) stamp1, (IntegerStamp) stamp2);
+        }
+        return StampFactory.illegal();
+    }
+
     public static Stamp add(IntegerStamp stamp1, IntegerStamp stamp2) {
         Kind kind = stamp1.kind();
         assert kind == stamp2.kind();
@@ -73,8 +80,15 @@
         return StampFactory.forInteger(kind, lowerBound, upperBound, mask);
     }
 
-    public static Stamp sub(IntegerStamp stamp1, IntegerStamp stamp2) {
-        return add(stamp1, (IntegerStamp) StampTool.negate(stamp2));
+    public static Stamp sub(Stamp stamp1, Stamp stamp2) {
+        return add(stamp1, StampTool.negate(stamp2));
+    }
+
+    public static Stamp div(Stamp stamp1, Stamp stamp2) {
+        if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
+            return div((IntegerStamp) stamp1, (IntegerStamp) stamp2);
+        }
+        return StampFactory.illegal();
     }
 
     public static Stamp div(IntegerStamp stamp1, IntegerStamp stamp2) {
@@ -122,12 +136,26 @@
         return StampFactory.forInteger(kind, lowerBound, upperBound, mask);
     }
 
+    public static Stamp and(Stamp stamp1, Stamp stamp2) {
+        if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
+            return and((IntegerStamp) stamp1, (IntegerStamp) stamp2);
+        }
+        return StampFactory.illegal();
+    }
+
     public static Stamp and(IntegerStamp stamp1, IntegerStamp stamp2) {
         Kind kind = stamp1.kind();
         long mask = stamp1.mask() & stamp2.mask();
         return stampForMask(kind, mask);
     }
 
+    public static Stamp or(Stamp stamp1, Stamp stamp2) {
+        if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
+            return or((IntegerStamp) stamp1, (IntegerStamp) stamp2);
+        }
+        return StampFactory.illegal();
+    }
+
     public static Stamp or(IntegerStamp stamp1, IntegerStamp stamp2) {
         Kind kind = stamp1.kind();
         long mask = stamp1.mask() | stamp2.mask();
@@ -138,12 +166,26 @@
         }
     }
 
+    public static Stamp xor(Stamp stamp1, Stamp stamp2) {
+        if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
+            return xor((IntegerStamp) stamp1, (IntegerStamp) stamp2);
+        }
+        return StampFactory.illegal();
+    }
+
     public static Stamp xor(IntegerStamp stamp1, IntegerStamp stamp2) {
         Kind kind = stamp1.kind();
         long mask = stamp1.mask() | stamp2.mask();
         return stampForMask(kind, mask);
     }
 
+    public static Stamp unsignedRightShift(Stamp value, Stamp shift) {
+        if (value instanceof IntegerStamp && shift instanceof IntegerStamp) {
+            return unsignedRightShift((IntegerStamp) value, (IntegerStamp) shift);
+        }
+        return StampFactory.illegal();
+    }
+
     public static Stamp unsignedRightShift(IntegerStamp value, IntegerStamp shift) {
         Kind kind = value.kind();
         if (shift.lowerBound() == shift.upperBound()) {
@@ -167,6 +209,13 @@
         return stampForMask(kind, mask);
     }
 
+    public static Stamp leftShift(Stamp value, Stamp shift) {
+        if (value instanceof IntegerStamp && shift instanceof IntegerStamp) {
+            return leftShift((IntegerStamp) value, (IntegerStamp) shift);
+        }
+        return StampFactory.illegal();
+    }
+
     public static Stamp leftShift(IntegerStamp value, IntegerStamp shift) {
         Kind kind = value.kind();
         int shiftBits = kind == Kind.Int ? 5 : 6;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Thu Aug 08 18:17:47 2013 +0200
@@ -34,7 +34,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
@@ -295,9 +294,7 @@
 
         /**
          * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means
-         * that the stamp has changed), re-queues the node's usages . If the stamp has changed then
-         * this method also checks if the stamp now describes a constant integer value, in which
-         * case the node is replaced with a constant.
+         * that the stamp has changed), re-queues the node's usages.
          */
         private boolean tryInferStamp(Node node, StructuredGraph graph) {
             if (node.isAlive() && node instanceof ValueNode) {
@@ -305,16 +302,10 @@
                 METRIC_INFER_STAMP_CALLED.increment();
                 if (valueNode.inferStamp()) {
                     METRIC_STAMP_CHANGED.increment();
-                    if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) {
-                        ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph);
-                        Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement);
-                        valueNode.replaceAtUsages(replacement);
-                    } else {
-                        for (Node usage : valueNode.usages()) {
-                            workList.addAgain(usage);
-                        }
-                        return true;
+                    for (Node usage : valueNode.usages()) {
+                        workList.addAgain(usage);
                     }
+                    return true;
                 }
             }
             return false;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Thu Aug 08 18:17:47 2013 +0200
@@ -114,7 +114,7 @@
                         break;
                     }
                 }
-                if (type != null && type != node.objectStamp().type()) {
+                if (type != null && type != ObjectStamp.typeOrNull(node)) {
                     newKnownTypes.put(node, type);
                 }
             }
@@ -196,15 +196,15 @@
 
         public ResolvedJavaType getNodeType(ValueNode node) {
             ResolvedJavaType result = knownTypes.get(GraphUtil.unproxify(node));
-            return result == null ? node.objectStamp().type() : result;
+            return result == null ? ObjectStamp.typeOrNull(node) : result;
         }
 
         public boolean isNull(ValueNode value) {
-            return value.objectStamp().alwaysNull() || knownNull.contains(GraphUtil.unproxify(value));
+            return ObjectStamp.isObjectAlwaysNull(value) || knownNull.contains(GraphUtil.unproxify(value));
         }
 
         public boolean isNonNull(ValueNode value) {
-            return value.objectStamp().nonNull() || knownNonNull.contains(GraphUtil.unproxify(value));
+            return ObjectStamp.isObjectNonNull(value) || knownNonNull.contains(GraphUtil.unproxify(value));
         }
 
         @Override
@@ -576,7 +576,7 @@
                     ValueNode receiver = callTarget.receiver();
                     if (receiver != null && (callTarget.invokeKind() == InvokeKind.Interface || callTarget.invokeKind() == InvokeKind.Virtual)) {
                         ResolvedJavaType type = state.getNodeType(receiver);
-                        if (type != receiver.objectStamp().type()) {
+                        if (type != ObjectStamp.typeOrNull(receiver)) {
                             ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod());
                             if (method != null) {
                                 if ((method.getModifiers() & Modifier.FINAL) != 0 || (type.getModifiers() & Modifier.FINAL) != 0) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Aug 08 18:17:47 2013 +0200
@@ -1036,7 +1036,10 @@
         assert callTarget.invokeKind() == InvokeKind.Virtual || callTarget.invokeKind() == InvokeKind.Interface;
 
         ResolvedJavaType holder = targetMethod.getDeclaringClass();
-        ObjectStamp receiverStamp = callTarget.receiver().objectStamp();
+        if (!(callTarget.receiver().stamp() instanceof ObjectStamp)) {
+            return null;
+        }
+        ObjectStamp receiverStamp = (ObjectStamp) callTarget.receiver().stamp();
         if (receiverStamp.alwaysNull()) {
             // Don't inline if receiver is known to be null
             return null;
@@ -1442,8 +1445,8 @@
         assert !callTarget.isStatic() : callTarget.targetMethod();
         StructuredGraph graph = callTarget.graph();
         ValueNode firstParam = callTarget.arguments().get(0);
-        if (firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) {
-            assert !firstParam.objectStamp().alwaysNull();
+        if (firstParam.kind() == Kind.Object && !ObjectStamp.isObjectNonNull(firstParam)) {
+            assert !ObjectStamp.isObjectAlwaysNull(firstParam);
             IsNullNode condition = graph.unique(new IsNullNode(firstParam));
             Stamp stamp = firstParam.stamp().join(objectNonNull());
             GuardingPiNode nonNullReceiver = graph.add(new GuardingPiNode(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp));
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Aug 08 18:17:47 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
@@ -77,7 +78,7 @@
 
         @Override
         public GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object) {
-            if (object.objectStamp().nonNull()) {
+            if (ObjectStamp.isObjectNonNull(object)) {
                 // Short cut creation of null check guard if the object is known to be non-null.
                 return null;
             }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Thu Aug 08 18:17:47 2013 +0200
@@ -45,7 +45,7 @@
     private boolean isAssignableType(ValueNode node, MetaAccessProvider runtime) {
         if (node.stamp() instanceof ObjectStamp) {
             ResolvedJavaType valueType = runtime.lookupJavaType(klass);
-            ResolvedJavaType nodeType = node.objectStamp().type();
+            ResolvedJavaType nodeType = ObjectStamp.typeOrNull(node);
 
             if (nodeType != null && valueType.isAssignableFrom(nodeType)) {
                 return true;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Aug 08 18:17:47 2013 +0200
@@ -267,7 +267,7 @@
                             return inlineGraph;
                         }
                     });
-                    if (!methodCallTargetNode.isStatic() && methodCallTargetNode.receiver().objectStamp().alwaysNull()) {
+                    if (!methodCallTargetNode.isStatic() && ObjectStamp.isObjectAlwaysNull(methodCallTargetNode.receiver())) {
                         return invoke.next();
                     }
                     FixedNode fixedNode = (FixedNode) invoke.predecessor();
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -43,7 +43,7 @@
     @Override
     public boolean inferStamp() {
         // TODO Should probably use a specialised version which understands that it can't overflow
-        return updateStamp(StampTool.add(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.add(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java	Thu Aug 08 18:17:47 2013 +0200
@@ -43,7 +43,7 @@
     @Override
     public boolean inferStamp() {
         // TODO Should probably use a specialised version which understands that it can't overflow
-        return updateStamp(StampTool.sub(x().integerStamp(), y().integerStamp()));
+        return updateStamp(StampTool.sub(x().stamp(), y().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Aug 08 14:19:06 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Aug 08 18:17:47 2013 +0200
@@ -123,13 +123,14 @@
 
         for (AccessIndexedNode node : graph.getNodes().filter(AccessIndexedNode.class).snapshot()) {
             ValueNode array = node.array();
-            if (array.objectStamp().type() == null) {
+            ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array);
+            if (arrayType == null) {
                 // There are cases where the array does not have a known type yet. Assume it is not
                 // a word type.
                 continue;
             }
-            assert array.objectStamp().type().isArray();
-            if (isWord(array.objectStamp().type().getComponentType())) {
+            assert arrayType.isArray();
+            if (isWord(arrayType.getComponentType())) {
                 /*
                  * The elementKind of the node is a final field, and other information such as the
                  * stamp depends on elementKind. Therefore, just create a new node and replace the
@@ -374,8 +375,8 @@
         if (node.stamp() == StampFactory.forWord()) {
             return true;
         }
-        if (node.kind() == Kind.Object) {
-            return isWord(node.objectStamp().type());
+        if (node.stamp() instanceof ObjectStamp) {
+            return isWord(((ObjectStamp) node.stamp()).type());
         }
         return false;
     }
--- a/mx/projects	Thu Aug 08 14:19:06 2013 +0200
+++ b/mx/projects	Thu Aug 08 18:17:47 2013 +0200
@@ -293,6 +293,14 @@
 project@com.oracle.graal.nodes@javaCompliance=1.7
 project@com.oracle.graal.nodes@workingSets=Graal,Graph
 
+# graal.nodes.test
+project@com.oracle.graal.nodes.test@subDir=graal
+project@com.oracle.graal.nodes.test@sourceDirs=src
+project@com.oracle.graal.nodes.test@dependencies=com.oracle.graal.compiler.test
+project@com.oracle.graal.nodes.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.nodes.test@javaCompliance=1.7
+project@com.oracle.graal.nodes.test@workingSets=Graal,Graph
+
 # graal.phases
 project@com.oracle.graal.phases@subDir=graal
 project@com.oracle.graal.phases@sourceDirs=src