changeset 5443:141817e206d4

changes to the dependencies and stamp system: * dependencies can only be of type ValueNode * exactType is a boolean flag, not a separate RiResolvedType * use different Stamp subclasses for IntegerStamp, FloatStamp, ObjectStamp and GenericStamp * use different stamp for nodes that can be a target for dependencies * use different PhiNode constructors for value- and non-value-Phis * use correct stamps for ExceptionObjectNode and CurrentThread
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 25 May 2012 11:35:18 +0200
parents 2fac5abf145f
children 0368c19fc175
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/TypeFeedbackCache.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectStoreNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AnchorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BooleanNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.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/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/IsNullNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.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/ExceptionObjectNode.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/IsTypeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.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/NewObjectArrayNode.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/StoreFieldNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ScalarTypeFeedbackStore.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeCanonicalizable.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeFeedbackChanged.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeQuery.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/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/virtual/VirtualObjectFieldNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java
diffstat 84 files changed, 786 insertions(+), 470 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri May 25 11:35:18 2012 +0200
@@ -46,6 +46,7 @@
 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.virtual.*;
 import com.oracle.max.asm.*;
 import com.oracle.max.cri.ci.*;
@@ -577,7 +578,7 @@
     @Override
     public void visitNewObjectArray(NewObjectArrayNode x) {
         XirArgument length = toXirArgument(x.length());
-        XirSnippet snippet = xir.genNewArray(site(x), length, CiKind.Object, x.elementType(), x.exactType());
+        XirSnippet snippet = xir.genNewArray(site(x), length, CiKind.Object, x.elementType(), x.elementType().arrayOf());
         emitXir(snippet, x, state(), true);
     }
 
@@ -1376,7 +1377,7 @@
         }
 
         public boolean requiresNullCheck() {
-            return receiver == null || !receiver.stamp().nonNull();
+            return receiver == null || !(receiver.stamp() instanceof ObjectStamp && ((ObjectStamp) receiver.stamp()).nonNull());
         }
 
         public boolean requiresBoundsCheck() {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java	Fri May 25 11:35:18 2012 +0200
@@ -78,7 +78,7 @@
                             }
                         }
                         if (merge != null) { // found values of interest (backedge values that exist in the peel)
-                            PhiNode firstPhi = graph.add(new PhiNode(phi.kind(), merge, phi.type()));
+                            PhiNode firstPhi = graph.add(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), merge) : new PhiNode(phi.type(), merge));
                             for (EndNode end : merge.forwardEnds()) {
                                 LoopEndNode loopEnd = reverseEnds.get(end);
                                 ValueNode prim = prim(phi.valueAt(loopEnd));
@@ -93,7 +93,7 @@
                         }
                     }
                     if (first != null) { // create a new phi (we don't patch the old one since some usages of the old one may still be valid)
-                        PhiNode newPhi = graph.add(new PhiNode(phi.kind(), loopBegin, phi.type()));
+                        PhiNode newPhi = graph.add(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), loopBegin) : new PhiNode(phi.type(), loopBegin));
                         newPhi.addInput(first);
                         for (LoopEndNode end : loopBegin.orderedLoopEnds()) {
                             newPhi.addInput(phi.valueAt(end));
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java	Fri May 25 11:35:18 2012 +0200
@@ -194,7 +194,7 @@
                 ValueNode replaceWith;
                 ValueProxyNode newVpn = (ValueProxyNode) duplicates.get(vpn);
                 if (newVpn != null) {
-                    PhiNode phi = graph.add(new PhiNode(vpn.kind(), merge, vpn.type()));
+                    PhiNode phi = graph.add(vpn.type() == PhiType.Value ? new PhiNode(vpn.kind(), merge) : new PhiNode(vpn.type(), merge));
                     phi.addInput(vpn);
                     phi.addInput(newVpn);
                     if (vpn.type() == PhiType.Value) {
@@ -249,7 +249,7 @@
             ValueNode newValue = newVirtualState[i];
             assert value.kind() == newValue.kind();
             if (value != newValue) {
-                PhiNode valuePhi = graph.add(new PhiNode(value.kind(), merge, PhiType.Value));
+                PhiNode valuePhi = graph.add(new PhiNode(value.kind(), merge));
                 ValueProxyNode inputProxy = findProxy(value, earlyExit);
                 if (inputProxy != null) {
                     ValueProxyNode newInputProxy = findProxy(newValue, newEarlyExit);
@@ -291,7 +291,7 @@
                 assert v.kind() == state[i].kind();
             }
             if (reconcile) {
-                PhiNode valuePhi = graph.add(new PhiNode(v.kind(), merge, PhiType.Value));
+                PhiNode valuePhi = graph.add(new PhiNode(v.kind(), merge));
                 for (ValueNode[] state : virtualStates) {
                     valuePhi.addInput(state[i]);
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java	Fri May 25 11:35:18 2012 +0200
@@ -26,14 +26,14 @@
 
 import java.util.*;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 public class BoxingEliminationPhase extends Phase {
 
@@ -66,13 +66,14 @@
     private PhiNode getReplacementPhi(PhiNode phiNode, CiKind kind, Map<PhiNode, PhiNode> phiReplacements) {
         if (!phiReplacements.containsKey(phiNode)) {
             PhiNode result = null;
-            if (phiNode.stamp().nonNull()) {
-                RiResolvedType exactType = phiNode.stamp().exactType();
-                if (exactType != null && exactType.toJava() == kind.toBoxedJavaClass()) {
+            ObjectStamp stamp = phiNode.objectStamp();
+            if (stamp.nonNull() && stamp.isExactType()) {
+                RiResolvedType type = stamp.type();
+                if (type != null && type.toJava() == kind.toBoxedJavaClass()) {
                     StructuredGraph graph = (StructuredGraph) phiNode.graph();
-                    result = graph.add(new PhiNode(kind, phiNode.merge(), PhiType.Value));
+                    result = graph.add(new PhiNode(kind, phiNode.merge()));
                     phiReplacements.put(phiNode, result);
-                    virtualizeUsages(phiNode, result, exactType);
+                    virtualizeUsages(phiNode, result, type);
                     int i = 0;
                     for (ValueNode n : phiNode.values()) {
                         ValueNode unboxedValue = unboxedValue(n, kind, phiReplacements);
@@ -107,7 +108,8 @@
 
     private static void tryEliminate(BoxNode boxNode) {
 
-        virtualizeUsages(boxNode, boxNode.source(), boxNode.exactType());
+        assert boxNode.objectStamp().isExactType();
+        virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type());
 
         if (boxNode.usages().filter(isNotA(FrameState.class).nor(VirtualObjectFieldNode.class)).isNotEmpty()) {
             // Elimination failed, because boxing object escapes.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java	Fri May 25 11:35:18 2012 +0200
@@ -97,7 +97,7 @@
                         break;
                     }
                 }
-                if (type == null && type != node.declaredType()) {
+                if (type == null && type != node.objectStamp().type()) {
                     newKnownTypes.put(node, type);
                 }
             }
@@ -203,7 +203,7 @@
 
         public RiResolvedType getNodeType(ValueNode node) {
             RiResolvedType result = knownTypes.get(node);
-            return result == null ? node.declaredType() : result;
+            return result == null ? node.objectStamp().type() : result;
         }
 
         @Override
@@ -338,11 +338,8 @@
                 RiResolvedType type = state.getNodeType(checkCast.object());
                 if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) {
                     PiNode piNode;
-                    if (state.knownNotNull.contains(checkCast.object())) {
-                        piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, StampFactory.declaredNonNull(type)));
-                    } else {
-                        piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, StampFactory.declared(type)));
-                    }
+                    boolean nonNull = state.knownNotNull.contains(checkCast.object());
+                    piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type)));
                     checkCast.replaceAtUsages(piNode);
                     graph.removeFixed(checkCast);
                     metricCheckCastRemoved.increment();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Fri May 25 11:35:18 2012 +0200
@@ -81,13 +81,13 @@
             PhiNode[] valuePhis = new PhiNode[fieldState.length];
             for (BlockExitState other : withStates) {
                 if (virtualObjectField != other.virtualObjectField && vobjPhi == null) {
-                    vobjPhi = graph.add(new PhiNode(CiKind.Illegal, merge, PhiType.Virtual));
+                    vobjPhi = graph.add(new PhiNode(PhiType.Virtual, merge));
                     vobjPhi.addInput(virtualObjectField);
                     virtualObjectField = vobjPhi;
                 }
                 for (int i2 = 0; i2 < fieldState.length; i2++) {
                     if (fieldState[i2] != other.fieldState[i2] && valuePhis[i2] == null) {
-                        valuePhis[i2] = graph.add(new PhiNode(fieldState[i2].kind(), merge, PhiType.Value));
+                        valuePhis[i2] = graph.add(new PhiNode(fieldState[i2].kind(), merge));
                         valuePhis[i2].addInput(fieldState[i2]);
                         fieldState[i2] = valuePhis[i2];
                     }
@@ -117,11 +117,11 @@
         public void loopBegin(LoopBeginNode loopBegin) {
             assert virtualObjectField != null : "unexpected null virtualObjectField";
             PhiNode vobjPhi = null;
-            vobjPhi = graph.add(new PhiNode(CiKind.Illegal, loopBegin, PhiType.Virtual));
+            vobjPhi = graph.add(new PhiNode(PhiType.Virtual, loopBegin));
             vobjPhi.addInput(virtualObjectField);
             virtualObjectField = vobjPhi;
             for (int i2 = 0; i2 < fieldState.length; i2++) {
-                PhiNode valuePhi = graph.add(new PhiNode(fieldState[i2].kind(), loopBegin, PhiType.Value));
+                PhiNode valuePhi = graph.add(new PhiNode(fieldState[i2].kind(), loopBegin));
                 valuePhi.addInput(fieldState[i2]);
                 fieldState[i2] = valuePhi;
                 updateField(i2);
@@ -180,7 +180,8 @@
             for (int i = 0; i < escapeFields.length; i++) {
                 fields.put(escapeFields[i].representation(), i);
             }
-            final VirtualObjectNode virtual = graph.add(new VirtualObjectNode(((ValueNode) node).exactType(), escapeFields));
+            assert node.objectStamp().isExactType();
+            final VirtualObjectNode virtual = graph.add(new VirtualObjectNode(node.objectStamp().type(), escapeFields));
             if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
                 TTY.println("new virtual object: " + virtual);
             }
@@ -385,7 +386,7 @@
             double weight = analyze(op, node, exits, invokes);
             if (exits.size() != 0) {
                 if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
-                    TTY.println("%n####### escaping object: %s (%s)", node, node.exactType());
+                    TTY.println("%n####### escaping object: %s (%s)", node, node.stamp());
                     if (GraalOptions.TraceEscapeAnalysis) {
                         TTY.print("%d: new value: %s, weight %f, escapes at ", iterations, node, weight);
                         for (Node n : exits) {
@@ -402,7 +403,7 @@
             if (invokes.size() == 0) {
 
                 Debug.dump(graph, "Before escape %s", node);
-                Debug.log("!!!!!!!! non-escaping object: %s (%s)", node, node.exactType());
+                Debug.log("!!!!!!!! non-escaping object: %s (%s)", node, node.stamp());
                 removeAllocation(node, op);
                 Debug.dump(graph, "After escape", graph);
                 break;
@@ -423,7 +424,7 @@
             new DeadCodeEliminationPhase().apply(graph);
             if (node.isDeleted()) {
                 if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
-                    TTY.println("!!!!!!!! object died while performing escape analysis: %s (%s)", node, node.exactType());
+                    TTY.println("!!!!!!!! object died while performing escape analysis: %s (%s)", node, node.stamp());
                 }
                 break;
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Fri May 25 11:35:18 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.max.cri.ci.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
@@ -116,7 +115,7 @@
                 Debug.log("Add new input to %s: %s.", original, newValue);
                 assert phi.valueCount() <= phi.merge().forwardEndCount() : phi.merge();
             } else {
-                PhiNode phi = m.graph().unique(new PhiNode(CiKind.Illegal, m, PhiType.Memory));
+                PhiNode phi = m.graph().unique(new PhiNode(PhiType.Memory, m));
                 // TODO(ls) how does this work? add documentation ...
                 for (int i = 0; i < mergeOperationCount + 1; ++i) {
                     phi.addInput((ValueNode) original);
@@ -199,7 +198,7 @@
         }
 
         private void createLoopEntryPhi(Object modifiedLocation, Node other, Loop loop) {
-            PhiNode phi = other.graph().unique(new PhiNode(CiKind.Illegal, (MergeNode) loop.header.getBeginNode(), PhiType.Memory));
+            PhiNode phi = other.graph().unique(new PhiNode(PhiType.Memory, (MergeNode) loop.header.getBeginNode()));
             phi.addInput((ValueNode) other);
             map.put(modifiedLocation, phi);
             loopEntryMap.put(modifiedLocation, phi);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Fri May 25 11:35:18 2012 +0200
@@ -31,7 +31,7 @@
 
     private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, LIRLowerable {
         public PlaceholderNode() {
-            super(StampFactory.illegal());
+            super(StampFactory.forVoid());
         }
 
         @Override
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Fri May 25 11:35:18 2012 +0200
@@ -47,22 +47,22 @@
         }
 
         @Override
-        public Node getGuardAnchor() {
+        public ValueNode getGuardAnchor() {
             throw new UnsupportedOperationException();
         }
 
         @Override
-        public Node createNullCheckGuard(ValueNode object, long leafGraphId) {
+        public ValueNode createNullCheckGuard(ValueNode object, long leafGraphId) {
             return createGuard(object.graph().unique(new IsNullNode(object)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, true, leafGraphId);
         }
 
         @Override
-        public Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, long leafGraphId) {
+        public ValueNode createGuard(BooleanNode condition, RiDeoptReason deoptReason, RiDeoptAction action, long leafGraphId) {
             return createGuard(condition, deoptReason, action, false, leafGraphId);
         }
 
         @Override
-        public Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, boolean negated, long leafGraphId) {
+        public ValueNode createGuard(BooleanNode condition, RiDeoptReason deoptReason, RiDeoptAction action, boolean negated, long leafGraphId) {
             // TODO (thomaswue): Document why this must not be called on floating nodes.
             throw new UnsupportedOperationException();
         }
@@ -162,26 +162,26 @@
         }
     }
 
-    private void process(final Block b, final NodeBitMap activeGuards, NodeBitMap processed, final Node anchor) {
+    private void process(final Block b, final NodeBitMap activeGuards, NodeBitMap processed, final ValueNode anchor) {
 
         final CiLoweringTool loweringTool = new LoweringToolBase() {
 
             @Override
-            public Node getGuardAnchor() {
+            public ValueNode getGuardAnchor() {
                 return anchor;
             }
 
             @Override
-            public Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, boolean negated, long leafGraphId) {
+            public ValueNode createGuard(BooleanNode condition, RiDeoptReason deoptReason, RiDeoptAction action, boolean negated, long leafGraphId) {
                 FixedNode guardAnchor = (FixedNode) getGuardAnchor();
                 if (GraalOptions.OptEliminateGuards) {
                     for (Node usage : condition.usages()) {
                         if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage)) {
-                            return usage;
+                            return (ValueNode) usage;
                         }
                     }
                 }
-                GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, deoptReason, action, negated, leafGraphId));
+                GuardNode newGuard = guardAnchor.graph().unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, leafGraphId));
                 if (GraalOptions.OptEliminateGuards) {
                     activeGuards.grow();
                     activeGuards.mark(newGuard);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java	Fri May 25 11:35:18 2012 +0200
@@ -226,7 +226,7 @@
                             if (canonical.dependencies.length > 0) {
                                 for (Node usage : node.usages()) {
                                     if (usage instanceof ValueNode) {
-                                        for (Node dependency : canonical.dependencies) {
+                                        for (ValueNode dependency : canonical.dependencies) {
                                             // TODO(lstadler) dead dependencies should be handled differently
                                             if (dependency.isAlive()) {
                                                 ((ValueNode) usage).dependencies().add(dependency);
@@ -245,7 +245,7 @@
                         }
                     }
                     if (node.isAlive() && node instanceof TypeFeedbackProvider) {
-                        changed.node = node;
+                        changed.node = (ValueNode) node;
                         ((TypeFeedbackProvider) node).typeFeedback(cache);
                         if (DUMP) {
                             out.println("  " + cache);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/TypeFeedbackCache.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/TypeFeedbackCache.java	Fri May 25 11:35:18 2012 +0200
@@ -25,11 +25,10 @@
 import java.util.*;
 import java.util.Map.Entry;
 
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.types.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.types.*;
-import com.oracle.graal.nodes.type.*;
 
 public class TypeFeedbackCache implements TypeFeedbackTool, Cloneable {
 
@@ -181,7 +180,7 @@
                 ScalarTypeFeedbackStore scalar = ScalarTypeFeedbackStore.meet(types);
                 if (scalar != null && !scalar.isEmpty()) {
                     result.scalarTypeFeedback.put(phi, scalar);
-                    phi.setStamp(StampFactory.forKind(phi.kind(), scalar.query(), null));
+//                    phi.setStamp(StampFactory.forKind(phi.kind(), scalar.query(), null));
                 }
             } else if (phi.kind() == CiKind.Object) {
                 ObjectTypeFeedbackStore[] types = new ObjectTypeFeedbackStore[phi.valueCount()];
@@ -195,7 +194,7 @@
                 ObjectTypeFeedbackStore object = ObjectTypeFeedbackStore.meet(types);
                 if (object != null && !object.isEmpty()) {
                     result.objectTypeFeedback.put(phi, object);
-                    phi.setStamp(StampFactory.forKind(phi.kind(), null, object.query()));
+//                    phi.setStamp(StampFactory.forKind(phi.kind(), null, object.query()));
                 }
             }
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Fri May 25 11:35:18 2012 +0200
@@ -33,10 +33,9 @@
 import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.*;
+import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -281,7 +280,7 @@
 
             PhiNode returnValuePhi = null;
             if (hasReturnValue) {
-                returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge, PhiType.Value));
+                returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge));
             }
 
             MergeNode exceptionMerge = null;
@@ -296,7 +295,7 @@
 
                 FixedNode exceptionSux = exceptionObject.next();
                 graph.addBeforeFixed(exceptionSux, exceptionMerge);
-                exceptionObjectPhi = graph.unique(new PhiNode(CiKind.Object, exceptionMerge, PhiType.Value));
+                exceptionObjectPhi = graph.unique(new PhiNode(CiKind.Object, exceptionMerge));
                 exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, CiKind.Void, exceptionObjectPhi));
             }
 
@@ -575,10 +574,11 @@
             }
             return null;
         }
-        if (callTarget.receiver().exactType() != null) {
-            RiResolvedType exact = callTarget.receiver().exactType();
-            assert exact.isSubtypeOf(targetMethod.holder()) : exact + " subtype of " + targetMethod.holder() + " for " + targetMethod;
-            RiResolvedMethod resolved = exact.resolveMethodImpl(targetMethod);
+        ObjectStamp receiverStamp = callTarget.receiver().objectStamp();
+        RiResolvedType receiverType = receiverStamp.type();
+        if (receiverStamp.isExactType()) {
+            assert receiverType.isSubtypeOf(targetMethod.holder()) : receiverType + " subtype of " + targetMethod.holder() + " for " + targetMethod;
+            RiResolvedMethod resolved = receiverType.resolveMethodImpl(targetMethod);
             if (checkTargetConditions(invoke, resolved, optimisticOpts)) {
                 double weight = callback == null ? 0 : callback.inliningWeight(parent, resolved, invoke);
                 return new ExactInlineInfo(invoke, weight, level, resolved);
@@ -587,12 +587,11 @@
         }
         RiResolvedType holder = targetMethod.holder();
 
-        if (callTarget.receiver().declaredType() != null) {
-            RiResolvedType declared = callTarget.receiver().declaredType();
+        if (receiverStamp.type() != null) {
             // the invoke target might be more specific than the holder (happens after inlining: locals lose their declared type...)
             // TODO (lstadler) fix this
-            if (declared != null && declared.isSubtypeOf(holder)) {
-                holder = declared;
+            if (receiverType != null && receiverType.isSubtypeOf(holder)) {
+                holder = receiverType;
             }
         }
         // TODO (thomaswue) fix this
@@ -1066,7 +1065,7 @@
         StructuredGraph graph = (StructuredGraph) invoke.graph();
         NodeInputList<ValueNode> parameters = callTarget.arguments();
         ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0);
-        if (!callTarget.isStatic() && firstParam.kind() == CiKind.Object && !firstParam.stamp().nonNull()) {
+        if (!callTarget.isStatic() && firstParam.kind() == CiKind.Object && !firstParam.objectStamp().nonNull()) {
             graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), RiDeoptReason.ClassCastException, RiDeoptAction.InvalidateReprofile, true, invoke.leafGraphId())));
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java	Fri May 25 11:35:18 2012 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -32,8 +33,8 @@
 
     private int threadObjectOffset;
 
-    public CurrentThread(int threadObjectOffset) {
-        super(StampFactory.forKind(CiKind.Object));
+    public CurrentThread(int threadObjectOffset, RiRuntime runtime) {
+        super(StampFactory.declaredNonNull(runtime.getType(Thread.class)));
         this.threadObjectOffset = threadObjectOffset;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Fri May 25 11:35:18 2012 +0200
@@ -49,7 +49,7 @@
      * @param frameState the parameters will be taken from this FrameState
      */
     public TailcallNode(ValueNode target, FrameState frameState) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         this.target = target;
         this.frameState = frameState;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Fri May 25 11:35:18 2012 +0200
@@ -31,7 +31,7 @@
 public abstract class WriteBarrier extends FixedWithNextNode {
 
     public WriteBarrier() {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
     }
 
     protected void generateBarrier(CiValue adr, LIRGeneratorTool gen) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Fri May 25 11:35:18 2012 +0200
@@ -327,8 +327,8 @@
             CompareAndSwapNode cas = (CompareAndSwapNode) n;
             ValueNode expected = cas.expected();
             if (expected.kind() == CiKind.Object && !cas.newValue().isNullConstant()) {
-                RiResolvedType declaredType = cas.object().declaredType();
-                if (declaredType != null && !declaredType.isArrayClass() && declaredType.toJava() != Object.class) {
+                RiResolvedType type = cas.object().objectStamp().type();
+                if (type != null && !type.isArrayClass() && type.toJava() != Object.class) {
                     // Use a field write barrier since it's not an array store
                     FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(cas.object()));
                     graph.addAfterFixed(cas, writeBarrier);
@@ -341,7 +341,7 @@
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
 
-            Node boundsCheck = createBoundsCheck(loadIndexed, tool);
+            ValueNode boundsCheck = createBoundsCheck(loadIndexed, tool);
 
             CiKind elementKind = loadIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index());
@@ -350,7 +350,7 @@
             graph.replaceFixedWithFixed(loadIndexed, memoryRead);
         } else if (n instanceof StoreIndexedNode) {
             StoreIndexedNode storeIndexed = (StoreIndexedNode) n;
-            Node boundsCheck = createBoundsCheck(storeIndexed, tool);
+            ValueNode boundsCheck = createBoundsCheck(storeIndexed, tool);
 
             CiKind elementKind = storeIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index());
@@ -359,8 +359,9 @@
             ValueNode array = storeIndexed.array();
             if (elementKind == CiKind.Object && !value.isNullConstant()) {
                 // Store check!
-                if (array.exactType() != null) {
-                    RiResolvedType elementType = array.exactType().componentType();
+                RiResolvedType arrayType = array.objectStamp().type();
+                if (arrayType != null && array.objectStamp().isExactType()) {
+                    RiResolvedType elementType = arrayType.componentType();
                     if (elementType.superType() != null) {
                         ConstantNode type = ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph);
                         checkcast = graph.add(new CheckCastNode(type, elementType, value));
@@ -370,7 +371,7 @@
                         assert elementType.name().equals("Ljava/lang/Object;") : elementType.name();
                     }
                 } else {
-                    Node guard = tool.createNullCheckGuard(array, StructuredGraph.INVALID_GRAPH_ID);
+                    ValueNode guard = tool.createNullCheckGuard(array, StructuredGraph.INVALID_GRAPH_ID);
                     FloatingReadNode arrayClass = graph.unique(new FloatingReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), null, StampFactory.objectNonNull()));
                     arrayClass.dependencies().add(guard);
                     FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), null, StampFactory.objectNonNull()));
@@ -467,10 +468,10 @@
         return safeRead(array.graph(), CiKind.Int, array, config.arrayLengthOffset, StampFactory.positiveInt(), leafGraphId);
     }
 
-    private static Node createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) {
+    private static ValueNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) n.graph();
         ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array()));
-        Node guard = tool.createGuard(graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), RiDeoptReason.BoundsCheckException, RiDeoptAction.InvalidateReprofile, n.leafGraphId());
+        ValueNode guard = tool.createGuard(graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), RiDeoptReason.BoundsCheckException, RiDeoptAction.InvalidateReprofile, n.leafGraphId());
 
         graph.addBeforeFixed(n, arrayLength);
         return guard;
@@ -484,17 +485,19 @@
         if (holderName.equals("Ljava/lang/Object;")) {
             if (fullName.equals("getClass()Ljava/lang/Class;")) {
                 ValueNode obj = (ValueNode) parameters.get(0);
-                if (obj.stamp().nonNull() && obj.stamp().exactType() != null) {
+                ObjectStamp stamp = (ObjectStamp) obj.stamp();
+                if (stamp.nonNull() && stamp.isExactType()) {
                     StructuredGraph graph = new StructuredGraph();
-                    ValueNode result = ConstantNode.forObject(obj.stamp().exactType().toJava(), this, graph);
+                    ValueNode result = ConstantNode.forObject(stamp.type().toJava(), this, graph);
                     ReturnNode ret = graph.add(new ReturnNode(result));
                     graph.start().setNext(ret);
                     return graph;
                 }
                 StructuredGraph graph = new StructuredGraph();
-                LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0));
+                LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull()));
                 SafeReadNode klassOop = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID);
-                FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), null, StampFactory.objectNonNull()));
+                Stamp resultStamp = StampFactory.declared(getType(Class.class));
+                FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), null, resultStamp));
                 ReturnNode ret = graph.add(new ReturnNode(result));
                 graph.start().setNext(klassOop);
                 klassOop.setNext(ret);
@@ -503,11 +506,11 @@
         } else if (holderName.equals("Ljava/lang/Class;")) {
             if (fullName.equals("getModifiers()I")) {
                 StructuredGraph graph = new StructuredGraph();
-                LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0));
+                LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull()));
                 SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset, StampFactory.objectNonNull(), StructuredGraph.INVALID_GRAPH_ID);
                 graph.start().setNext(klassOop);
                 // TODO(thomaswue): Care about primitive classes! Crashes for primitive classes at the moment (klassOop == null)
-                FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph), null, StampFactory.forKind(CiKind.Int)));
+                FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph), null, StampFactory.intValue()));
                 ReturnNode ret = graph.add(new ReturnNode(result));
                 klassOop.setNext(ret);
                 return graph;
@@ -515,7 +518,7 @@
         } else if (holderName.equals("Ljava/lang/Thread;")) {
             if (fullName.equals("currentThread()Ljava/lang/Thread;")) {
                 StructuredGraph graph = new StructuredGraph();
-                ReturnNode ret = graph.add(new ReturnNode(graph.unique(new CurrentThread(config.threadObjectOffset))));
+                ReturnNode ret = graph.add(new ReturnNode(graph.unique(new CurrentThread(config.threadObjectOffset, this))));
                 graph.start().setNext(ret);
                 return graph;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java	Fri May 25 11:35:18 2012 +0200
@@ -39,7 +39,7 @@
     private final int displacement;
 
     public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         this.object = object;
         this.value = value;
         this.offset = offset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectStoreNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectStoreNode.java	Fri May 25 11:35:18 2012 +0200
@@ -37,7 +37,7 @@
     @Input private ValueNode value;
 
     public DirectStoreNode(ValueNode address, ValueNode value) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         this.address = address;
         this.value = value;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Fri May 25 11:35:18 2012 +0200
@@ -81,14 +81,14 @@
                 ValueNode src = methodCallTarget.arguments().get(0);
                 ValueNode dest = methodCallTarget.arguments().get(2);
                 assert src != null && dest != null;
-                RiResolvedType srcDeclaredType = src.declaredType();
-                RiResolvedType destDeclaredType = dest.declaredType();
-                if (srcDeclaredType != null
-                                && srcDeclaredType.isArrayClass()
-                                && destDeclaredType != null
-                                && destDeclaredType.isArrayClass()) {
-                    CiKind componentKind = srcDeclaredType.componentType().kind(false);
-                    if (srcDeclaredType.componentType() == destDeclaredType.componentType()) {
+                RiResolvedType srcType = src.objectStamp().type();
+                RiResolvedType destType = dest.objectStamp().type();
+                if (srcType != null
+                                && srcType.isArrayClass()
+                                && destType != null
+                                && destType.isArrayClass()) {
+                    CiKind componentKind = srcType.componentType().kind(false);
+                    if (srcType.componentType() == destType.componentType()) {
                         if (componentKind == CiKind.Int) {
                             snippetMethod = intArrayCopy;
                         } else if (componentKind == CiKind.Char) {
@@ -107,7 +107,7 @@
                             snippetMethod = objectArrayCopy;
                         }
                     } else if (componentKind == CiKind.Object
-                                    && srcDeclaredType.componentType().isSubtypeOf(destDeclaredType.componentType())) {
+                                    && srcType.componentType().isSubtypeOf(destType.componentType())) {
                         snippetMethod = objectArrayCopy;
                     }
                 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Fri May 25 11:35:18 2012 +0200
@@ -74,8 +74,7 @@
             CiKind kind = type.kind(false).stackKind();
             Stamp stamp;
             if (kind == CiKind.Object && type instanceof RiResolvedType) {
-                RiResolvedType resolvedType = (RiResolvedType) type;
-                stamp = StampFactory.declared(resolvedType);
+                stamp = StampFactory.declared((RiResolvedType) type);
             } else {
                 stamp = StampFactory.forKind(kind);
             }
@@ -170,7 +169,7 @@
                 return null;
             }
 
-            PhiNode phi = graph.unique(new PhiNode(currentValue.kind(), block, PhiType.Value));
+            PhiNode phi = graph.unique(new PhiNode(currentValue.kind(), block));
             for (int i = 0; i < block.phiPredecessorCount(); i++) {
                 phi.addInput(currentValue);
             }
@@ -257,7 +256,7 @@
         }
         assert !block.isPhiAtMerge(value) : "phi function for this block already created";
 
-        PhiNode phi = graph.unique(new PhiNode(value.kind(), block, PhiType.Value));
+        PhiNode phi = graph.unique(new PhiNode(value.kind(), block));
         phi.addInput(value);
         return phi;
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri May 25 11:35:18 2012 +0200
@@ -98,7 +98,7 @@
      */
     private static class BlockPlaceholderNode extends FixedWithNextNode implements Node.IterableNodeType {
         public BlockPlaceholderNode() {
-            super(StampFactory.illegal());
+            super(StampFactory.forVoid());
         }
     }
 
@@ -259,7 +259,7 @@
         dispatchBegin.setStateAfter(dispatchState.create(bci));
 
         if (exceptionObject == null) {
-            ExceptionObjectNode newExceptionObject = currentGraph.add(new ExceptionObjectNode());
+            ExceptionObjectNode newExceptionObject = currentGraph.add(new ExceptionObjectNode(runtime));
             dispatchState.apush(newExceptionObject);
             dispatchState.setRethrowException(true);
             newExceptionObject.setStateAfter(dispatchState.create(bci));
@@ -937,7 +937,10 @@
             return;
         }
         // 1. check if the exact type of the receiver can be determined
-        RiResolvedType exact = getExactType(klass, receiver);
+        RiResolvedType exact = klass.exactType();
+        if (exact == null && receiver.objectStamp().isExactType()) {
+            exact = receiver.objectStamp().type();
+        }
         if (exact != null) {
             // either the holder class is exact, or the receiver object has an exact type
             invokeDirect(exact.resolveMethodImpl(target), args);
@@ -982,25 +985,6 @@
         }
     }
 
-    private RiResolvedType getExactType(RiResolvedType staticType, ValueNode receiver) {
-        RiResolvedType exact = staticType.exactType();
-        if (exact == null) {
-            exact = receiver.exactType();
-            if (exact == null) {
-                if (receiver.isConstant()) {
-                    exact = runtime.getTypeOf(receiver.asConstant());
-                }
-                if (exact == null) {
-                    RiResolvedType declared = receiver.declaredType();
-                    if (declared != null) {
-                        exact = declared.exactType();
-                    }
-                }
-            }
-        }
-        return exact;
-    }
-
     private void callRegisterFinalizer() {
         // append a call to the finalizer registration
         append(currentGraph.add(new RegisterFinalizerNode(frameState.loadLocal(0))));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Fri May 25 11:35:18 2012 +0200
@@ -22,17 +22,16 @@
  */
 package com.oracle.graal.cri;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 
 public interface CiLoweringTool {
     GraalRuntime getRuntime();
-    Node getGuardAnchor();
-    Node createNullCheckGuard(ValueNode object, long leafGraphId);
-    Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, long leafGraphId);
-    Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, boolean negated, long leafGraphId);
+    ValueNode getGuardAnchor();
+    ValueNode createNullCheckGuard(ValueNode object, long leafGraphId);
+    ValueNode createGuard(BooleanNode condition, RiDeoptReason deoptReason, RiDeoptAction action, long leafGraphId);
+    ValueNode createGuard(BooleanNode condition, RiDeoptReason deoptReason, RiDeoptAction action, boolean negated, long leafGraphId);
     CiAssumptions assumptions();
 }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AnchorNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AnchorNode.java	Fri May 25 11:35:18 2012 +0200
@@ -32,7 +32,7 @@
 public final class AnchorNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable {
 
     public AnchorNode() {
-        super(StampFactory.illegal());
+        super(StampFactory.dependency());
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Fri May 25 11:35:18 2012 +0200
@@ -49,7 +49,7 @@
     }
 
     public BeginNode() {
-        super(StampFactory.illegal());
+        super(StampFactory.dependency());
     }
 
     public static BeginNode begin(FixedNode with) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BooleanNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BooleanNode.java	Fri May 25 11:35:18 2012 +0200
@@ -34,7 +34,7 @@
         super(stamp);
     }
 
-    public BooleanNode(Stamp stamp, Node... dependencies) {
+    public BooleanNode(Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Fri May 25 11:35:18 2012 +0200
@@ -32,7 +32,7 @@
     @Input protected final NodeInputList<ValueNode> arguments;
 
     public CallTargetNode(ValueNode[] arguments) {
-        super(StampFactory.illegal());
+        super(StampFactory.extension());
         this.arguments = new NodeInputList<>(this, arguments);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri May 25 11:35:18 2012 +0200
@@ -41,7 +41,7 @@
     }
 
     public DeoptimizeNode(RiDeoptAction action, RiDeoptReason reason, long leafGraphId) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         this.action = action;
         this.reason = reason;
         this.leafGraphId = leafGraphId;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java	Fri May 25 11:35:18 2012 +0200
@@ -31,7 +31,7 @@
 public class EndNode extends FixedNode implements Node.IterableNodeType, LIRLowerable {
 
     public EndNode() {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Fri May 25 11:35:18 2012 +0200
@@ -50,7 +50,7 @@
     }
 
     public FixedGuardNode(BooleanNode condition, RiDeoptReason deoptReason, RiDeoptAction action, boolean negated, long leafGraphId) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         this.action = action;
         this.negated = negated;
         this.leafGraphId = leafGraphId;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Fri May 25 11:35:18 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
 public abstract class FixedNode extends ValueNode {
@@ -33,7 +32,7 @@
         super(stamp);
     }
 
-    public FixedNode(Stamp stamp, Node... dependencies) {
+    public FixedNode(Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Fri May 25 11:35:18 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -43,7 +42,7 @@
         super(stamp);
     }
 
-    public FixedWithNextNode(Stamp stamp, Node... dependencies) {
+    public FixedWithNextNode(Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Fri May 25 11:35:18 2012 +0200
@@ -83,7 +83,7 @@
     }
 
     public GuardNode(BooleanNode condition, FixedNode anchor, RiDeoptReason reason, RiDeoptAction action, boolean negated, long leafGraphId) {
-        super(StampFactory.illegal());
+        super(StampFactory.dependency());
         this.condition = condition;
         this.anchor = anchor;
         this.reason = reason;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Fri May 25 11:35:18 2012 +0200
@@ -49,7 +49,7 @@
     }
 
     public IfNode(BooleanNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double takenProbability) {
-        super(StampFactory.illegal(), new BeginNode[] {BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor)}, new double[] {takenProbability, 1 - takenProbability});
+        super(StampFactory.forVoid(), new BeginNode[] {BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor)}, new double[] {takenProbability, 1 - takenProbability});
         this.compare = condition;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java	Fri May 25 11:35:18 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.max.cri.ci.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.type.*;
@@ -36,10 +35,6 @@
 
     private final int index;
 
-    public LocalNode(CiKind kind, int index) {
-        this(index, StampFactory.forKind(kind));
-    }
-
     public LocalNode(int index, Stamp stamp) {
         super(stamp);
         this.index = index;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Fri May 25 11:35:18 2012 +0200
@@ -33,18 +33,42 @@
  * and a variable.
  */
 public final class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType {
+
     public static enum PhiType {
-        Value, // normal value phis
-        Memory, // memory phis
-        Virtual // phis used for VirtualObjectField merges
+        Value(null), // normal value phis
+        Memory(StampFactory.dependency()), // memory phis
+        Virtual(StampFactory.virtual()); // phis used for VirtualObjectField merges
+
+        public final Stamp stamp;
+
+        PhiType(Stamp stamp) {
+            this.stamp = stamp;
+        }
     }
 
     @Input(notDataflow = true) private MergeNode merge;
     @Input private final NodeInputList<ValueNode> values = new NodeInputList<>(this);
     private final PhiType type;
 
-    public PhiNode(CiKind kind, MergeNode merge, PhiType type) {
+    /**
+     * Create a value phi ({@link PhiType#Value}) with the specified kind.
+     * @param kind the kind of the value
+     * @param merge the merge that the new phi belongs to
+     */
+    public PhiNode(CiKind kind, MergeNode merge) {
         super(StampFactory.forKind(kind));
+        this.type = PhiType.Value;
+        this.merge = merge;
+    }
+
+    /**
+     * Create a non-value phi ({@link PhiType#Memory} or {@link PhiType#Virtual}) with the specified kind.
+     * @param type the type of the new phi
+     * @param merge the merge that the new phi belongs to
+     */
+    public PhiNode(PhiType type, MergeNode merge) {
+        super(type.stamp);
+        assert type.stamp != null : merge + " " + type;
         this.type = type;
         this.merge = merge;
     }
@@ -62,7 +86,7 @@
     }
 
     public boolean inferStamp() {
-        Stamp newStamp = StampFactory.or(values());
+        Stamp newStamp = StampFactory.meet(values());
         if (stamp().equals(newStamp)) {
             return false;
         } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Fri May 25 11:35:18 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.max.cri.ci.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -37,14 +36,21 @@
 
     /**
      * Constructs a new Return instruction.
+     *
      * @param result the instruction producing the result for this return; {@code null} if this is a void return
      */
     public ReturnNode(ValueNode result) {
-        super(StampFactory.forKind(result == null ? CiKind.Void : result.kind()));
+        super(result == null ? StampFactory.forVoid() : result.stamp());
         this.result = result;
     }
 
     @Override
+    public boolean verify() {
+        assertTrue((result == null && stamp() == StampFactory.forVoid()) || (result != null && kind() == result.kind()), "invalid stamp");
+        return super.verify();
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.visitReturn(this);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Fri May 25 11:35:18 2012 +0200
@@ -32,10 +32,9 @@
 public final class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
 
     public SafepointNode() {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
     }
 
-
     @Override
     public void generate(LIRGeneratorTool gen) {
         gen.visitSafepointNode(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Fri May 25 11:35:18 2012 +0200
@@ -39,7 +39,7 @@
     }
 
     public UnwindNode(ValueNode exception) {
-        super(StampFactory.forKind(CiKind.Object));
+        super(StampFactory.forVoid());
         assert exception == null || exception.kind() == CiKind.Object;
         this.exception = exception;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri May 25 11:35:18 2012 +0200
@@ -26,8 +26,8 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.type.GenericStamp.*;
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 
 /**
  * This class represents a value within the graph, including local variables, phis, and
@@ -41,12 +41,12 @@
      */
     private Stamp stamp;
 
-    @Input(notDataflow = true) private NodeInputList<Node> dependencies;
+    @Input(notDataflow = true) private NodeInputList<ValueNode> dependencies;
 
     /**
      * This collection keeps dependencies that should be observed while scheduling (guards, etc.).
      */
-    public NodeInputList<Node> dependencies() {
+    public NodeInputList<ValueNode> dependencies() {
         return dependencies;
     }
 
@@ -56,13 +56,13 @@
         assert kind() != null && kind() == kind().stackKind() : kind() + " != " + kind().stackKind();
     }
 
-    public ValueNode(Stamp stamp, Node... dependencies) {
+    public ValueNode(Stamp stamp, ValueNode... dependencies) {
         this.stamp = stamp;
         this.dependencies = new NodeInputList<>(this, dependencies);
         assert kind() != null && kind() == kind().stackKind() : kind() + " != " + kind().stackKind();
     }
 
-    public ValueNode(Stamp stamp, List<Node> dependencies) {
+    public ValueNode(Stamp stamp, List<ValueNode> dependencies) {
         this.stamp = stamp;
         this.dependencies = new NodeInputList<>(this, dependencies);
         assert kind() != null && kind() == kind().stackKind() : kind() + " != " + kind().stackKind();
@@ -108,20 +108,24 @@
         return null;
     }
 
-    /**
-     * Computes the exact type of the result of this node, if possible.
-     * @return the exact type of the result of this node, if it is known; {@code null} otherwise
-     */
-    public final RiResolvedType exactType() {
-        return stamp.exactType();
+    public final ObjectStamp objectStamp() {
+        return (ObjectStamp) stamp;
+    }
+
+    public final IntegerStamp integerStamp() {
+        return (IntegerStamp) stamp;
     }
 
-    /**
-     * Computes the declared type of the result of this node, if possible.
-     * @return the declared type of the result of this node, if it is known; {@code null} otherwise
-     */
-    public final RiResolvedType declaredType() {
-        return stamp.declaredType();
+    public final FloatStamp floatStamp() {
+        return (FloatStamp) stamp;
+    }
+
+    @Override
+    public boolean verify() {
+        for (ValueNode v : dependencies().nonNull()) {
+            assertTrue(!(v.stamp() instanceof GenericStamp) || ((GenericStamp) v.stamp()).type() == GenericStampType.Dependency, "cannot depend on node with stamp %s", v.stamp());
+        }
+        return super.verify();
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Fri May 25 11:35:18 2012 +0200
@@ -55,7 +55,7 @@
      * @param y the instruction that produces the second input to this instruction
      */
     public CompareNode(ValueNode x, ValueNode y) {
-        super(StampFactory.illegal());
+        super(StampFactory.condition());
         assert (x == null && y == null) || x.kind() == y.kind();
         this.x = x;
         this.y = y;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Fri May 25 11:35:18 2012 +0200
@@ -34,11 +34,11 @@
         super(stamp);
     }
 
-    public FloatingNode(Stamp stamp, Node... dependencies) {
+    public FloatingNode(Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
     }
 
-    public FloatingNode(Stamp stamp, List<Node> dependencies) {
+    public FloatingNode(Stamp stamp, List<ValueNode> dependencies) {
         super(stamp, dependencies);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Fri May 25 11:35:18 2012 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.max.cri.ci.*;
 
 @NodeInfo(shortName = "|<|")
@@ -56,7 +57,18 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forBoolean(false, graph());
+        } else {
+            IntegerStamp xStamp = x().integerStamp();
+            IntegerStamp yStamp = y().integerStamp();
+            if (yStamp.lowerBound() >= 0 && yStamp.upperBound() >= 0) {
+                if (xStamp.lowerBound() >= 0 && xStamp.upperBound() < yStamp.lowerBound()) {
+                    return ConstantNode.forBoolean(true, graph());
+                } else if (xStamp.upperBound() < 0 || xStamp.lowerBound() >= yStamp.upperBound()) {
+                    return ConstantNode.forBoolean(false, graph());
+                }
+            }
         }
+
         return super.canonical(tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Fri May 25 11:35:18 2012 +0200
@@ -71,6 +71,8 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forBoolean(true, graph());
+        } else if (x().integerStamp().alwaysDistinct(y().integerStamp())) {
+            return ConstantNode.forBoolean(false, graph());
         }
         return super.canonical(tool);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Fri May 25 11:35:18 2012 +0200
@@ -72,6 +72,10 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forBoolean(false, graph());
+        } else if (x().integerStamp().upperBound() < y().integerStamp().lowerBound()) {
+            return ConstantNode.forBoolean(true, graph());
+        } else if (x().integerStamp().lowerBound() >= y().integerStamp().upperBound()) {
+            return ConstantNode.forBoolean(false, graph());
         }
         return super.canonical(tool);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Fri May 25 11:35:18 2012 +0200
@@ -44,7 +44,7 @@
      * @param object the instruction producing the object to check against null
      */
     public IsNullNode(ValueNode object) {
-        super(StampFactory.illegal());
+        super(StampFactory.condition());
         assert object.kind() == CiKind.Object : object.kind();
         this.object = object;
     }
@@ -68,7 +68,7 @@
             assert constant.kind == CiKind.Object;
             return ConstantNode.forBoolean(constant.isNull(), graph());
         }
-        if (object.stamp().nonNull()) {
+        if (object.objectStamp().nonNull()) {
             return ConstantNode.forBoolean(false, graph());
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Fri May 25 11:35:18 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.type.*;
@@ -57,13 +56,13 @@
         this.location = location;
     }
 
-    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, Node... dependencies) {
+    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
         this.object = object;
         this.location = location;
     }
 
-    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, List<Node> dependencies) {
+    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, List<ValueNode> dependencies) {
         super(stamp, dependencies);
         this.object = object;
         this.location = location;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri May 25 11:35:18 2012 +0200
@@ -36,12 +36,12 @@
 
     @Input private Node lastLocationAccess;
 
-    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, Node... dependencies) {
+    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, ValueNode... dependencies) {
         super(object, location, stamp, dependencies);
         this.lastLocationAccess = lastLocationAccess;
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, List<Node> dependencies) {
+    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, List<ValueNode> dependencies) {
         super(object, location, stamp, dependencies);
         this.lastLocationAccess = lastLocationAccess;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri May 25 11:35:18 2012 +0200
@@ -61,7 +61,7 @@
     }
 
     protected LocationNode(Object identity, CiKind kind, int displacement) {
-        super(StampFactory.illegal());
+        super(StampFactory.extension());
         assert kind != CiKind.Illegal && kind != CiKind.Void;
         this.displacement = displacement;
         this.valueKind = kind;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Fri May 25 11:35:18 2012 +0200
@@ -38,7 +38,7 @@
      * @param barriers a mask of the barrier constants defined in {@link MemoryBarriers}
      */
     public MembarNode(int barriers) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         this.barriers = barriers;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java	Fri May 25 11:35:18 2012 +0200
@@ -49,14 +49,20 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        RiResolvedType exactType = object.exactType();
+        ObjectStamp stamp = object.objectStamp();
 
-        if (exactType == null && tool.assumptions() != null && object.declaredType() != null) {
-            exactType = object.declaredType().uniqueConcreteSubtype();
+        RiResolvedType exactType;
+        if (stamp.isExactType()) {
+            exactType = stamp.type();
+        } else if (stamp.type() != null && tool.assumptions() != null) {
+            exactType = stamp.type().uniqueConcreteSubtype();
             if (exactType != null) {
-                tool.assumptions().recordConcreteSubtype(object.declaredType(), exactType);
+                tool.assumptions().recordConcreteSubtype(stamp.type(), exactType);
             }
+        } else {
+            exactType = null;
         }
+
         if (exactType != null) {
             return ConstantNode.forCiConstant(exactType.getEncoding(Representation.ObjectHub), tool.runtime(), graph());
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Fri May 25 11:35:18 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.cri.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -38,7 +37,7 @@
     @Override
     public void lower(CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
-        Node guard = tool.createNullCheckGuard(object(), leafGraphId());
+        ValueNode guard = tool.createNullCheckGuard(object(), leafGraphId());
         ReadNode read = graph.add(new ReadNode(object(), location(), stamp()));
         read.dependencies().add(guard);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Fri May 25 11:35:18 2012 +0200
@@ -23,11 +23,9 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.cri.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.max.cri.ci.*;
 
 public class SafeWriteNode extends SafeAccessNode implements StateSplit, Lowerable {
 
@@ -49,7 +47,7 @@
     }
 
     public SafeWriteNode(ValueNode object, ValueNode value, LocationNode location, long leafGraphId) {
-        super(object, location, StampFactory.forKind(CiKind.Void), leafGraphId);
+        super(object, location, StampFactory.forVoid(), leafGraphId);
         this.value = value;
     }
 
@@ -60,7 +58,7 @@
     @Override
     public void lower(CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
-        Node guard = tool.createNullCheckGuard(object(), leafGraphId());
+        ValueNode guard = tool.createNullCheckGuard(object(), leafGraphId());
         WriteNode write = graph.add(new WriteNode(object(), value(), location()));
         write.dependencies().add(guard);
         graph.replaceFixedWithFixed(this, write);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Fri May 25 11:35:18 2012 +0200
@@ -43,7 +43,7 @@
      * @param stateAfter the state after the switch
      */
     public SwitchNode(ValueNode value, BeginNode[] successors, double[] probability) {
-        super(StampFactory.illegal(), successors, probability);
+        super(StampFactory.forVoid(), successors, probability);
         this.value = value;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri May 25 11:35:18 2012 +0200
@@ -49,7 +49,7 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (object != null && object.declaredType() != null && object.declaredType().isSubtypeOf(toType)) {
+        if (object != null && object.objectStamp().type() != null && object.objectStamp().type().isSubtypeOf(toType)) {
             return object;
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri May 25 11:35:18 2012 +0200
@@ -55,7 +55,7 @@
     }
 
     public UnsafeStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, CiKind kind) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         assert kind != CiKind.Void && kind != CiKind.Illegal;
         this.object = object;
         this.displacement = displacement;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri May 25 11:35:18 2012 +0200
@@ -36,7 +36,7 @@
 public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType {
 
     public ValueAnchorNode(ValueNode... values) {
-        super(StampFactory.illegal(), values);
+        super(StampFactory.dependency(), values);
     }
 
     @Override
@@ -53,7 +53,7 @@
         if (this.predecessor() instanceof ValueAnchorNode) {
             // transfer values and remove
             ValueAnchorNode previousAnchor = (ValueAnchorNode) this.predecessor();
-            for (Node node : dependencies().nonNull()) {
+            for (ValueNode node : dependencies().nonNull()) {
                 previousAnchor.dependencies().add(node);
             }
             return null;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Fri May 25 11:35:18 2012 +0200
@@ -30,7 +30,7 @@
 public final class WriteMemoryCheckpointNode extends AbstractStateSplit implements StateSplit, LIRLowerable, MemoryCheckpoint {
 
     public WriteMemoryCheckpointNode() {
-        this(StampFactory.illegal());
+        this(StampFactory.forVoid());
     }
 
     public WriteMemoryCheckpointNode(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri May 25 11:35:18 2012 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.max.cri.ci.*;
 
 
 public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable {
@@ -51,7 +50,7 @@
     }
 
     public WriteNode(ValueNode object, ValueNode value, LocationNode location) {
-        super(object, location, StampFactory.forKind(CiKind.Void));
+        super(object, location, StampFactory.forVoid());
         this.value = value;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Fri May 25 11:35:18 2012 +0200
@@ -66,7 +66,7 @@
      * @param object the instruction producing the object
      */
     public AccessMonitorNode(ValueNode object) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         this.object = object;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri May 25 11:35:18 2012 +0200
@@ -75,10 +75,7 @@
         assert object() != null : this;
 
         if (targetClass != null) {
-            RiResolvedType objectType = object().exactType();
-            if (objectType == null) {
-                objectType = object().declaredType();
-            }
+            RiResolvedType objectType = object().objectStamp().type();
             if (objectType != null && objectType.isSubtypeOf(targetClass)) {
                 // we don't have to check for null types here because they will also pass the checkcast.
                 return object();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri May 25 11:35:18 2012 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 /**
  * The {@code ExceptionObject} instruction represents the incoming exception object to an exception handler.
@@ -36,8 +36,8 @@
     /**
      * Constructs a new ExceptionObject instruction.
      */
-    public ExceptionObjectNode() {
-        super(StampFactory.forKind(CiKind.Object));
+    public ExceptionObjectNode(RiRuntime runtime) {
+        super(StampFactory.declared(runtime.getType(Throwable.class)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Fri May 25 11:35:18 2012 +0200
@@ -52,7 +52,7 @@
     }
 
     public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiTypeProfile profile) {
-        super(StampFactory.illegal());
+        super(StampFactory.condition());
         this.targetClassInstruction = targetClassInstruction;
         this.targetClass = targetClass;
         this.object = object;
@@ -68,42 +68,40 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        RiResolvedType exact = object().exactType();
-        if (exact != null) {
-            boolean subType = exact.isSubtypeOf(targetClass());
+        ObjectStamp stamp = object().objectStamp();
+        RiResolvedType type = stamp.type();
+
+        if (stamp.isExactType()) {
+            boolean subType = type.isSubtypeOf(targetClass());
 
             if (subType) {
-                if (object().stamp().nonNull()) {
-                    // the instanceOf matches, so return true (or false, for the negated case)
+                if (stamp.nonNull()) {
+                    // the instanceOf matches, so return true
                     return ConstantNode.forBoolean(true, graph());
                 } else {
-                    // the instanceof matches if the object is non-null, so return true (or false, for the negated case) depending on the null-ness.
+                    // the instanceof matches if the object is non-null, so return true depending on the null-ness.
                     negateUsages();
                     return graph().unique(new IsNullNode(object()));
                 }
             } else {
                 // 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.
-                // so return false (or true, for the negated case)
                 return ConstantNode.forBoolean(false, graph());
             }
-        } else {
-            RiResolvedType declared = object().declaredType();
-            if (declared != null) {
-                boolean subType = declared.isSubtypeOf(targetClass());
+        } else if (type != null) {
+            boolean subType = type.isSubtypeOf(targetClass());
 
-                if (subType) {
-                    if (object().stamp().nonNull()) {
-                        // the instanceOf matches, so return true (or false, for the negated case)
-                        return ConstantNode.forBoolean(true, graph());
-                    } else {
-                        // the instanceof matches if the object is non-null, so return true (or false, for the negated case) depending on the null-ness.
-                        negateUsages();
-                        return graph().unique(new IsNullNode(object()));
-                    }
+            if (subType) {
+                if (stamp.nonNull()) {
+                    // the instanceOf matches, so return true
+                    return ConstantNode.forBoolean(true, graph());
                 } else {
-                    // since the subtype comparison was only performed on a declared type we don't really know if it might be true at run time...
+                    // the instanceof matches if the object is non-null, so return true depending on the null-ness.
+                    negateUsages();
+                    return graph().unique(new IsNullNode(object()));
                 }
+            } else {
+                // since the subtype comparison was only performed on a declared type we don't really know if it might be true at run time...
             }
         }
 
@@ -113,7 +111,7 @@
             if (constant.isNull()) {
                 return ConstantNode.forBoolean(false, graph());
             } else {
-                assert false : "non-null constants are always expected to provide an exactType";
+                assert false : "non-null constants are always expected to provide an exact type";
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/IsTypeNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/IsTypeNode.java	Fri May 25 11:35:18 2012 +0200
@@ -46,7 +46,7 @@
      * @param type the type for this check
      */
     public IsTypeNode(ValueNode objectClass, RiResolvedType type) {
-        super(StampFactory.illegal());
+        super(StampFactory.condition());
         assert objectClass == null || objectClass.kind() == CiKind.Object;
         this.type = type;
         this.objectClass = objectClass;
@@ -70,11 +70,12 @@
             return ConstantNode.forBoolean(constant.equivalent(typeHub), graph());
         }
         // TODO(ls) since a ReadHubNode with an exactType should canonicalize itself to a constant this should actually never happen, maybe turn into an assertion?
-        RiResolvedType exactType = objectClass() instanceof ReadHubNode ? ((ReadHubNode) objectClass()).object().exactType() : null;
-        if (exactType != null) {
-            return ConstantNode.forBoolean(exactType == type(), graph());
+        if (objectClass() instanceof ReadHubNode) {
+            ObjectStamp stamp = ((ReadHubNode) objectClass()).object().objectStamp();
+            if (stamp.isExactType()) {
+                return ConstantNode.forBoolean(stamp.type() == type(), graph());
+            }
         }
-        // constants return the correct exactType, so they are handled by the code above
         return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Fri May 25 11:35:18 2012 +0200
@@ -47,8 +47,7 @@
     private static Stamp createStamp(RiResolvedField field) {
         CiKind kind = field.kind(false);
         if (kind == CiKind.Object && field.type() instanceof RiResolvedType) {
-            RiResolvedType resolvedType = (RiResolvedType) field.type();
-            return StampFactory.declared(resolvedType);
+            return StampFactory.declared((RiResolvedType) field.type());
         } else {
             return StampFactory.forKind(kind);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Fri May 25 11:35:18 2012 +0200
@@ -49,8 +49,8 @@
     }
 
     private static Stamp createStamp(ValueNode array, CiKind kind) {
-        if (kind == CiKind.Object && array.declaredType() != null) {
-            return StampFactory.declared(array.declaredType().componentType());
+        if (kind == CiKind.Object && array.objectStamp().type() != null) {
+            return StampFactory.declared(array.objectStamp().type().componentType());
         } else {
             return StampFactory.forKind(kind);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Fri May 25 11:35:18 2012 +0200
@@ -125,9 +125,9 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         if (!isStatic()) {
             ValueNode receiver = receiver();
-            if (receiver != null && receiver.exactType() != null) {
+            if (receiver != null && receiver.objectStamp().isExactType()) {
                 if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
-                    RiResolvedMethod method = receiver.exactType().resolveMethodImpl(targetMethod);
+                    RiResolvedMethod method = receiver.objectStamp().type().resolveMethodImpl(targetMethod);
                     if (method != null) {
                         invokeKind = InvokeKind.Special;
                         targetMethod = method;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java	Fri May 25 11:35:18 2012 +0200
@@ -39,7 +39,6 @@
      * Constructs a new NewObjectArrayNode.
      * @param elementClass the class of elements in this array
      * @param length the node producing the length of the array
-     * @param graph
      */
     public NewObjectArrayNode(RiResolvedType elementClass, ValueNode length) {
         super(StampFactory.exactNonNull(elementClass.arrayOf()), length);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri May 25 11:35:18 2012 +0200
@@ -22,11 +22,10 @@
  */
 package com.oracle.graal.nodes.java;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ci.*;
 
 /**
  * This node is used to perform the finalizer registration at the end of the java.lang.Object constructor.
@@ -40,7 +39,7 @@
     }
 
     public RegisterFinalizerNode(ValueNode object) {
-        super(StampFactory.illegal());
+        super(StampFactory.forVoid());
         this.object = object;
     }
 
@@ -51,22 +50,15 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        RiResolvedType declaredType = object.declaredType();
-        RiResolvedType exactType = object.exactType();
-        if (exactType == null && declaredType != null) {
-            exactType = declaredType.exactType();
-        }
+        ObjectStamp stamp = object.objectStamp();
 
         boolean needsCheck = true;
-        if (exactType != null) {
-            // we have an exact type
-            needsCheck = exactType.hasFinalizer();
-        } else {
+        if (stamp.isExactType()) {
+            needsCheck = stamp.type().hasFinalizer();
+        } else if (stamp.type() != null && !stamp.type().hasFinalizableSubclass()) {
             // if either the declared type of receiver or the holder can be assumed to have no finalizers
-            if (declaredType != null && !declaredType.hasFinalizableSubclass()) {
-                if (tool.assumptions() != null && tool.assumptions().recordNoFinalizableSubclassAssumption(declaredType)) {
-                    needsCheck = false;
-                }
+            if (tool.assumptions() != null && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) {
+                needsCheck = false;
             }
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Fri May 25 11:35:18 2012 +0200
@@ -59,7 +59,7 @@
      * @param value the node representing the value to store to the field
      */
     public StoreFieldNode(ValueNode object, RiResolvedField field, ValueNode value, long leafGraphId) {
-        super(StampFactory.illegal(), object, field, leafGraphId);
+        super(StampFactory.forVoid(), object, field, leafGraphId);
         this.value = value;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Fri May 25 11:35:18 2012 +0200
@@ -62,7 +62,7 @@
      * @param value the value to store into the array
      */
     public StoreIndexedNode(ValueNode array, ValueNode index, CiKind elementKind, ValueNode value, long leafGraphId) {
-        super(StampFactory.illegal(), array, index, elementKind, leafGraphId);
+        super(StampFactory.forVoid(), array, index, elementKind, leafGraphId);
         this.value = value;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java	Fri May 25 11:35:18 2012 +0200
@@ -112,7 +112,7 @@
             ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(false, node.graph()));
         } else if (usage instanceof IsTypeNode) {
             IsTypeNode x = (IsTypeNode) usage;
-            assert x.type() == ((ValueNode) node).exactType();
+            assert x.type() == ((ValueNode) node).objectStamp().type();
             ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(true, node.graph()));
         } else if (usage instanceof AccessMonitorNode) {
             ((AccessMonitorNode) usage).eliminate();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java	Fri May 25 11:35:18 2012 +0200
@@ -138,7 +138,7 @@
         }
 
         @Override
-        public Node dependency() {
+        public ValueNode dependency() {
             return store.dependency;
         }
     }
@@ -225,7 +225,7 @@
 
     private final TypeFeedbackChanged changed;
 
-    private Node dependency;
+    private ValueNode dependency;
 
     private void updateDependency() {
         dependency = changed.node;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ScalarTypeFeedbackStore.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ScalarTypeFeedbackStore.java	Fri May 25 11:35:18 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.max.cri.ci.*;
@@ -89,7 +88,7 @@
         }
 
         @Override
-        public Node dependency() {
+        public ValueNode dependency() {
             return store.dependency;
         }
     }
@@ -121,7 +120,7 @@
     private final CiKind kind;
     private final ConstantBound constantBounds;
     private final TypeFeedbackChanged changed;
-    private Node dependency;
+    private ValueNode dependency;
     private HashMap<ValueNode, Condition> valueBounds;
 
     private void updateDependency() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeCanonicalizable.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeCanonicalizable.java	Fri May 25 11:35:18 2012 +0200
@@ -29,11 +29,11 @@
 
 public interface TypeCanonicalizable {
 
-    Node[] EMPTY_ARRAY = new Node[0];
+    ValueNode[] EMPTY_ARRAY = new ValueNode[0];
 
     public static class Result {
         public final ValueNode replacement;
-        public final Node[] dependencies;
+        public final ValueNode[] dependencies;
 
         public Result(ValueNode replacement) {
             this.replacement = replacement;
@@ -44,7 +44,7 @@
             assert query != null;
             this.replacement = replacement;
             if (query.dependency() != null) {
-                this.dependencies = new Node[] {query.dependency()};
+                this.dependencies = new ValueNode[] {query.dependency()};
             } else {
                 this.dependencies = EMPTY_ARRAY;
             }
@@ -58,7 +58,7 @@
                     deps.add(query.dependency());
                 }
             }
-            this.dependencies = deps.toArray(new Node[deps.size()]);
+            this.dependencies = deps.toArray(new ValueNode[deps.size()]);
         }
 
         @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeFeedbackChanged.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeFeedbackChanged.java	Fri May 25 11:35:18 2012 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes.spi.types;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
 
 public class TypeFeedbackChanged {
 
-    public Node node;
+    public ValueNode node;
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeQuery.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/TypeQuery.java	Fri May 25 11:35:18 2012 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes.spi.types;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
 
 public interface TypeQuery {
 
-    Node dependency();
+    ValueNode dependency();
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Fri May 25 11:35:18 2012 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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.max.cri.ci.*;
+
+
+public class FloatStamp extends Stamp {
+
+    protected FloatStamp(CiKind kind) {
+        super(kind);
+        assert kind == CiKind.Float || kind == CiKind.Double;
+    }
+
+    @Override
+    public String toString() {
+        return "" + kind().typeChar;
+    }
+
+    @Override
+    public boolean alwaysDistinct(Stamp other) {
+        return false;
+    }
+
+    @Override
+    public Stamp meet(Stamp other) {
+        assert kind() == other.kind();
+        return this;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Fri May 25 11:35:18 2012 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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.max.cri.ci.*;
+
+public final class GenericStamp extends Stamp {
+
+    public enum GenericStampType {
+        Dependency, Extension, Virtual, Condition, Void
+    }
+
+    private final GenericStampType type;
+
+    protected GenericStamp(GenericStampType type) {
+        super(CiKind.Void);
+        this.type = type;
+    }
+
+    public GenericStampType type() {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        return type.toString();
+    }
+
+    @Override
+    public boolean alwaysDistinct(Stamp other) {
+        return false;
+    }
+
+    @Override
+    public Stamp meet(Stamp other) {
+        assert ((GenericStamp) other).type == type;
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        return 31 + ((type == null) ? 0 : type.hashCode());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        if (type != ((GenericStamp) obj).type) {
+            return false;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Fri May 25 11:35:18 2012 +0200
@@ -0,0 +1,109 @@
+/*
+ * 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.max.cri.ci.*;
+
+
+public class IntegerStamp extends Stamp {
+
+    private final long lowerBound;
+    private final long upperBound;
+
+    public IntegerStamp(CiKind kind) {
+        this(kind, kind.minValue(), kind.maxValue());
+    }
+
+    public IntegerStamp(CiKind kind, long lowerBound, long upperBound) {
+        super(kind);
+        assert lowerBound <= upperBound;
+        this.lowerBound = lowerBound;
+        this.upperBound = upperBound;
+    }
+
+    public long lowerBound() {
+        return lowerBound;
+    }
+
+    public long upperBound() {
+        return upperBound;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append(kind().typeChar);
+        if (lowerBound == upperBound) {
+            str.append(" [").append(lowerBound).append(']');
+        } else if (lowerBound != kind().minValue() || upperBound != kind().maxValue()) {
+            str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
+        }
+        return str.toString();
+    }
+
+    @Override
+    public boolean alwaysDistinct(Stamp otherStamp) {
+        IntegerStamp other = (IntegerStamp) otherStamp;
+        return lowerBound > other.upperBound || upperBound < other.lowerBound;
+    }
+
+    @Override
+    public Stamp meet(Stamp otherStamp) {
+        IntegerStamp other = (IntegerStamp) otherStamp;
+        assert kind() == other.kind();
+        long meetUpperBound = Math.max(upperBound, other.upperBound);
+        long meetLowerBound = Math.min(lowerBound, other.lowerBound);
+        if (meetLowerBound == lowerBound && meetUpperBound == upperBound) {
+            return this;
+        } else {
+            return new IntegerStamp(kind(), meetLowerBound, meetUpperBound);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32));
+        result = prime * result + (int) (upperBound ^ (upperBound >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        IntegerStamp other = (IntegerStamp) obj;
+        if (lowerBound != other.lowerBound || upperBound != other.upperBound) {
+            return false;
+        }
+        return true;
+    }
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Fri May 25 11:35:18 2012 +0200
@@ -0,0 +1,142 @@
+/*
+ * 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.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+
+
+public class ObjectStamp extends Stamp {
+
+    private final RiResolvedType type;
+    private final boolean exactType;
+    private final boolean nonNull;
+
+    public ObjectStamp(RiResolvedType type, boolean exactType, boolean nonNull) {
+        super(CiKind.Object);
+        assert !exactType || type != null;
+        this.type = type;
+        this.exactType = exactType;
+        this.nonNull = nonNull;
+    }
+
+    @Override
+    public boolean nonNull() {
+        return nonNull;
+    }
+
+    public RiResolvedType type() {
+        return type;
+    }
+
+    public boolean isExactType() {
+        return exactType;
+    }
+
+    @Override
+    public RiResolvedType exactType() {
+        return exactType ? type : null;
+    }
+
+    @Override
+    public RiResolvedType declaredType() {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append(kind().typeChar);
+        str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.name());
+        return str.toString();
+    }
+
+    @Override
+    public boolean alwaysDistinct(Stamp otherStamp) {
+        ObjectStamp other = (ObjectStamp) otherStamp;
+        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() && !other.type.isSubtypeOf(type) && !type.isSubtypeOf(other.type);
+        }
+        return false;
+    }
+
+    @Override
+    public Stamp meet(Stamp otherStamp) {
+        ObjectStamp other = (ObjectStamp) otherStamp;
+        RiResolvedType orType = meetTypes(type(), other.type());
+        boolean meetExactType = orType == type && orType == other.type && exactType && other.exactType;
+        boolean meetNonNull = nonNull && other.nonNull;
+
+        if (orType == type && meetExactType == exactType && meetNonNull == nonNull) {
+            return this;
+        } else {
+            return new ObjectStamp(orType, meetExactType, meetNonNull);
+        }
+    }
+
+    private static RiResolvedType meetTypes(RiResolvedType a, RiResolvedType b) {
+        if (a == b) {
+            return a;
+        } else if (a == null || b == null) {
+            return null;
+        } else {
+            return a.leastCommonAncestor(b);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (exactType ? 1231 : 1237);
+        result = prime * result + (nonNull ? 1231 : 1237);
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        ObjectStamp other = (ObjectStamp) obj;
+        if (exactType != other.exactType || nonNull != other.nonNull) {
+            return false;
+        }
+        if (type == null) {
+            if (other.type != null) {
+                return false;
+            }
+        } else if (!type.equals(other.type)) {
+            return false;
+        }
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Fri May 25 11:35:18 2012 +0200
@@ -22,18 +22,44 @@
  */
 package com.oracle.graal.nodes.type;
 
+import com.oracle.graal.nodes.spi.types.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.graal.nodes.spi.types.*;
 
 
-public interface Stamp {
-    boolean nonNull();
-    RiResolvedType declaredType();
-    RiResolvedType exactType();
-    CiKind kind();
-    boolean alwaysDistinct(Stamp other);
+public abstract class Stamp {
+
+    private final CiKind kind;
+
+    protected Stamp(CiKind kind) {
+        this.kind = kind;
+    }
+
+    public CiKind kind() {
+        return kind;
+    }
+
+    public ScalarTypeQuery scalarType() {
+        return null;
+    }
 
-    ScalarTypeQuery scalarType();
-    ObjectTypeQuery objectType();
+    public ObjectTypeQuery objectType() {
+        return null;
+    }
+
+    public boolean nonNull() {
+        return false;
+    }
+
+    public RiResolvedType exactType() {
+        return null;
+    }
+
+    public RiResolvedType declaredType() {
+        return null;
+    }
+
+    public abstract boolean alwaysDistinct(Stamp other);
+
+    public abstract Stamp meet(Stamp other);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Fri May 25 11:35:18 2012 +0200
@@ -24,179 +24,85 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.type.GenericStamp.GenericStampType;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.types.*;
 
 
 public class StampFactory {
 
-    private static class BasicValueStamp implements Stamp {
-
-        private final CiKind kind;
-        private final boolean nonNull;
-        private RiResolvedType declaredType;
-        private RiResolvedType exactType;
-        private final ScalarTypeQuery scalarType;
-        private final ObjectTypeQuery objectType;
-
-        public BasicValueStamp(CiKind kind) {
-            this(kind, false, null, null);
-        }
-
-        public BasicValueStamp(CiKind kind, boolean nonNull, RiResolvedType declaredType, RiResolvedType exactType) {
-            this(kind, nonNull, declaredType, exactType, null, null);
-        }
-
-        public BasicValueStamp(CiKind kind, boolean nonNull, RiResolvedType declaredType, RiResolvedType exactType, ScalarTypeQuery scalarType, ObjectTypeQuery objectType) {
-            this.kind = kind;
-            this.nonNull = nonNull;
-            this.declaredType = declaredType;
-            this.exactType = exactType;
-            this.scalarType = scalarType;
-            this.objectType = objectType;
-        }
-
-        @Override
-        public CiKind kind() {
-            return kind;
-        }
-
-        @Override
-        public boolean nonNull() {
-            return nonNull;
-        }
-
-        @Override
-        public RiResolvedType declaredType() {
-            return declaredType;
-        }
-
-        @Override
-        public RiResolvedType exactType() {
-            return exactType;
-        }
+    private static final Stamp[] stampCache = new Stamp[CiKind.values().length];
+    private static final Stamp objectStamp = new ObjectStamp(null, false, false);
+    private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true);
+    private static final Stamp dependencyStamp = new GenericStamp(GenericStampType.Dependency);
+    private static final Stamp extensionStamp = new GenericStamp(GenericStampType.Extension);
+    private static final Stamp virtualStamp = new GenericStamp(GenericStampType.Virtual);
+    private static final Stamp conditionStamp = new GenericStamp(GenericStampType.Condition);
+    private static final Stamp voidStamp = new GenericStamp(GenericStampType.Void);
 
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == this) {
-                return true;
-            }
-            if (obj instanceof Stamp) {
-                Stamp other = (Stamp) obj;
-                return kind == other.kind() && nonNull() == other.nonNull() && declaredType() == other.declaredType() && exactType() == other.exactType();
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return kind.hashCode();
-        }
+    private static final Stamp positiveInt = forInt(0, Integer.MAX_VALUE);
 
-        @Override
-        public String toString() {
-            StringBuilder str = new StringBuilder();
-            str.append(kind().typeChar);
-            if (nonNull || declaredType != null || exactType != null) {
-                str.append(nonNull ? "!" : "").append(' ').append(declaredType == null ? "-" : declaredType.name()).append(' ').append(exactType == null ? "-" : exactType.name());
-            }
-            if (scalarType != null) {
-                str.append(' ').append(scalarType);
-            }
-            if (objectType != null) {
-                str.append(' ').append(objectType);
-            }
-            return str.toString();
-        }
-
-        @Override
-        public boolean alwaysDistinct(Stamp other) {
-            if (other.kind() != kind()) {
-                return true;
-            } else if (kind() != CiKind.Object) {
-                return false;
-            } else if (other.declaredType() == null || declaredType() == 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.declaredType().isInterface() && !declaredType().isInterface() && !other.declaredType().isSubtypeOf(declaredType()) && !declaredType().isSubtypeOf(other.declaredType());
-            } else {
-                // Both values may be null.
-                return false;
-            }
-        }
-
-        @Override
-        public ScalarTypeQuery scalarType() {
-            return scalarType;
-        }
-
-        @Override
-        public ObjectTypeQuery objectType() {
-            return objectType;
-        }
+    private static void setCache(CiKind kind, Stamp stamp) {
+        stampCache[kind.ordinal()] = stamp;
     }
 
-    private static final Stamp[] stampCache = new Stamp[CiKind.values().length];
     static {
-        for (CiKind k : CiKind.values()) {
-            stampCache[k.ordinal()] = new BasicValueStamp(k);
-        }
+        setCache(CiKind.Boolean, new IntegerStamp(CiKind.Boolean));
+        setCache(CiKind.Byte, new IntegerStamp(CiKind.Byte));
+        setCache(CiKind.Short, new IntegerStamp(CiKind.Short));
+        setCache(CiKind.Char, new IntegerStamp(CiKind.Char));
+        setCache(CiKind.Int, new IntegerStamp(CiKind.Int));
+        setCache(CiKind.Long, new IntegerStamp(CiKind.Long));
+
+        setCache(CiKind.Float, new FloatStamp(CiKind.Float));
+        setCache(CiKind.Double, new FloatStamp(CiKind.Double));
+
+        setCache(CiKind.Jsr, new IntegerStamp(CiKind.Jsr));
+
+        setCache(CiKind.Object, objectStamp);
+        setCache(CiKind.Void, voidStamp);
     }
 
-    public static Stamp illegal() {
-        return forKind(CiKind.Illegal);
+    public static Stamp forKind(CiKind kind) {
+        assert stampCache[kind.stackKind().ordinal()] != null : "unexpected forKind(" + kind + ")";
+        return stampCache[kind.stackKind().ordinal()];
+    }
+
+    public static Stamp forVoid() {
+        return voidStamp;
     }
 
     public static Stamp intValue() {
         return forKind(CiKind.Int);
     }
 
-    public static Stamp forKind(CiKind kind) {
-        return stampCache[kind.stackKind().ordinal()];
+    public static Stamp dependency() {
+        return dependencyStamp;
+    }
+
+    public static Stamp extension() {
+        return extensionStamp;
     }
 
-    public static Stamp forKind(CiKind kind, ScalarTypeQuery scalarTypeFeedback, ObjectTypeQuery objectTypeFeedback) {
-        if (scalarTypeFeedback == null && objectTypeFeedback == null) {
-            return forKind(kind);
-        } else {
-            return new BasicValueStamp(kind, false, null, null, scalarTypeFeedback, objectTypeFeedback);
-        }
+    public static Stamp virtual() {
+        return virtualStamp;
     }
 
-    public static final Stamp positiveInt = forInt(0, Integer.MAX_VALUE);
+    public static Stamp condition() {
+        return conditionStamp;
+    }
 
     public static Stamp positiveInt() {
         return positiveInt;
     }
 
     public static Stamp forInt(int lowerBound, int upperBound) {
-        ScalarTypeFeedbackStore scalarType = new ScalarTypeFeedbackStore(CiKind.Int, new TypeFeedbackChanged());
-        scalarType.constantBound(Condition.GE, CiConstant.forInt(lowerBound));
-        scalarType.constantBound(Condition.LE, CiConstant.forInt(upperBound));
-
-        return new BasicValueStamp(CiKind.Int, false, null, null, scalarType.query(), null);
+        return new IntegerStamp(CiKind.Int, lowerBound, upperBound);
     }
 
     public static Stamp forLong(long lowerBound, long upperBound) {
-        ScalarTypeFeedbackStore scalarType = new ScalarTypeFeedbackStore(CiKind.Long, new TypeFeedbackChanged());
-        scalarType.constantBound(Condition.GE, CiConstant.forLong(lowerBound));
-        scalarType.constantBound(Condition.LE, CiConstant.forLong(upperBound));
-
-        return new BasicValueStamp(CiKind.Long, false, null, null, scalarType.query(), null);
-    }
-
-    public static Stamp exactNonNull(final RiResolvedType type) {
-        // (cwimmer) type can be null for certain Maxine-internal objects such as the static hub. Is this a problem here?
-        assert type == null || type.kind(false) == CiKind.Object;
-        ObjectTypeFeedbackStore objectType = new ObjectTypeFeedbackStore(new TypeFeedbackChanged());
-        objectType.constantBound(Condition.NE, CiConstant.NULL_OBJECT);
-        objectType.exactType(type);
-        return new BasicValueStamp(CiKind.Object, true, type, type, null, objectType.query());
+        return new IntegerStamp(CiKind.Long, lowerBound, upperBound);
     }
 
     public static Stamp forConstant(CiConstant value) {
@@ -216,69 +122,59 @@
     public static Stamp forConstant(CiConstant value, RiRuntime runtime) {
         assert value.kind == CiKind.Object;
         if (value.kind == CiKind.Object) {
-            ObjectTypeFeedbackStore objectType = new ObjectTypeFeedbackStore(new TypeFeedbackChanged());
-            objectType.constantBound(Condition.EQ, value);
             RiResolvedType type = value.isNull() ? null : runtime.getTypeOf(value);
-            return new BasicValueStamp(CiKind.Object, value.isNonNull(), type, type, null, objectType.query());
+            return new ObjectStamp(type, value.isNonNull(), value.isNonNull());
         } else {
             throw new GraalInternalError("CiKind.Object expected, actual kind: %s", value.kind);
         }
     }
 
+    public static Stamp object() {
+        return objectStamp;
+    }
+
     public static Stamp objectNonNull() {
-        return new BasicValueStamp(CiKind.Object, true, null, null);
+        return objectNonNullStamp;
     }
 
-    public static Stamp declared(final RiResolvedType type) {
+    public static Stamp declared(RiResolvedType type) {
+        return declared(type, false);
+    }
+
+    public static Stamp declaredNonNull(RiResolvedType type) {
+        return declared(type, true);
+    }
+
+    private static Stamp declared(RiResolvedType type, boolean nonNull) {
         assert type != null;
         assert type.kind(false) == CiKind.Object;
-        return new BasicValueStamp(CiKind.Object, false, type, type.exactType());
+        RiResolvedType exact = type.exactType();
+        if (exact != null) {
+            return new ObjectStamp(exact, true, nonNull);
+        } else {
+            return new ObjectStamp(type, false, nonNull);
+        }
     }
 
-    public static Stamp declaredNonNull(final RiResolvedType type) {
-        assert type != null;
-        assert type.kind(false) == CiKind.Object;
-        return new BasicValueStamp(CiKind.Object, true, type, type.exactType());
+    public static Stamp exactNonNull(RiResolvedType type) {
+        return new ObjectStamp(type, true, true);
     }
 
     public static Stamp or(Collection<? extends StampProvider> values) {
+        return meet(values);
+    }
+
+    public static Stamp meet(Collection<? extends StampProvider> values) {
         if (values.size() == 0) {
-            return illegal();
+            return forVoid();
         } else {
             Iterator< ? extends StampProvider> iterator = values.iterator();
-            Stamp first = iterator.next().stamp();
-            if (values.size() == 1) {
-                return first;
-            }
+            Stamp stamp = iterator.next().stamp();
 
-            boolean nonNull = first.nonNull();
-            RiResolvedType declaredType = first.declaredType();
-            RiResolvedType exactType = first.exactType();
             while (iterator.hasNext()) {
-                Stamp current = iterator.next().stamp();
-                assert current.kind() == first.kind() : values + " first=" + first + " current=" + current + " first kind=" + first.kind() + " current kind=" + current.kind();
-                nonNull &= current.nonNull();
-                declaredType = orTypes(declaredType, current.declaredType());
-                if (exactType != current.exactType()) {
-                    exactType = null;
-                }
+                stamp = stamp.meet(iterator.next().stamp());
             }
-
-            if (nonNull != first.nonNull() || declaredType != first.declaredType() || exactType != first.exactType()) {
-                return new BasicValueStamp(first.kind(), nonNull, declaredType, exactType);
-            } else {
-                return first;
-            }
-        }
-    }
-
-    private static RiResolvedType orTypes(RiResolvedType a, RiResolvedType b) {
-        if (a == b) {
-            return a;
-        } else if (a == null || b == null) {
-            return null;
-        } else {
-            return a.leastCommonAncestor(b);
+            return stamp;
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java	Fri May 25 11:35:18 2012 +0200
@@ -49,7 +49,7 @@
     }
 
     public VirtualObjectFieldNode(VirtualObjectNode object, ValueNode lastState, ValueNode input, int index) {
-        super(StampFactory.illegal());
+        super(StampFactory.virtual());
         this.index = index;
         this.object = object;
         this.lastState = lastState;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Fri May 25 10:36:23 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Fri May 25 11:35:18 2012 +0200
@@ -35,14 +35,14 @@
     private int fieldsCount;
 
     public VirtualObjectNode(RiResolvedType type, EscapeField[] fields) {
-        super(StampFactory.illegal());
+        super(StampFactory.virtual());
         this.type = type;
         this.fields = fields;
         this.fieldsCount = fields.length;
     }
 
     public VirtualObjectNode(RiResolvedType type, int fieldCount) {
-        super(StampFactory.illegal());
+        super(StampFactory.virtual());
         this.type = type;
         this.fieldsCount = fieldCount;
     }