changeset 7300:2912b72d840a

More complete and reusable Word type
author Christian Wimmer <christian.wimmer@oracle.com>
date Fri, 04 Jan 2013 12:08:11 -0800
parents 57edf6b07d36
children 6e68b27928c8
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotCurrentRawThreadNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.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/ThreadIsInterruptedStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.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.snippets.test/src/com/oracle/graal/snippets/WordTest.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java graal/com.oracle.graal.word/src/com/oracle/graal/word/WordBase.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java mx/projects src/share/vm/runtime/arguments.cpp
diffstat 84 files changed, 3056 insertions(+), 1094 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Fri Jan 04 12:08:11 2013 -0800
@@ -50,12 +50,12 @@
      * Gets the calling convention describing how arguments are passed.
      *
      * @param type the type of calling convention being requested
-     * @param returnKind the return kind
-     * @param parameters the kinds of the arguments of the call
+     * @param returnType the return type (can be null for methods returning {@code void})
+     * @param parameterTypes the types of the arguments of the call
      * @param target the target platform
      * @param stackOnly ignore registers
      */
-    CallingConvention getCallingConvention(Type type, Kind returnKind, Kind[] parameters, TargetDescription target, boolean stackOnly);
+    CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly);
 
     /**
      * Gets the ordered set of registers that are can be used to pass parameters
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java	Fri Jan 04 12:08:11 2013 -0800
@@ -24,8 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.meta.*;
-
 /**
  * The name, signature and calling convention of a call from compiled code to the runtime.
  * The target of such a call may be a leaf stub or a call into the runtime code proper.
@@ -38,14 +36,14 @@
     public static class Descriptor {
         private final String name;
         private final boolean hasSideEffect;
-        private final Kind resultKind;
-        private final Kind[] argumentKinds;
+        private final Class resultType;
+        private final Class[] argumentTypes;
 
-        public Descriptor(String name, boolean hasSideEffect, Kind resultKind, Kind... args) {
+        public Descriptor(String name, boolean hasSideEffect, Class resultType, Class... argumentTypes) {
             this.name = name;
             this.hasSideEffect = hasSideEffect;
-            this.resultKind = resultKind;
-            this.argumentKinds = args;
+            this.resultType = resultType;
+            this.argumentTypes = argumentTypes;
         }
 
         /**
@@ -67,15 +65,15 @@
         /**
          * Gets the return kind of this runtime call.
          */
-        public Kind getResultKind() {
-            return resultKind;
+        public Class getResultType() {
+            return resultType;
         }
 
         /**
          * Gets the argument kinds of this runtime call.
          */
-        public Kind[] getArgumentKinds() {
-            return argumentKinds.clone();
+        public Class[] getArgumentTypes() {
+            return argumentTypes.clone();
         }
 
         @Override
@@ -87,7 +85,7 @@
         public boolean equals(Object obj) {
             if (obj instanceof Descriptor) {
                 Descriptor nas = (Descriptor) obj;
-                return nas.name.equals(name) && nas.resultKind.equals(resultKind) && Arrays.equals(nas.argumentKinds, argumentKinds);
+                return nas.name.equals(name) && nas.resultType.equals(resultType) && Arrays.equals(nas.argumentTypes, argumentTypes);
             }
             return false;
         }
@@ -96,11 +94,11 @@
         public String toString() {
             StringBuilder sb = new StringBuilder(name).append('(');
             String sep = "";
-            for (Kind arg : argumentKinds) {
-                sb.append(sep).append(arg);
+            for (Class arg : argumentTypes) {
+                sb.append(sep).append(arg.getSimpleName());
                 sep = ",";
             }
-            return sb.append(')').append(resultKind).toString();
+            return sb.append(')').append(resultType.getSimpleName()).toString();
         }
     }
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.api.code;
 
+import java.math.*;
+
 //JaCoCo Exclude
 
 /**
@@ -87,5 +89,37 @@
     public static boolean belowOrEqual(long a, long b) {
         return (a <= b) ^ ((a < 0) != (b < 0));
     }
+
+    /**
+     * Unsigned division for two numbers.
+     */
+    public static int divide(int a, int b) {
+        return (int) ((a & MASK) / (b & MASK));
+    }
+
+    /**
+     * Unsigned remainder for two numbers.
+     */
+    public static int remainder(int a, int b) {
+        return (int) ((a & MASK) % (b & MASK));
+    }
+
+    /**
+     * Unsigned division for two numbers.
+     */
+    public static long divide(long a, long b) {
+        return bi(a).divide(bi(b)).longValue();
+    }
+
+    /**
+     * Unsigned remainder for two numbers.
+     */
+    public static long remainder(long a, long b) {
+        return bi(a).remainder(bi(b)).longValue();
+    }
+
+    private static BigInteger bi(long unsigned) {
+        return unsigned >= 0 ? BigInteger.valueOf(unsigned) : BigInteger.valueOf(unsigned & 0x7fffffffffffffffL).setBit(63);
+    }
 }
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Fri Jan 04 12:08:11 2013 -0800
@@ -431,4 +431,32 @@
                 throw new RuntimeException("cannot create Constant for boxed " + kind + " value");
         }
     }
+
+    /**
+     * Returns a constant with the default value for the given kind.
+     */
+    public static Constant defaultForKind(Kind kind) {
+        switch(kind) {
+            case Boolean:
+                return FALSE;
+            case Byte:
+                return forByte((byte) 0);
+            case Char:
+                return forChar((char) 0);
+            case Short:
+                return forShort((short) 0);
+            case Int:
+                return INT_0;
+            case Double:
+                return DOUBLE_0;
+            case Float:
+                return FLOAT_0;
+            case Long:
+                return LONG_0;
+            case Object:
+                return NULL_OBJECT;
+            default:
+                throw new IllegalArgumentException(kind.toString());
+        }
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Fri Jan 04 12:08:11 2013 -0800
@@ -46,6 +46,17 @@
     }
 
     /**
+     * Calls {@link MetaAccessProvider#lookupJavaType(Class)} on an array of classes.
+     */
+    public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class[] classes) {
+        ResolvedJavaType[] result = new ResolvedJavaType[classes.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = metaAccess.lookupJavaType(classes[i]);
+        }
+        return result;
+    }
+
+    /**
      * Gets the {@link Class} mirror for a given resolved type.
      *
      * @param type the type for which the Java mirror is requested
@@ -460,29 +471,46 @@
         return sb.append(" [bci: ").append(bci).append(']');
     }
 
-    public static Kind[] signatureToKinds(ResolvedJavaMethod method) {
-        Kind receiver = isStatic(method.getModifiers()) ? null : method.getDeclaringClass().getKind();
-        return signatureToKinds(method.getSignature(), receiver);
+    public static JavaType[] signatureToTypes(ResolvedJavaMethod method) {
+        JavaType receiver = isStatic(method.getModifiers()) ? null : method.getDeclaringClass();
+        return signatureToTypes(method.getSignature(), receiver);
     }
 
-    public static Kind[] signatureToKinds(Signature signature, Kind receiverKind) {
+    public static JavaType[] signatureToTypes(Signature signature, JavaType receiverType) {
         int args = signature.getParameterCount(false);
-        Kind[] result;
+        JavaType[] result;
         int i = 0;
-        if (receiverKind != null) {
-            result = new Kind[args + 1];
-            result[0] = receiverKind;
+        if (receiverType != null) {
+            result = new JavaType[args + 1];
+            result[0] = receiverType;
             i = 1;
         } else {
-            result = new Kind[args];
+            result = new JavaType[args];
         }
         for (int j = 0; j < args; j++) {
-            result[i + j] = signature.getParameterKind(j);
+            result[i + j] = signature.getParameterType(j, null);
         }
         return result;
     }
 
     /**
+     * Converts a {@link Signature} to internal representation, i.e., the signature
+     * <pre>(int, String, double)void</pre> is converted to <pre>(ILjava/lang/String;D)V</pre>.
+     *
+     * @param sig the {@link Signature} to be converted.
+     *
+     * @return the signature's internal representation as a string.
+     */
+    public static String signatureToInternal(Signature sig) {
+        StringBuilder sb = new StringBuilder("(");
+        for (int i = 0; i < sig.getParameterCount(false); ++i) {
+            sb.append(sig.getParameterType(i, null).getName());
+        }
+        sb.append(')').append(sig.getReturnType(null).getName());
+        return sb.toString();
+    }
+
+    /**
      * Formats some profiling information associated as a string.
      *
      * @param info the profiling info to format
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java	Fri Jan 04 12:08:11 2013 -0800
@@ -36,8 +36,8 @@
 
 public class AMD64DeoptimizationStub extends AMD64Code {
 
-    public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, Kind.Void);
-    public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", true, Kind.Void, Kind.Object);
+    public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class);
+    public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", true, void.class, Object.class);
 
     public final Label label = new Label();
     public final LIRFrameState info;
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Jan 04 12:08:11 2013 -0800
@@ -79,8 +79,8 @@
  */
 public abstract class AMD64LIRGenerator extends LIRGenerator {
 
-    public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, Kind.Float, Kind.Float, Kind.Float);
-    public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, Kind.Double, Kind.Double, Kind.Double);
+    public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, float.class, float.class, float.class);
+    public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, double.class, double.class, double.class);
 
     private static final RegisterValue RAX_I = AMD64.rax.asValue(Kind.Int);
     private static final RegisterValue RAX_L = AMD64.rax.asValue(Kind.Long);
@@ -529,6 +529,11 @@
             case MOV_L2D: append(new Op1Reg(MOV_L2D, result, input)); break;
             case MOV_F2I: append(new Op1Reg(MOV_F2I, result, input)); break;
             case MOV_D2L: append(new Op1Reg(MOV_D2L, result, input)); break;
+            case UNSIGNED_I2L:
+                // Instructions that move or generate 32-bit register values also set the upper 32 bits of the register to zero.
+                // Consequently, there is no need for a special zero-extension move.
+                emitMove(input, result);
+                break;
             default: throw GraalInternalError.shouldNotReachHere();
         }
         return result;
@@ -711,12 +716,12 @@
 
     @Override
     public void visitBreakpointNode(BreakpointNode node) {
-        Kind[] sig = new Kind[node.arguments.size()];
+        JavaType[] sig = new JavaType[node.arguments.size()];
         for (int i = 0; i < sig.length; i++) {
-            sig[i] = node.arguments.get(i).kind();
+            sig[i] = node.arguments.get(i).stamp().javaType(runtime);
         }
 
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, Kind.Void, sig, target(), false);
+        CallingConvention cc = frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false);
         Value[] parameters = visitInvokeArguments(cc, node.arguments);
         append(new AMD64BreakpointOp(parameters));
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Jan 04 12:08:11 2013 -0800
@@ -459,7 +459,7 @@
     }
 
     protected CallingConvention createCallingConvention() {
-        return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnKind(), MetaUtil.signatureToKinds(method), target, false);
+        return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), MetaUtil.signatureToTypes(method), target, false);
     }
 
     protected void emitPrologue() {
@@ -711,8 +711,7 @@
     @Override
     public void emitInvoke(Invoke x) {
         AbstractCallTargetNode callTarget = (AbstractCallTargetNode) x.callTarget();
-        Kind[] signature = callTarget.signature();
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().kind(), signature, target(), false);
+        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().stamp().javaType(runtime), callTarget.signature(), target(), false);
         frameMap.callsMethod(cc);
 
         Value[] parameters = visitInvokeArguments(cc, callTarget.arguments());
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java	Fri Jan 04 12:08:11 2013 -0800
@@ -25,9 +25,7 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-import sun.misc.*;
-
-public abstract class FieldIntrospection {
+public abstract class FieldIntrospection extends UnsafeAccess {
 
     /**
      * Interface used by {@link #rescanAllFieldOffsets(CalcOffset)} to determine the offset (in bytes) of a field.
@@ -43,28 +41,6 @@
         }
     }
 
-    /**
-     * An instance of {@link Unsafe} for use within Graal.
-     */
-    public static final Unsafe unsafe = getUnsafe();
-
-    private static Unsafe getUnsafe() {
-        try {
-            // this will fail if Graal is not part of the boot class path
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-            // nothing to do
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            // currently we rely on being able to use Unsafe...
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
-
     protected static final ConcurrentHashMap<Class<?>, FieldIntrospection> allClasses = new ConcurrentHashMap<>();
 
     protected final Class<?> clazz;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 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.graph;
+
+import java.lang.reflect.*;
+
+import sun.misc.*;
+
+public class UnsafeAccess {
+
+    /**
+     * An instance of {@link Unsafe} for use within Graal.
+     */
+    public static final Unsafe unsafe = getUnsafe();
+
+    private static Unsafe getUnsafe() {
+        try {
+            // this will fail if Graal is not part of the boot class path
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+            // nothing to do
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            // currently we rely on being able to use Unsafe...
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Jan 04 12:08:11 2013 -0800
@@ -90,7 +90,7 @@
             if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
                 return super.createCallingConvention();
             } else {
-                return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnKind(), new Kind[]{Kind.Long}, target, false);
+                return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), new JavaType[]{runtime.lookupJavaType(long.class)}, target, false);
             }
         }
 
@@ -262,7 +262,7 @@
 
         if (!isStatic) {
             tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
-            CallingConvention cc = regConfig.getCallingConvention(JavaCallee, Kind.Void, new Kind[] {Kind.Object}, target, false);
+            CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[] {runtime().lookupJavaType(Object.class)}, target, false);
             Register inlineCacheKlass = rax; // see definition of IC_Klass in c1_LIRAssembler_x86.cpp
             Register receiver = asRegister(cc.getArgument(0));
             Address src = new Address(target.wordKind, receiver.asValue(), config.hubOffset);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Jan 04 12:08:11 2013 -0800
@@ -105,11 +105,11 @@
     }
 
     @Override
-    public CallingConvention getCallingConvention(Type type, Kind returnKind, Kind[] parameters, TargetDescription target, boolean stackOnly) {
+    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
         if (type == Type.NativeCall) {
             throw new UnsupportedOperationException();
         }
-        return callingConvention(returnKind, parameters, type, target, stackOnly);
+        return callingConvention(returnType, parameterTypes, type, target, stackOnly);
     }
 
     public Register[] getCallingConventionRegisters(Type type, RegisterFlag flag) {
@@ -119,15 +119,15 @@
         return generalParameterRegisters;
     }
 
-    private CallingConvention callingConvention(Kind returnKind, Kind[] kinds, Type type, TargetDescription target, boolean stackOnly) {
-        Value[] locations = new Value[kinds.length];
+    private CallingConvention callingConvention(JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
+        Value[] locations = new Value[parameterTypes.length];
 
         int currentGeneral = 0;
         int currentXMM = 0;
         int currentStackOffset = 0;
 
-        for (int i = 0; i < kinds.length; i++) {
-            final Kind kind = kinds[i];
+        for (int i = 0; i < parameterTypes.length; i++) {
+            final Kind kind = parameterTypes[i].getKind();
 
             switch (kind) {
                 case Byte:
@@ -159,6 +159,7 @@
             }
         }
 
+        Kind returnKind = returnType == null ? Kind.Void : returnType.getKind();
         Value returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind);
         return new CallingConvention(currentStackOffset, returnLocation, locations);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -70,14 +70,14 @@
     }
 
     private boolean checkArgs(Object... args) {
-        Kind[] sig = MetaUtil.signatureToKinds(method);
+        JavaType[] sig = MetaUtil.signatureToTypes(method);
         assert args.length == sig.length : MetaUtil.format("%H.%n(%p): expected ", method) + sig.length + " args, got " + args.length;
         for (int i = 0; i < sig.length; i++) {
             Object arg = args[i];
             if (arg == null) {
-                assert sig[i] == Kind.Object : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i];
-            } else if (sig[i] != Kind.Object) {
-                assert sig[i].toBoxedJavaClass() == arg.getClass() : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass();
+                assert sig[i].getKind() == Kind.Object : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i];
+            } else if (sig[i].getKind() != Kind.Object) {
+                assert sig[i].getKind().toBoxedJavaClass() == arg.getClass() : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass();
             }
         }
         return true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Jan 04 12:08:11 2013 -0800
@@ -66,6 +66,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.printer.*;
 import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * HotSpot implementation of {@link GraalCodeCacheProvider}.
@@ -264,20 +265,27 @@
         for (int i = 0; i < temps.length; i++) {
             temps[i] = tempRegs[i].asValue();
         }
-        Kind retKind = ret.getKind();
-        if (retKind == Kind.Illegal) {
-            retKind = Kind.Void;
-        }
-        assert retKind.equals(descriptor.getResultKind()) : descriptor + " incompatible with result location " + ret;
-        Kind[] argKinds = descriptor.getArgumentKinds();
-        assert argKinds.length == args.length : descriptor + " incompatible with number of argument locations: " + args.length;
-        for (int i = 0; i < argKinds.length; i++) {
-            assert argKinds[i].equals(args[i].getKind()) : descriptor + " incompatible with argument location " + i + ": " + args[i];
+        assert checkAssignable(descriptor.getResultType(), ret) : descriptor + " incompatible with result location " + ret;
+        Class[] argTypes = descriptor.getArgumentTypes();
+        assert argTypes.length == args.length : descriptor + " incompatible with number of argument locations: " + args.length;
+        for (int i = 0; i < argTypes.length; i++) {
+            assert checkAssignable(argTypes[i], args[i]) : descriptor + " incompatible with argument location " + i + ": " + args[i];
         }
         HotSpotRuntimeCallTarget runtimeCall = new HotSpotRuntimeCallTarget(descriptor, address, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM());
         runtimeCalls.put(descriptor, runtimeCall);
     }
 
+    private boolean checkAssignable(Class spec, Value value) {
+        Kind kind = value.getKind();
+        if (kind == Kind.Illegal) {
+            kind = Kind.Void;
+        }
+        if (WordBase.class.isAssignableFrom(spec)) {
+            return kind == graalRuntime.getTarget().wordKind;
+        }
+        return kind == Kind.fromJavaClass(spec);
+    }
+
     /**
      * Binds a snippet-base {@link Stub} to a runtime call descriptor.
      *
@@ -502,7 +510,7 @@
                 if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) {
                     invoke.node().dependencies().add(tool.createNullCheckGuard(receiver, invoke.leafGraphId()));
                 }
-                Kind[] signature = MetaUtil.signatureToKinds(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass().getKind());
+                JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
 
                 AbstractCallTargetNode loweredCallTarget = null;
                 if (callTarget.invokeKind() == InvokeKind.Virtual &&
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Intrinsic for opening a scope binding a stack-based lock with an object.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -27,7 +27,7 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -28,7 +28,7 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Intrinsic for allocating an on-stack array of integers to hold the dimensions
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * A special purpose store node that differs from {@link CompareAndSwapNode} in that
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotCurrentRawThreadNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotCurrentRawThreadNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 
 public class HotSpotCurrentRawThreadNode extends FloatingNode implements LIRLowerable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -34,7 +34,7 @@
 
     private final InvokeKind invokeKind;
 
-    public HotSpotDirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, Kind[] signature, Object target, Type callType, InvokeKind invokeKind) {
+    public HotSpotDirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, Type callType, InvokeKind invokeKind) {
         super(arguments, returnStamp, signature, target, callType);
         this.invokeKind = invokeKind;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -33,7 +33,7 @@
 
     @Input private ValueNode metaspaceMethod;
 
-    public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, Kind[] signature, Object target, Type callType) {
+    public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, Type callType) {
         super(computedAddress, arguments, returnStamp, signature, target, callType);
         this.metaspaceMethod = metaspaceMethod;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -36,7 +36,7 @@
  */
 public class IdentityHashCodeStubCall extends FixedWithNextNode implements LIRGenLowerable {
     @Input private final ValueNode object;
-    public static final Descriptor IDENTITY_HASHCODE = new Descriptor("identity_hashcode", false, Kind.Int, Kind.Object);
+    public static final Descriptor IDENTITY_HASHCODE = new Descriptor("identity_hashcode", false, int.class, Object.class);
 
     public IdentityHashCodeStubCall(ValueNode object) {
         super(StampFactory.forKind(Kind.Int));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -28,7 +28,7 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Node that is used to maintain a stack based counter of how many locks
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,16 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Node implementing a call to HotSpot's {@code graal_monitorenter} stub.
@@ -40,7 +37,7 @@
 
     @Input private final ValueNode object;
     @Input private final ValueNode lock;
-    public static final Descriptor MONITORENTER = new Descriptor("monitorenter", true, Kind.Void, Kind.Object, wordKind());
+    public static final Descriptor MONITORENTER = new Descriptor("monitorenter", true, void.class, Object.class, Word.class);
 
     public MonitorEnterStubCall(ValueNode object, ValueNode lock) {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,15 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.word.*;
 
 /**
  * Node implementing a call to HotSpot's {@code graal_monitorexit} stub.
@@ -38,7 +36,7 @@
 public class MonitorExitStubCall extends FixedWithNextNode implements LIRGenLowerable {
 
     @Input private final ValueNode object;
-    public static final Descriptor MONITOREXIT = new Descriptor("monitorexit", true, Kind.Void, Kind.Object, wordKind());
+    public static final Descriptor MONITOREXIT = new Descriptor("monitorexit", true, void.class, Object.class, Word.class);
 
     public MonitorExitStubCall(ValueNode object) {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,18 +22,15 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Node implementing a call to the {@code new_array} stub.
@@ -45,7 +42,7 @@
     @Input private final ValueNode hub;
     @Input private final ValueNode length;
 
-    public static final Descriptor NEW_ARRAY_SLOW = new Descriptor("new_array_slow", false, Kind.Object, wordKind(), Kind.Int);
+    public static final Descriptor NEW_ARRAY_SLOW = new Descriptor("new_array_slow", false, Object.class, Word.class, int.class);
 
     public NewArraySlowStubCall(ValueNode hub, ValueNode length) {
         super(defaultStamp);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,11 +22,8 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -34,7 +31,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * A call to the {@link NewArrayStub}.
@@ -46,7 +43,7 @@
     @Input private final ValueNode hub;
     @Input private final ValueNode length;
 
-    public static final Descriptor NEW_ARRAY = new Descriptor("new_array", false, Kind.Object, wordKind(), Kind.Int);
+    public static final Descriptor NEW_ARRAY = new Descriptor("new_array", false, Object.class, Word.class, int.class);
 
     public NewArrayStubCall(ValueNode hub, ValueNode length) {
         super(defaultStamp);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,18 +22,15 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Node implementing a call to HotSpot's {@code new_instance} stub.
@@ -44,7 +41,7 @@
 
     @Input private final ValueNode hub;
 
-    public static final Descriptor NEW_INSTANCE_SLOW = new Descriptor("new_instance_slow", false, Kind.Object, wordKind());
+    public static final Descriptor NEW_INSTANCE_SLOW = new Descriptor("new_instance_slow", false, Object.class, Word.class);
 
     public NewInstanceSlowStubCall(ValueNode hub) {
         super(defaultStamp);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,11 +22,8 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -34,7 +31,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * A call to the {@link NewInstanceStub}.
@@ -45,7 +42,7 @@
 
     @Input private final ValueNode hub;
 
-    public static final Descriptor NEW_INSTANCE = new Descriptor("new_instance", false, Kind.Object, wordKind());
+    public static final Descriptor NEW_INSTANCE = new Descriptor("new_instance", false, Object.class, Word.class);
 
     public NewInstanceStubCall(ValueNode hub) {
         super(defaultStamp);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
@@ -33,7 +31,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Node implementing a call to HotSpot's {@code new_multi_array} stub.
@@ -46,7 +44,7 @@
     @Input private final ValueNode dims;
     private final int rank;
 
-    public static final Descriptor NEW_MULTI_ARRAY = new Descriptor("new_multi_array", false, Kind.Object, wordKind(), Kind.Int, wordKind());
+    public static final Descriptor NEW_MULTI_ARRAY = new Descriptor("new_multi_array", false, Object.class, Word.class, int.class, Word.class);
 
     public NewMultiArrayStubCall(ValueNode hub, int rank, ValueNode dims) {
         super(defaultStamp);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -25,7 +25,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Allocates some uninitialized area. This is used for TLAB allocation
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -60,8 +60,8 @@
         ResolvedJavaMethod method = frameState.method();
         boolean isStatic = Modifier.isStatic(method.getModifiers());
 
-        Kind[] signature = MetaUtil.signatureToKinds(method.getSignature(), isStatic ? null : method.getDeclaringClass().getKind());
-        CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, Kind.Void, signature, gen.target(), false);
+        JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass());
+        CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.target(), false);
         gen.frameMap().callsMethod(cc); // TODO (aw): I think this is unnecessary for a tail call.
         List<ValueNode> parameters = new ArrayList<>();
         for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -37,7 +37,7 @@
 public class ThreadIsInterruptedStubCall extends FixedWithNextNode implements LIRGenLowerable {
     @Input private final ValueNode thread;
     @Input private final ValueNode clearIsInterrupted;
-    public static final Descriptor THREAD_IS_INTERRUPTED = new Descriptor("thread_is_interrupted", false, Kind.Int, Kind.Object, Kind.Boolean);
+    public static final Descriptor THREAD_IS_INTERRUPTED = new Descriptor("thread_is_interrupted", false, int.class, Object.class, boolean.class);
 
     public ThreadIsInterruptedStubCall(ValueNode thread, ValueNode clearIsInterrupted) {
         super(StampFactory.forInteger(Kind.Int, 0, 1));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -41,7 +41,7 @@
 
     @Input private ValueNode format;
     @Input private ValueNode value;
-    public static final Descriptor VM_ERROR = new Descriptor("vm_error", false, Kind.Void, Kind.Object, Kind.Object, Kind.Long);
+    public static final Descriptor VM_ERROR = new Descriptor("vm_error", false, void.class, Object.class, Object.class, long.class);
 
     public VMErrorNode(ValueNode format, ValueNode value) {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Fri Jan 04 12:08:11 2013 -0800
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
@@ -36,7 +35,7 @@
 public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable {
 
     @Input private final ValueNode object;
-    public static final Descriptor VERIFY_OOP = new Descriptor("verify_oop", false, Kind.Void, Kind.Object);
+    public static final Descriptor VERIFY_OOP = new Descriptor("verify_oop", false, void.class, Object.class);
 
     public VerifyOopStubCall(ValueNode object) {
         super(StampFactory.objectNonNull());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Fri Jan 04 12:08:11 2013 -0800
@@ -41,7 +41,7 @@
 
 public class OnStackReplacementPhase extends Phase {
 
-    public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, Kind.Void, Kind.Long);
+    public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, void.class, long.class);
 
     @Override
     protected void run(StructuredGraph graph) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -46,6 +46,7 @@
 import com.oracle.graal.snippets.SnippetTemplate.Arguments;
 import com.oracle.graal.snippets.SnippetTemplate.Key;
 import com.oracle.graal.snippets.nodes.*;
+import com.oracle.graal.word.*;
 
 /**
  * Snippets used for implementing the type test of a checkcast instruction.
@@ -177,7 +178,7 @@
         int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
         for (int i = 0; i < length; i++) {
             if (t == loadWordElement(secondarySupers, i)) {
-                DirectObjectStoreNode.storeWord(s, secondarySuperCacheOffset(), 0, t);
+                s.writeWord(secondarySuperCacheOffset(), t);
                 secondariesHit.inc();
                 return true;
             }
@@ -218,7 +219,7 @@
         int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
         for (int i = 0; i < length; i++) {
             if (t == loadWordElement(secondarySupers, i)) {
-                DirectObjectStoreNode.storeWord(s, secondarySuperCacheOffset(), 0, t);
+                s.writeWord(secondarySuperCacheOffset(), t);
                 secondariesHit.inc();
                 return true;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -30,6 +30,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
+import com.oracle.graal.word.*;
 
 /**
  * Snippets for {@link java.lang.Class} methods.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Fri Jan 04 12:08:11 2013 -0800
@@ -31,7 +31,7 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.snippets.Snippet.Fold;
-import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 //JaCoCo Exclude
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -43,6 +43,7 @@
 import com.oracle.graal.snippets.SnippetTemplate.Arguments;
 import com.oracle.graal.snippets.SnippetTemplate.Key;
 import com.oracle.graal.snippets.nodes.*;
+import com.oracle.graal.word.*;
 
 /**
  * Snippets used for implementing the type test of an instanceof instruction.
@@ -150,7 +151,7 @@
         int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
         for (int i = 0; i < length; i++) {
             if (t == loadWordElement(secondarySupers, i)) {
-                DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t);
+                s.writeWord(secondarySuperCacheOffset(), t);
                 secondariesHit.inc();
                 return true;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -28,7 +28,6 @@
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
 import static com.oracle.graal.snippets.SnippetTemplate.*;
-import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*;
 
 import java.util.*;
 
@@ -50,7 +49,7 @@
 import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.snippets.SnippetTemplate.Arguments;
 import com.oracle.graal.snippets.SnippetTemplate.Key;
-import com.oracle.graal.snippets.nodes.*;
+import com.oracle.graal.word.*;
 
 /**
  * Snippets used for implementing the monitorenter and monitorexit instructions.
@@ -86,9 +85,9 @@
 
         final Word lock = beginLockScope(false);
 
-        trace(trace, "           object: 0x%016lx\n", Word.fromObject(object).toLong());
-        trace(trace, "             lock: 0x%016lx\n", lock.toLong());
-        trace(trace, "             mark: 0x%016lx\n", mark.toLong());
+        trace(trace, "           object: 0x%016lx\n", Word.fromObject(object));
+        trace(trace, "             lock: 0x%016lx\n", lock);
+        trace(trace, "             mark: 0x%016lx\n", mark);
 
         incCounter();
 
@@ -100,7 +99,7 @@
             final Word biasableLockBits = mark.and(biasedLockMaskInPlace());
 
             // First check to see whether biasing is enabled for this object
-            if (biasableLockBits.toLong() != biasedLockPattern()) {
+            if (biasableLockBits != Word.unsigned(biasedLockPattern())) {
                 // Biasing not enabled -> fall through to lightweight locking
             } else {
                 // The bias pattern is present in the object's mark word. Need to check
@@ -109,12 +108,12 @@
                 final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
                 final Word thread = thread();
                 final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace());
-                trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord.toLong());
-                trace(trace, "           thread: 0x%016lx\n", thread.toLong());
-                trace(trace, "              tmp: 0x%016lx\n", tmp.toLong());
+                trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord);
+                trace(trace, "           thread: 0x%016lx\n", thread);
+                trace(trace, "              tmp: 0x%016lx\n", tmp);
                 if (tmp == Word.zero()) {
                     // Object is already biased to current thread -> done
-                    trace(trace, "+lock{bias:existing}", object);
+                    traceObject(trace, "+lock{bias:existing}", object);
                     return;
                 }
 
@@ -146,17 +145,17 @@
                         // don't accidentally blow away another thread's valid bias.
                         Word unbiasedMark = mark.and(biasedLockMaskInPlace() | ageMaskInPlace() | epochMaskInPlace());
                         Word biasedMark = unbiasedMark.or(thread);
-                        trace(trace, "     unbiasedMark: 0x%016lx\n", unbiasedMark.toLong());
-                        trace(trace, "       biasedMark: 0x%016lx\n", biasedMark.toLong());
+                        trace(trace, "     unbiasedMark: 0x%016lx\n", unbiasedMark);
+                        trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
                         if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark) == unbiasedMark) {
                             // Object is now biased to current thread -> done
-                            trace(trace, "+lock{bias:acquired}", object);
+                            traceObject(trace, "+lock{bias:acquired}", object);
                             return;
                         }
                         // If the biasing toward our thread failed, this means that another thread
                         // owns the bias and we need to revoke that bias. The revocation will occur
                         // in the interpreter runtime.
-                        trace(trace, "+lock{stub:revoke}", object);
+                        traceObject(trace, "+lock{stub:revoke}", object);
                         MonitorEnterStubCall.call(object, lock);
                         return;
                     } else {
@@ -167,16 +166,16 @@
                         // bias in the current epoch. In other words, we allow transfer of
                         // the bias from one thread to another directly in this situation.
                         Word biasedMark = prototypeMarkWord.or(thread);
-                        trace(trace, "       biasedMark: 0x%016lx\n", biasedMark.toLong());
+                        trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
                         if (compareAndSwap(object, markOffset(), mark, biasedMark) == mark) {
                             // Object is now biased to current thread -> done
-                            trace(trace, "+lock{bias:transfer}", object);
+                            traceObject(trace, "+lock{bias:transfer}", object);
                             return;
                         }
                         // If the biasing toward our thread failed, then another thread
                         // succeeded in biasing it toward itself and we need to revoke that
                         // bias. The revocation will occur in the runtime in the slow case.
-                        trace(trace, "+lock{stub:epoch-expired}", object);
+                        traceObject(trace, "+lock{stub:epoch-expired}", object);
                         MonitorEnterStubCall.call(object, lock);
                         return;
                     }
@@ -204,16 +203,16 @@
 
         // Create the unlocked mark word pattern
         Word unlockedMark = mark.or(unlockedMask());
-        trace(trace, "     unlockedMark: 0x%016lx\n", unlockedMark.toLong());
+        trace(trace, "     unlockedMark: 0x%016lx\n", unlockedMark);
 
         // Copy this unlocked mark word into the lock slot on the stack
-        storeWord(lock, lockDisplacedMarkOffset(), 0, unlockedMark);
+        lock.writeWord(lockDisplacedMarkOffset(), unlockedMark);
 
         // Test if the object's mark word is unlocked, and if so, store the
         // (address of) the lock slot into the object's mark word.
         Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock);
         if (currentMark != unlockedMark) {
-            trace(trace, "      currentMark: 0x%016lx\n", currentMark.toLong());
+            trace(trace, "      currentMark: 0x%016lx\n", currentMark);
             // The mark word in the object header was not the same.
             // Either the object is locked by another thread or is already locked
             // by the current thread. The latter is true if the mark word
@@ -229,20 +228,20 @@
             //
             // assuming both the stack pointer and page_size have their least
             // significant 2 bits cleared and page_size is a power of 2
-            final Word alignedMask = Word.fromInt(wordSize() - 1);
+            final Word alignedMask = Word.unsigned(wordSize() - 1);
             final Word stackPointer = stackPointer();
-            if (currentMark.minus(stackPointer).and(alignedMask.minus(pageSize())) != Word.zero()) {
+            if (currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())) != Word.zero()) {
                 // Most likely not a recursive lock, go into a slow runtime call
-                trace(trace, "+lock{stub:failed-cas}", object);
+                traceObject(trace, "+lock{stub:failed-cas}", object);
                 MonitorEnterStubCall.call(object, lock);
                 return;
             } else {
                 // Recursively locked => write 0 to the lock slot
-                storeWord(lock, lockDisplacedMarkOffset(), 0, Word.zero());
-                trace(trace, "+lock{recursive}", object);
+                lock.writeWord(lockDisplacedMarkOffset(), Word.zero());
+                traceObject(trace, "+lock{recursive}", object);
             }
         } else {
-            trace(trace, "+lock{cas}", object);
+            traceObject(trace, "+lock{cas}", object);
         }
     }
 
@@ -265,13 +264,13 @@
         // BeginLockScope nodes do not read from object so a use of object
         // cannot float about the null check above
         final Word lock = beginLockScope(false);
-        trace(trace, "+lock{stub}", object);
+        traceObject(trace, "+lock{stub}", object);
         MonitorEnterStubCall.call(object, lock);
     }
 
     @Snippet
     public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
-        trace(trace, "           object: 0x%016lx\n", Word.fromObject(object).toLong());
+        trace(trace, "           object: 0x%016lx\n", Word.fromObject(object));
         if (useBiasedLocking()) {
             // Check for biased locking unlock case, which is a no-op
             // Note: we do not have to check the thread ID for two reasons.
@@ -280,11 +279,11 @@
             // lock, the object could not be rebiased toward another thread, so
             // the bias bit would be clear.
             final Word mark = loadWordFromObject(object, markOffset());
-            trace(trace, "             mark: 0x%016lx\n", mark.toLong());
-            if (mark.and(biasedLockMaskInPlace()).toLong() == biasedLockPattern()) {
+            trace(trace, "             mark: 0x%016lx\n", mark);
+            if (mark.and(biasedLockMaskInPlace()) == Word.unsigned(biasedLockPattern())) {
                 endLockScope();
                 decCounter();
-                trace(trace, "-lock{bias}", object);
+                traceObject(trace, "-lock{bias}", object);
                 return;
             }
         }
@@ -293,11 +292,11 @@
 
         // Load displaced mark
         final Word displacedMark = lock.readWord(lockDisplacedMarkOffset());
-        trace(trace, "    displacedMark: 0x%016lx\n", displacedMark.toLong());
+        trace(trace, "    displacedMark: 0x%016lx\n", displacedMark);
 
         if (displacedMark == Word.zero()) {
             // Recursive locking => done
-            trace(trace, "-lock{recursive}", object);
+            traceObject(trace, "-lock{recursive}", object);
         } else {
             verifyOop(object);
             // Test if object's mark word is pointing to the displaced mark word, and if so, restore
@@ -306,10 +305,10 @@
             if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark) != lock) {
               // The object's mark word was not pointing to the displaced header,
               // we do unlocking via runtime call.
-                trace(trace, "-lock{stub}", object);
+                traceObject(trace, "-lock{stub}", object);
                 MonitorExitStubCall.call(object);
             } else {
-                trace(trace, "-lock{cas}", object);
+                traceObject(trace, "-lock{cas}", object);
             }
         }
         endLockScope();
@@ -322,7 +321,7 @@
     @Snippet
     public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
         verifyOop(object);
-        trace(trace, "-lock{stub}", object);
+        traceObject(trace, "-lock{stub}", object);
         MonitorExitStubCall.call(object);
         endLockScope();
         decCounter();
@@ -334,7 +333,7 @@
         decCounter();
     }
 
-    private static void trace(boolean enabled, String action, Object object) {
+    private static void traceObject(boolean enabled, String action, Object object) {
         if (enabled) {
             Log.print(action);
             Log.print(' ');
@@ -342,9 +341,9 @@
         }
     }
 
-    private static void trace(boolean enabled, String format, long value) {
+    private static void trace(boolean enabled, String format, WordBase value) {
         if (enabled) {
-            Log.printf(format, value);
+            Log.printf(format, value.rawValue());
         }
     }
 
@@ -360,7 +359,7 @@
         if (CHECK_BALANCED_MONITORS) {
             final Word counter = MonitorCounterNode.counter();
             final int count = counter.readInt(0);
-            DirectObjectStoreNode.storeInt(counter, 0, 0, count + 1);
+            counter.writeInt(0, count + 1);
         }
     }
 
@@ -368,14 +367,14 @@
         if (CHECK_BALANCED_MONITORS) {
             final Word counter = MonitorCounterNode.counter();
             final int count = counter.readInt(0);
-            DirectObjectStoreNode.storeInt(counter, 0, 0, count - 1);
+            counter.writeInt(0, count - 1);
         }
     }
 
     @Snippet
     private static void initCounter() {
         final Word counter = MonitorCounterNode.counter();
-        DirectObjectStoreNode.storeInt(counter, 0, 0, 0);
+        counter.writeInt(0, 0);
     }
 
     @Snippet
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -29,7 +29,6 @@
 import static com.oracle.graal.snippets.Snippet.Varargs.*;
 import static com.oracle.graal.snippets.SnippetTemplate.*;
 import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
-import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*;
 import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*;
 
 import com.oracle.graal.api.code.*;
@@ -50,6 +49,7 @@
 import com.oracle.graal.snippets.SnippetTemplate.Arguments;
 import com.oracle.graal.snippets.SnippetTemplate.Key;
 import com.oracle.graal.snippets.nodes.*;
+import com.oracle.graal.word.*;
 
 /**
  * Snippets used for implementing NEW, ANEWARRAY and NEWARRAY.
@@ -61,10 +61,10 @@
         Word thread = thread();
         Word top = thread.readWord(threadTlabTopOffset());
         Word end = thread.readWord(threadTlabEndOffset());
-        Word newTop = top.plus(size);
+        Word newTop = top.add(size);
         // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code)
         if (newTop.belowOrEqual(end)) {
-            storeObject(thread, 0, threadTlabTopOffset(), newTop);
+            thread.writeWord(threadTlabTopOffset(), newTop);
             return top;
         }
         return Word.zero();
@@ -171,7 +171,7 @@
         Word dims = DimensionsNode.allocaDimsArray(rank);
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < rank; i++) {
-            DirectObjectStoreNode.storeInt(dims, 0, i * 4, dimensions[i]);
+            dims.writeInt(i * 4, dimensions[i]);
         }
         return NewMultiArrayStubCall.call(hub, rank, dims);
     }
@@ -188,19 +188,19 @@
      */
     private static void formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents) {
         Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset()) : compileTimePrototypeMarkWord;
-        storeWord(memory, 0, markOffset(), prototypeMarkWord);
-        storeWord(memory, 0, hubOffset(), hub);
+        memory.writeWord(markOffset(), prototypeMarkWord);
+        memory.writeWord(hubOffset(), hub);
         if (fillContents) {
             if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) {
                 new_seqInit.inc();
                 explodeLoop();
                 for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
-                    storeWord(memory, 0, offset, Word.zero());
+                    memory.writeWord(offset, Word.zero());
                 }
             } else {
                 new_loopInit.inc();
                 for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
-                    storeWord(memory, 0, offset, Word.zero());
+                    memory.writeWord(offset, Word.zero());
                 }
             }
         }
@@ -210,13 +210,13 @@
      * Formats some allocated memory with an object header zeroes out the rest.
      */
     public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
-        storeWord(memory, 0, markOffset(), prototypeMarkWord);
-        storeInt(memory, 0, arrayLengthOffset(), length);
+        memory.writeWord(markOffset(), prototypeMarkWord);
+        memory.writeInt(arrayLengthOffset(), length);
         // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null
-        storeWord(memory, 0, hubOffset(), hub);
+        memory.writeWord(hubOffset(), hub);
         if (fillContents) {
             for (int offset = headerSize; offset < allocationSize; offset += wordSize()) {
-                storeWord(memory, 0, offset, Word.zero());
+                memory.writeWord(offset, Word.zero());
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -28,6 +28,7 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
+import com.oracle.graal.word.*;
 
 /**
  * Snippets for {@link java.lang.Object} methods.
@@ -37,7 +38,7 @@
     @MethodSubstitution(isStatic = false)
     public static Class<?> getClass(final Object thisObj) {
         Word hub = loadHub(thisObj);
-        return unsafeCast(hub.readFinalObject(classMirrorOffset()), Class.class, true, true);
+        return unsafeCast(hub.readFinalObject(Word.signed(classMirrorOffset())), Class.class, true, true);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -46,8 +47,8 @@
 
         // this code is independent from biased locking (although it does not look that way)
         final Word biasedLock = mark.and(biasedLockMaskInPlace());
-        if (biasedLock.toLong() == unlockedMask()) {
-            int hash = (int) (mark.toLong() >>> identityHashCodeShift());
+        if (biasedLock == Word.unsigned(unlockedMask())) {
+            int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue();
             if (hash != uninitializedIdentityHashCodeValue()) {
                 return hash;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -22,15 +22,15 @@
  */
 package com.oracle.graal.hotspot.snippets;
 
-import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
 
-import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * Snippets for {@link java.lang.System} methods.
@@ -38,8 +38,8 @@
 @ClassSubstitution(java.lang.System.class)
 public class SystemSnippets implements SnippetsInterface {
 
-    public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", false, Kind.Long);
-    public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", false, Kind.Long);
+    public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", false, long.class);
+    public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", false, long.class);
 
     public static long currentTimeMillis() {
         return callLong(JAVA_TIME_MILLIS);
@@ -58,8 +58,8 @@
 
         // this code is independent from biased locking (although it does not look that way)
         final Word biasedLock = mark.and(biasedLockMaskInPlace());
-        if (biasedLock.toLong() == unlockedMask()) {
-            int hash = (int) (mark.toLong() >>> identityHashCodeShift());
+        if (biasedLock == Word.unsigned(unlockedMask())) {
+            int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue();
             if (hash != uninitializedIdentityHashCodeValue()) {
                 return hash;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -27,6 +27,7 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
+import com.oracle.graal.word.*;
 
 /**
  * Snippets for {@link java.lang.Thread} methods.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Jan 04 12:08:11 2013 -0800
@@ -35,6 +35,7 @@
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Parameter;
 import com.oracle.graal.snippets.SnippetTemplate.Key;
+import com.oracle.graal.word.*;
 
 /**
  * Stub implementing the fast path for TLAB refill during instance class allocation.
@@ -78,14 +79,14 @@
         log(log, "newArray: element kind %d\n", elementKind);
         log(log, "newArray: array length %d\n", length);
         log(log, "newArray: array size %d\n", sizeInBytes);
-        log(log, "newArray: hub=%p\n", hub.toLong());
+        log(log, "newArray: hub=%p\n", hub);
 
         // check that array length is small enough for fast path.
         if (length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) {
             Word memory = refillAllocate(intArrayHub, sizeInBytes, log);
             if (memory != Word.zero()) {
-                log(log, "newArray: allocated new array at %p\n", memory.toLong());
-                formatArray(hub, sizeInBytes, length, headerSize, memory, Word.fromLong(arrayPrototypeMarkWord()), true);
+                log(log, "newArray: allocated new array at %p\n", memory);
+                formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true);
                 return verifyOop(memory.toObject());
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri Jan 04 12:08:11 2013 -0800
@@ -26,7 +26,6 @@
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
 import static com.oracle.graal.hotspot.snippets.NewObjectSnippets.*;
-import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -34,8 +33,11 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.snippets.*;
 import com.oracle.graal.snippets.*;
-import com.oracle.graal.snippets.Snippet.*;
+import com.oracle.graal.snippets.Snippet.ConstantParameter;
+import com.oracle.graal.snippets.Snippet.Fold;
+import com.oracle.graal.snippets.Snippet.Parameter;
 import com.oracle.graal.snippets.SnippetTemplate.Key;
+import com.oracle.graal.word.*;
 
 /**
  * Stub implementing the fast path for TLAB refill during instance class allocation.
@@ -74,10 +76,10 @@
                 Word memory = refillAllocate(intArrayHub, sizeInBytes, log);
                 if (memory != Word.zero()) {
                     Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
-                    storeWord(memory, 0, markOffset(), prototypeMarkWord);
-                    storeWord(memory, 0, hubOffset(), hub);
+                    memory.writeWord(markOffset(), prototypeMarkWord);
+                    memory.writeWord(hubOffset(), hub);
                     for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) {
-                        storeWord(memory, 0, offset, Word.zero());
+                        memory.writeWord(offset, Word.zero());
                     }
                     return verifyOop(memory.toObject());
                 }
@@ -96,7 +98,7 @@
      */
     static Word refillAllocate(Word intArrayHub, int sizeInBytes, boolean log) {
 
-        Word intArrayMarkWord = Word.fromLong(tlabIntArrayMarkWord());
+        Word intArrayMarkWord = Word.unsigned(tlabIntArrayMarkWord());
         int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords() * wordSize();
 
         Word thread = thread();
@@ -104,15 +106,14 @@
         Word end = thread.readWord(threadTlabEndOffset());
 
         // calculate amount of free space
-        Word tlabFreeSpaceInBytes = end.minus(top);
+        Word tlabFreeSpaceInBytes = end.subtract(top);
 
-        log(log, "refillTLAB: thread=%p\n", thread.toLong());
-        log(log, "refillTLAB: top=%p\n", top.toLong());
-        log(log, "refillTLAB: end=%p\n", end.toLong());
-        log(log, "refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes.toLong());
+        log(log, "refillTLAB: thread=%p\n", thread);
+        log(log, "refillTLAB: top=%p\n", top);
+        log(log, "refillTLAB: end=%p\n", end);
+        log(log, "refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes);
 
-        // a DIV or SHR operations on Words would be handy here...
-        Word tlabFreeSpaceInWords = Word.fromLong(tlabFreeSpaceInBytes.toLong() >>> log2WordSize());
+        Word tlabFreeSpaceInWords = tlabFreeSpaceInBytes.unsignedShiftRight(log2WordSize());
 
         // Retain TLAB and allocate object in shared space if
         // the amount free in the TLAB is too large to discard.
@@ -120,12 +121,12 @@
         if (tlabFreeSpaceInWords.belowOrEqual(refillWasteLimit)) {
             if (tlabStats()) {
                 // increment number of refills
-                storeInt(thread, 0, tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1);
-                log(log, "thread: %p -- number_of_refills %d\n", thread.toLong(), thread.readInt(tlabNumberOfRefillsOffset()));
+                thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1);
+                log(log, "thread: %p -- number_of_refills %d\n", thread, thread.readInt(tlabNumberOfRefillsOffset()));
                 // accumulate wastage
-                Word wastage = thread.readWord(tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords);
-                log(log, "thread: %p -- accumulated wastage %d\n", thread.toLong(), wastage.toLong());
-                storeWord(thread, 0, tlabFastRefillWasteOffset(), wastage);
+                Word wastage = thread.readWord(tlabFastRefillWasteOffset()).add(tlabFreeSpaceInWords);
+                log(log, "thread: %p -- accumulated wastage %d\n", thread, wastage);
+                thread.writeWord(tlabFastRefillWasteOffset(), wastage);
             }
 
             // if TLAB is currently allocated (top or end != null) then
@@ -133,26 +134,26 @@
             if (top != Word.zero()) {
                 int headerSize = arrayBaseOffset(Kind.Int);
                 // just like the HotSpot assembler stubs, assumes that tlabFreeSpaceInInts fits in an int
-                int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes.toLong() >>> 2;
+                int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes.rawValue() >>> 2;
                 int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts;
                 NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false);
 
                 Word allocated = thread.readWord(threadAllocatedBytesOffset());
-                allocated = allocated.plus(top.minus(thread.readWord(threadTlabStartOffset())));
-                storeWord(thread, 0, threadAllocatedBytesOffset(), allocated);
+                allocated = allocated.add(top.subtract(thread.readWord(threadTlabStartOffset())));
+                thread.writeWord(threadAllocatedBytesOffset(), allocated);
             }
 
             // refill the TLAB with an eden allocation
             Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset());
-            Word tlabRefillSizeInBytes = Word.fromLong(tlabRefillSizeInWords.toLong() * wordSize());
+            Word tlabRefillSizeInBytes = tlabRefillSizeInWords.multiply(wordSize());
             // allocate new TLAB, address returned in top
             top = edenAllocate(tlabRefillSizeInBytes, log);
             if (top != Word.zero()) {
-                storeWord(thread, 0, threadTlabStartOffset(), top);
-                storeWord(thread, 0, threadTlabTopOffset(), top);
+                thread.writeWord(threadTlabStartOffset(), top);
+                thread.writeWord(threadTlabTopOffset(), top);
 
-                end = top.plus(tlabRefillSizeInBytes.minus(alignmentReserveInBytes));
-                storeWord(thread, 0, threadTlabEndOffset(), end);
+                end = top.add(tlabRefillSizeInBytes.subtract(alignmentReserveInBytes));
+                thread.writeWord(threadTlabEndOffset(), end);
 
                 return allocate(sizeInBytes);
             } else {
@@ -160,15 +161,15 @@
             }
         } else {
             // Retain TLAB
-            Word newRefillWasteLimit = refillWasteLimit.plus(tlabRefillWasteIncrement());
-            storeWord(thread, 0, tlabRefillWasteLimitOffset(), newRefillWasteLimit);
-            log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.toLong());
+            Word newRefillWasteLimit = refillWasteLimit.add(tlabRefillWasteIncrement());
+            thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit);
+            log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit);
 
             if (tlabStats()) {
-                storeInt(thread, 0, tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1);
+                thread.writeInt(tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1);
             }
 
-            return edenAllocate(Word.fromInt(sizeInBytes), log);
+            return edenAllocate(Word.unsigned(sizeInBytes), log);
         }
     }
 
@@ -180,18 +181,18 @@
      * @return the allocated chunk or {@link Word#zero()} if allocation fails
      */
     static Word edenAllocate(Word sizeInBytes, boolean log) {
-        Word heapTopAddress = Word.fromLong(heapTopAddress());
-        Word heapEndAddress = Word.fromLong(heapEndAddress());
+        Word heapTopAddress = Word.unsigned(heapTopAddress());
+        Word heapEndAddress = Word.unsigned(heapEndAddress());
 
         while (true) {
             Word heapTop = heapTopAddress.readWord(0);
-            Word newHeapTop = heapTop.plus(sizeInBytes);
+            Word newHeapTop = heapTop.add(sizeInBytes);
             if (newHeapTop.belowOrEqual(heapTop)) {
                 return Word.zero();
             }
 
             Word heapEnd = heapEndAddress.readWord(0);
-            if (newHeapTop.above(heapEnd)) {
+            if (newHeapTop.aboveThan(heapEnd)) {
                 return Word.zero();
             }
 
@@ -211,11 +212,26 @@
             Log.printf(format, value);
         }
     }
+    static void log(boolean enabled, String format, WordBase value) {
+        if (enabled) {
+            Log.printf(format, value.rawValue());
+        }
+    }
     static void log(boolean enabled, String format, long v1, long v2) {
         if (enabled) {
             Log.printf(format, v1, v2);
         }
     }
+    static void log(boolean enabled, String format, Word v1, long v2) {
+        if (enabled) {
+            Log.printf(format, v1.rawValue(), v2);
+        }
+    }
+    static void log(boolean enabled, String format, Word v1, Word v2) {
+        if (enabled) {
+            Log.printf(format, v1.rawValue(), v2.rawValue());
+        }
+    }
     static void log(boolean enabled, String format, long v1, long v2, long v3) {
         if (enabled) {
             Log.printf(format, v1, v2, v3);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Jan 04 12:08:11 2013 -0800
@@ -54,8 +54,8 @@
  */
 public final class GraphBuilderPhase extends Phase {
 
-    public static final Descriptor CREATE_NULL_POINTER_EXCEPTION = new Descriptor("createNullPointerException", true, Kind.Object);
-    public static final Descriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new Descriptor("createOutOfBoundsException", true, Kind.Object, Kind.Int);
+    public static final Descriptor CREATE_NULL_POINTER_EXCEPTION = new Descriptor("createNullPointerException", true, Object.class);
+    public static final Descriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new Descriptor("createOutOfBoundsException", true, Object.class, int.class);
 
 
     /**
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Fri Jan 04 12:08:11 2013 -0800
@@ -54,11 +54,11 @@
         if (argsToBind != null) {
             Object receiver = isStatic(m.getModifiers()) ? null : this;
             Object[] args = argsWithReceiver(receiver, argsToBind);
-            Kind[] parameterKinds = signatureToKinds(runtime.lookupJavaMethod(m));
-            assert parameterKinds.length == args.length;
+            JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m));
+            assert parameterTypes.length == args.length;
             for (int i = 0; i < argsToBind.length; i++) {
                 LocalNode local = graph.getLocal(i);
-                Constant c = Constant.forBoxed(parameterKinds[i], argsToBind[i]);
+                Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]);
                 ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph);
                 local.replaceAtUsages(replacement);
             }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Fri Jan 04 12:08:11 2013 -0800
@@ -35,7 +35,7 @@
 
 public class AMD64Call {
 
-    public static final Descriptor DEBUG = new Descriptor("debug", false, Kind.Void);
+    public static final Descriptor DEBUG = new Descriptor("debug", false, void.class);
 
     @Opcode("CALL_DIRECT")
     public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -31,11 +31,11 @@
 public abstract class AbstractCallTargetNode extends CallTargetNode {
 
     private final Stamp returnStamp;
-    private final Kind[] signature;
+    private final JavaType[] signature;
     private final Object target;
     private final CallingConvention.Type callType;
 
-    public AbstractCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, Kind[] signature, Object target, CallingConvention.Type callType) {
+    public AbstractCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) {
         super(arguments);
         this.returnStamp = returnStamp;
         this.signature = signature;
@@ -48,7 +48,7 @@
         return returnStamp;
     }
 
-    public Kind[] signature() {
+    public JavaType[] signature() {
         return signature;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -30,7 +30,7 @@
 
 public class DirectCallTargetNode extends AbstractCallTargetNode {
 
-    public DirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, Kind[] signature, Object target, CallingConvention.Type callType) {
+    public DirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) {
         super(arguments, returnStamp, signature, target, callType);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -32,7 +32,7 @@
 
     @Input protected ValueNode computedAddress;
 
-    public IndirectCallTargetNode(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, Kind[] signature, Object target, CallingConvention.Type callType) {
+    public IndirectCallTargetNode(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) {
         super(arguments, returnStamp, signature, target, callType);
         this.computedAddress = computedAddress;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -34,7 +34,7 @@
  */
 public final class UnwindNode extends FixedNode implements LIRLowerable, Node.IterableNodeType {
 
-    public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, Kind.Void, Kind.Object);
+    public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, void.class, Object.class);
 
     @Input private ValueNode exception;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -50,6 +50,7 @@
         L2D(Long, Double),
         F2L(Float, Long),
         D2L(Double, Long),
+        UNSIGNED_I2L(Int, Long),
         MOV_I2F(Int, Float),
         MOV_L2D(Long, Double),
         MOV_F2I(Float, Int),
@@ -104,6 +105,7 @@
                 case L2D: return ConstantNode.forDouble(c.asLong(), graph());
                 case F2L: return ConstantNode.forLong((long) c.asFloat(), graph());
                 case D2L: return ConstantNode.forLong((long) c.asDouble(), graph());
+                case UNSIGNED_I2L: return ConstantNode.forLong(c.asInt() & 0xffffffffL, graph());
                 case MOV_I2F: return ConstantNode.forFloat(java.lang.Float.intBitsToFloat(c.asInt()), graph());
                 case MOV_L2D: return ConstantNode.forDouble(java.lang.Double.longBitsToDouble(c.asLong()), graph());
                 case MOV_F2I: return ConstantNode.forInt(java.lang.Float.floatToRawIntBits(c.asFloat()), graph());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.calc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo(shortName = "|/|")
+public final class UnsignedDivNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
+
+    public UnsignedDivNode(Kind kind, ValueNode x, ValueNode y) {
+        super(kind, x, y);
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (x().isConstant() && y().isConstant()) {
+            long yConst = y().asConstant().asLong();
+            if (yConst == 0) {
+                return this; // this will trap, cannot canonicalize
+            }
+            if (kind() == Kind.Int) {
+                return ConstantNode.forInt(UnsignedMath.divide(x().asConstant().asInt(), (int) yConst), graph());
+            } else {
+                assert kind() == Kind.Long;
+                return ConstantNode.forLong(UnsignedMath.divide(x().asConstant().asLong(), yConst), graph());
+            }
+        } else if (y().isConstant()) {
+            long c = y().asConstant().asLong();
+            if (c == 1) {
+                return x();
+            }
+            if (CodeUtil.isPowerOf2(c)) {
+                return graph().unique(new UnsignedRightShiftNode(kind(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph())));
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y())));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.calc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo(shortName = "|%|")
+public final class UnsignedRemNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
+
+    public UnsignedRemNode(Kind kind, ValueNode x, ValueNode y) {
+        super(kind, x, y);
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (x().isConstant() && y().isConstant()) {
+            long yConst = y().asConstant().asLong();
+            if (yConst == 0) {
+                return this; // this will trap, cannot canonicalize
+            }
+            if (kind() == Kind.Int) {
+                return ConstantNode.forInt(UnsignedMath.remainder(x().asConstant().asInt(), (int) yConst), graph());
+            } else {
+                assert kind() == Kind.Long;
+                return ConstantNode.forLong(UnsignedMath.remainder(x().asConstant().asLong(), yConst), graph());
+            }
+        } else if (y().isConstant()) {
+            long c = y().asConstant().asLong();
+            if (c == 1) {
+                return ConstantNode.forIntegerKind(kind(), 0, graph());
+            } else if (CodeUtil.isPowerOf2(c)) {
+                return graph().unique(new AndNode(kind(), x(), ConstantNode.forIntegerKind(kind(), c - 1, graph())));
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y())));
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,7 +35,7 @@
     private final Descriptor descriptor;
 
     public RuntimeCallNode(Descriptor descriptor, ValueNode... arguments) {
-        super(StampFactory.forKind(descriptor.getResultKind()), arguments);
+        super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())), arguments);
         this.descriptor = descriptor;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -23,8 +23,7 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.*;
-import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -34,7 +33,7 @@
  */
 public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable {
 
-    public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", true, Kind.Void, Kind.Object);
+    public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", true, void.class, Object.class);
 
     @Input private ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Fri Jan 04 12:08:11 2013 -0800
@@ -44,6 +44,11 @@
         this.nonNaN = nonNaN;
     }
 
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        return metaAccess.lookupJavaType(kind().toJavaClass());
+    }
+
     /**
      * The (inclusive) lower bound on the value described by this stamp.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Fri Jan 04 12:08:11 2013 -0800
@@ -42,6 +42,11 @@
     }
 
     @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        return metaAccess.lookupJavaType(kind().toJavaClass());
+    }
+
+    @Override
     public String toString() {
         return type.toString();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Fri Jan 04 12:08:11 2013 -0800
@@ -52,6 +52,11 @@
         this.mask = mask;
     }
 
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        return metaAccess.lookupJavaType(kind().toJavaClass());
+    }
+
     /**
      * The (inclusive) lower bound on the value described by this stamp.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Fri Jan 04 12:08:11 2013 -0800
@@ -43,6 +43,14 @@
     }
 
     @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        if (type != null) {
+            return type;
+        }
+        return metaAccess.lookupJavaType(Object.class);
+    }
+
+    @Override
     public boolean nonNull() {
         return nonNull;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Fri Jan 04 12:08:11 2013 -0800
@@ -40,6 +40,12 @@
         return kind;
     }
 
+    /**
+     * Returns the type of the stamp, guaranteed to be non-null. In some cases, this requires the lookup of class meta
+     * data, therefore the {@link MetaAccessProvider} is mandatory.
+     */
+    public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess);
+
     public boolean nonNull() {
         return false;
     }
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Fri Jan 04 12:08:11 2013 -0800
@@ -32,9 +32,8 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.snippets.Snippet.DefaultSnippetInliningPolicy;
 import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy;
+import com.oracle.graal.word.*;
 
 /**
  * Tests for the {@link Word} type.
@@ -57,37 +56,41 @@
     }
 
     @Test
-    public void test_arithmetic() {
-        long[] words = new long[] {Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE};
+    public void construction() {
+        long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
+                        Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
         for (long word : words) {
-            for (int addend = -1000; addend < 1000; addend++) {
-                test("plus_int", word, addend);
-                test("plus_int", word, -addend);
-                test("minus_int", word, addend);
-                test("minus_int", word, -addend);
-                test("plus_long", word, (long) addend);
-                test("plus_long", word, (long) -addend);
-                test("minus_long", word, (long) addend);
-                test("minus_long", word, (long) -addend);
+            test("unsigned_long", word);
+            test("unsigned_int", (int) word);
+            test("signed_long", word);
+            test("signed_int", (int) word);
+        }
+    }
 
-                test("and_int", word, addend);
-                test("and_int", word, -addend);
-                test("or_int", word, addend);
-                test("or_int", word, -addend);
-                test("and_long", word, (long) addend);
-                test("and_long", word, (long) -addend);
-                test("or_long", word, (long) addend);
-                test("or_long", word, (long) -addend);
-            }
+    @Test
+    public void test_arithmetic() {
+        long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
+                        Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
+        for (long word : words) {
+            test("unsigned_not", word);
+            test("signed_not", word);
             for (long addend : words) {
-                test("plus_int", word, (int) addend);
-                test("minus_int", word, (int) addend);
-                test("plus_int", word, -((int) addend));
-                test("minus_int", word, -((int) addend));
-                test("plus_long", word, addend);
-                test("minus_long", word, addend);
-                test("plus_long", word, -addend);
-                test("minus_long", word, -addend);
+                test("unsigned_plus_int", word, (int) addend);
+                test("unsigned_minus_int", word, (int) addend);
+                test("unsigned_plus_int", word, -((int) addend));
+                test("unsigned_minus_int", word, -((int) addend));
+                test("unsigned_plus_long", word, addend);
+                test("unsigned_minus_long", word, addend);
+                test("unsigned_plus_long", word, -addend);
+                test("unsigned_minus_long", word, -addend);
+                test("signed_plus_int", word, (int) addend);
+                test("signed_minus_int", word, (int) addend);
+                test("signed_plus_int", word, -((int) addend));
+                test("signed_minus_int", word, -((int) addend));
+                test("signed_plus_long", word, addend);
+                test("signed_minus_long", word, addend);
+                test("signed_plus_long", word, -addend);
+                test("signed_minus_long", word, -addend);
 
                 test("and_int", word, (int) addend);
                 test("or_int", word, (int) addend);
@@ -114,84 +117,113 @@
         }
     }
 
-    @Test
-    public void test_fromObject() {
-        inliningPolicy.set(new DefaultSnippetInliningPolicy(runtime(), new BoxingMethodPool(runtime())) {
-            @Override
-            public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
-                return super.shouldInline(method, caller) && !method.getName().equals("hashCode");
-            }
-        });
-        test("fromToObject", "object1", "object2");
-        test("fromToObject", "object1", "object1");
-        test("fromToObject", "object", null);
-        test("fromToObject", null, "object");
-        test("fromToObject", null, null);
-        inliningPolicy.set(null);
+    @Snippet
+    public static long unsigned_long(long word) {
+        return Word.unsigned(word).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_int(int word) {
+        return Word.unsigned(word).rawValue();
+    }
+
+    @Snippet
+    public static long signed_long(long word) {
+        return Word.signed(word).rawValue();
+    }
+
+    @Snippet
+    public static long signed_int(int word) {
+        return Word.signed(word).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_plus_int(long word, int addend) {
+        return Word.unsigned(word).add(addend).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_minus_int(long word, int addend) {
+        return Word.unsigned(word).subtract(addend).rawValue();
     }
 
     @Snippet
-    public static long plus_int(long word, int addend) {
-        return Word.fromLong(word).plus(addend).toLong();
+    public static long unsigned_plus_long(long word, long addend) {
+        return Word.unsigned(word).add(Word.unsigned(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_minus_long(long word, long addend) {
+        return Word.unsigned(word).subtract(Word.unsigned(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long signed_plus_int(long word, int addend) {
+        return Word.signed(word).add(addend).rawValue();
     }
 
     @Snippet
-    public static long minus_int(long word, int addend) {
-        return Word.fromLong(word).minus(addend).toLong();
+    public static long signed_minus_int(long word, int addend) {
+        return Word.signed(word).subtract(addend).rawValue();
+    }
+
+    @Snippet
+    public static long signed_plus_long(long word, long addend) {
+        return Word.signed(word).add(Word.signed(addend)).rawValue();
     }
 
     @Snippet
-    public static long plus_long(long word, long addend) {
-        return Word.fromLong(word).plus(addend).toLong();
+    public static long signed_minus_long(long word, long addend) {
+        return Word.signed(word).subtract(Word.signed(addend)).rawValue();
     }
 
     @Snippet
-    public static long minus_long(long word, long addend) {
-        return Word.fromLong(word).minus(addend).toLong();
+    public static long signed_not(long word) {
+        return Word.signed(word).not().rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_not(long word) {
+        return Word.unsigned(word).not().rawValue();
     }
 
     @Snippet
     public static boolean aboveOrEqual(long word1, long word2) {
-        return Word.fromLong(word1).aboveOrEqual(Word.fromLong(word2));
+        return Word.unsigned(word1).aboveOrEqual(Word.unsigned(word2));
     }
 
     @Snippet
     public static boolean above(long word1, long word2) {
-        return Word.fromLong(word1).above(Word.fromLong(word2));
+        return Word.unsigned(word1).aboveThan(Word.unsigned(word2));
     }
 
     @Snippet
     public static boolean belowOrEqual(long word1, long word2) {
-        return Word.fromLong(word1).belowOrEqual(Word.fromLong(word2));
+        return Word.unsigned(word1).belowOrEqual(Word.unsigned(word2));
     }
 
     @Snippet
     public static boolean below(long word1, long word2) {
-        return Word.fromLong(word1).below(Word.fromLong(word2));
-    }
-
-    @Snippet
-    public static int fromToObject(Object o1, Object o2) {
-        return Word.fromObject(o1).toObject().hashCode() + Word.fromObject(o2).toObject().hashCode();
+        return Word.unsigned(word1).belowThan(Word.unsigned(word2));
     }
 
     @Snippet
     public static long and_int(long word, int addend) {
-        return Word.fromLong(word).and(addend).toLong();
+        return Word.unsigned(word).and(addend).rawValue();
     }
 
     @Snippet
     public static long or_int(long word, int addend) {
-        return Word.fromLong(word).or(addend).toLong();
+        return Word.unsigned(word).or(addend).rawValue();
     }
 
     @Snippet
     public static long and_long(long word, long addend) {
-        return Word.fromLong(word).and(addend).toLong();
+        return Word.unsigned(word).and(Word.unsigned(addend)).rawValue();
     }
 
     @Snippet
     public static long or_long(long word, long addend) {
-        return Word.fromLong(word).or(addend).toLong();
+        return Word.unsigned(word).or(Word.unsigned(addend)).rawValue();
     }
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java	Fri Jan 04 12:08:11 2013 -0800
@@ -37,9 +37,9 @@
  */
 public final class Log {
 
-    public static final Descriptor LOG_PRIMITIVE = new Descriptor("logPrimitive", false, Kind.Void, Kind.Int, Kind.Long, Kind.Boolean);
-    public static final Descriptor LOG_OBJECT = new Descriptor("logObject", false, Kind.Void, Kind.Object, Kind.Int);
-    public static final Descriptor LOG_PRINTF = new Descriptor("logPrintf", false, Kind.Void, Kind.Object, Kind.Long, Kind.Long, Kind.Long);
+    public static final Descriptor LOG_PRIMITIVE = new Descriptor("logPrimitive", false, void.class, int.class, long.class, boolean.class);
+    public static final Descriptor LOG_OBJECT = new Descriptor("logObject", false, void.class, Object.class, int.class);
+    public static final Descriptor LOG_PRINTF = new Descriptor("logPrintf", false, void.class, Object.class, long.class, long.class, long.class);
 
     // Note: Must be kept in sync with constants in c1_Runtime1.hpp
     private static final int LOG_OBJECT_NEWLINE = 0x01;
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java	Fri Jan 04 12:08:11 2013 -0800
@@ -23,7 +23,6 @@
 package com.oracle.graal.snippets;
 
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.extended.*;
@@ -84,9 +83,9 @@
         }
     }
 
-    public static final Descriptor ARITHMETIC_SIN = new Descriptor("arithmeticSin", false, Kind.Double, Kind.Double);
-    public static final Descriptor ARITHMETIC_COS = new Descriptor("arithmeticCos", false, Kind.Double, Kind.Double);
-    public static final Descriptor ARITHMETIC_TAN = new Descriptor("arithmeticTan", false, Kind.Double, Kind.Double);
+    public static final Descriptor ARITHMETIC_SIN = new Descriptor("arithmeticSin", false, double.class, double.class);
+    public static final Descriptor ARITHMETIC_COS = new Descriptor("arithmeticCos", false, double.class, double.class);
+    public static final Descriptor ARITHMETIC_TAN = new Descriptor("arithmeticTan", false, double.class, double.class);
 
     @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true)
     public static native double callDouble(@ConstantNodeParameter Descriptor descriptor, double value);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Fri Jan 04 12:08:11 2013 -0800
@@ -29,8 +29,8 @@
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.Word.Operation;
 import com.oracle.graal.snippets.nodes.*;
+import com.oracle.graal.word.*;
 
 /**
  * A snippet is a Graal graph expressed as a Java source method. Graal snippets can be used for:
@@ -95,7 +95,7 @@
                     return false;
                 }
             }
-            if (method.getAnnotation(Operation.class) != null) {
+            if (method.getAnnotation(Word.Operation.class) != null) {
                 return false;
             }
             if (pool.isSpecialMethod(method)) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Fri Jan 04 12:08:11 2013 -0800
@@ -35,11 +35,13 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
 import com.oracle.graal.snippets.Snippet.DefaultSnippetInliningPolicy;
 import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy;
+import com.oracle.graal.word.phases.*;
 
 /**
  * Utility for snippet {@linkplain #install(Class) installation}.
@@ -191,6 +193,7 @@
     }
 
     private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
+        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method;
         final StructuredGraph graph = new StructuredGraph(method);
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
         GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
@@ -198,19 +201,19 @@
 
         Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName());
 
-        new SnippetVerificationPhase(runtime).apply(graph);
+        new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
 
         new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
 
         for (Invoke invoke : graph.getInvokes()) {
             MethodCallTargetNode callTarget = invoke.methodCallTarget();
             ResolvedJavaMethod callee = callTarget.targetMethod();
-            if (policy.shouldInline(callee, method)) {
+            if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) {
                 StructuredGraph targetGraph = parseGraph(callee, policy);
                 InliningUtil.inline(invoke, targetGraph, true);
                 Debug.dump(graph, "after inlining %s", callee);
                 if (GraalOptions.OptCanonicalizer) {
-                    new WordTypeRewriterPhase(target.wordKind).apply(graph);
+                    new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
                     new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
                 }
             }
@@ -218,7 +221,7 @@
 
         new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
 
-        new WordTypeRewriterPhase(target.wordKind).apply(graph);
+        new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
 
         new DeadCodeEliminationPhase().apply(graph);
         if (GraalOptions.OptCanonicalizer) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Fri Jan 04 12:08:11 2013 -0800
@@ -44,6 +44,8 @@
 import com.oracle.graal.snippets.Snippet.Varargs;
 import com.oracle.graal.snippets.Snippet.VarargsParameter;
 import com.oracle.graal.snippets.nodes.*;
+import com.oracle.graal.word.*;
+import com.oracle.graal.word.phases.*;
 
 /**
  * A snippet template is a graph created by parsing a snippet method and then
@@ -239,7 +241,7 @@
         replacements.put(snippetGraph.start(), snippetCopy.start());
 
         int parameterCount = signature.getParameterCount(false);
-        assert checkTemplate(key, parameterCount, method, signature);
+        assert checkTemplate(runtime, key, parameterCount, method, signature);
 
         Parameter[] parameterAnnotations = new Parameter[parameterCount];
         VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount];
@@ -278,7 +280,7 @@
         if (!replacements.isEmpty()) {
             // Do deferred intrinsification of node intrinsics
             new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy);
-            new WordTypeRewriterPhase(target.wordKind).apply(snippetCopy);
+            new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy);
 
             new CanonicalizerPhase(null, runtime, assumptions, 0).apply(snippetCopy);
         }
@@ -406,9 +408,9 @@
         return true;
     }
 
-    private static boolean checkConstantArgument(final ResolvedJavaMethod method, Signature signature, int i, String name, Object arg, Kind kind) {
+    private static boolean checkConstantArgument(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Object arg, Kind kind) {
         ResolvedJavaType type = signature.getParameterType(i, method.getDeclaringClass()).resolve(method.getDeclaringClass());
-        if (WordTypeRewriterPhase.isWord(type)) {
+        if (runtime.lookupJavaType(WordBase.class).isAssignableFrom(type)) {
             assert arg instanceof Constant : method + ": word constant parameters must be passed boxed in a Constant value: " + arg;
             return true;
         }
@@ -487,14 +489,22 @@
                 }
             } else if (parameter instanceof LocalNode[]) {
                 LocalNode[] locals = (LocalNode[]) parameter;
-                Object array = argument;
-                assert array != null && array.getClass().isArray();
                 int length = locals.length;
-                assert Array.getLength(array) == length : length + " != " + Array.getLength(array);
+                List list = null;
+                Object array = null;
+                if (argument instanceof List) {
+                    list = (List) argument;
+                    assert list.size() == length : length + " != " + list.size();
+                } else {
+                    array = argument;
+                    assert array != null && array.getClass().isArray();
+                    assert Array.getLength(array) == length : length + " != " + Array.getLength(array);
+                }
+
                 for (int j = 0; j < length; j++) {
                     LocalNode local = locals[j];
                     assert local != null;
-                    Object value = Array.get(array, j);
+                    Object value = list != null ? list.get(j) : Array.get(array, j);
                     if (value instanceof ValueNode) {
                         replacements.put(local, (ValueNode) value);
                     } else {
@@ -696,7 +706,7 @@
         return buf.append(')').toString();
     }
 
-    private static boolean checkTemplate(SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) {
+    private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) {
         Set<String> expected = new HashSet<>();
         for (int i = 0; i < parameterCount; i++) {
             ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
@@ -708,7 +718,7 @@
                 expected.add(name);
                 Kind kind = signature.getParameterKind(i);
                 assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key;
-                assert checkConstantArgument(method, signature, i, c.value(), key.get(name), kind);
+                assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind);
             } else if (vp != null) {
                 assert p == null;
                 String name = vp.value();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java	Wed Jan 02 18:52:33 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2011, 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.snippets;
-
-import static com.oracle.graal.snippets.WordTypeRewriterPhase.*;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.snippets.Word.*;
-
-/**
- * Verifies invariants that must hold for snippet code above and beyond normal
- * bytecode verification.
- */
-public class SnippetVerificationPhase extends Phase {
-
-    private final MetaAccessProvider metaAccess;
-
-    public SnippetVerificationPhase(MetaAccessProvider metaAccess) {
-        this.metaAccess = metaAccess;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        ResolvedJavaType wordType = metaAccess.lookupJavaType(Word.class);
-
-        for (ValueNode node : graph.getNodes().filter(ValueNode.class)) {
-            for (Node usage : node.usages()) {
-                if (usage instanceof AccessMonitorNode) {
-                    verify(!isWord(node), node, usage, "word value has no monitor");
-                } else if (usage instanceof LoadFieldNode) {
-                    verify(!isWord(node) || ((LoadFieldNode) usage).object() != node, node, usage, "cannot load from word value");
-                } else if (usage instanceof StoreFieldNode) {
-                    verify(!isWord(node) || ((StoreFieldNode) usage).object() != node, node, usage, "cannot store to word value");
-                } else if (usage instanceof CheckCastNode) {
-                    verify(!isWord(node), node, usage, "word value cannot be cast");
-                    verify(!isWord(((CheckCastNode) usage).type()), node, usage, "cannot cast to word value");
-                } else if (usage instanceof LoadIndexedNode) {
-                    verify(!isWord(node) || ((LoadIndexedNode) usage).array() != node, node, usage, "cannot load from word value");
-                    verify(!isWord(node) || ((LoadIndexedNode) usage).index() != node, node, usage, "cannot use word value as index");
-                } else if (usage instanceof StoreIndexedNode) {
-                    verify(!isWord(node) || ((StoreIndexedNode) usage).array() != node, node, usage, "cannot store to word value");
-                    verify(!isWord(node) || ((StoreIndexedNode) usage).index() != node, node, usage, "cannot use word value as index");
-                    verify(!isWord(node) || ((StoreIndexedNode) usage).value() != node, node, usage, "cannot store word value to array");
-                } else if (usage instanceof MethodCallTargetNode) {
-                    MethodCallTargetNode callTarget = (MethodCallTargetNode) usage;
-                    ResolvedJavaMethod method = callTarget.targetMethod();
-                    if (method.getAnnotation(NodeIntrinsic.class) == null) {
-                        Invoke invoke = (Invoke) callTarget.usages().first();
-                        NodeInputList<ValueNode> arguments = callTarget.arguments();
-                        boolean isStatic = Modifier.isStatic(method.getModifiers());
-                        int argc = 0;
-                        if (!isStatic) {
-                            ValueNode receiver = arguments.get(argc);
-                            if (receiver == node && isWord(node)) {
-                                Operation operation = method.getAnnotation(Word.Operation.class);
-                                verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + method);
-                            }
-                            argc++;
-                        }
-                        Signature signature = method.getSignature();
-                        for (int i = 0; i < signature.getParameterCount(false); i++) {
-                            ValueNode argument = arguments.get(argc);
-                            if (argument == node) {
-                                ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass());
-                                verify(type.equals(wordType) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa");
-                            }
-                            argc++;
-                        }
-                    }
-                } else if (usage instanceof ObjectEqualsNode) {
-                    ObjectEqualsNode compare = (ObjectEqualsNode) usage;
-                    if (compare.x() == node || compare.y() == node) {
-                        verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and non-word type in use of '==' or '!='");
-                    }
-                } else if (usage instanceof ArrayLengthNode) {
-                    verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value");
-                } else if (usage instanceof PhiNode) {
-                    if (!(node instanceof MergeNode)) {
-                        PhiNode phi = (PhiNode) usage;
-                        for (ValueNode input : phi.values()) {
-                            verify(isWord(node) == isWord(input), node, input, "cannot merge word and non-word values");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private static void verify(boolean condition, Node node, Node usage, String message) {
-        if (!condition) {
-            error(node, usage, message);
-        }
-    }
-
-    private static void error(Node node, Node usage, String message) {
-        throw new GraalInternalError(String.format("Snippet verification error: %s" +
-                        "%n   node: %s (%s)" +
-                        "%n  usage: %s (%s)", message, node, sourceLocation(node), usage, sourceLocation(usage)));
-    }
-
-    private static String sourceLocation(Node n) {
-        if (n instanceof PhiNode) {
-            StringBuilder buf = new StringBuilder();
-            for (Node usage : n.usages()) {
-                String loc = sourceLocation(usage);
-                if (!loc.equals("<unknown>")) {
-                    if (buf.length() != 0) {
-                        buf.append(", ");
-                    }
-                    buf.append(loc);
-                }
-            }
-            return buf.toString();
-        } else {
-            String loc = GraphUtil.approxSourceLocation(n);
-            return loc == null ? "<unknown>" : loc;
-        }
-    }
-}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java	Fri Jan 04 12:08:11 2013 -0800
@@ -26,6 +26,8 @@
 import static com.oracle.graal.nodes.calc.Condition.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.calc.*;
 
 /**
  * Snippets for {@link UnsignedMath}.
@@ -82,4 +84,44 @@
     public static boolean belowOrEqual(long a, long b) {
         return !materialize(BT, b, a);
     }
+
+    /**
+     * Unsigned division for two numbers.
+     */
+    public static int divide(int a, int b) {
+        return unsignedDivide(Kind.Int, a, b);
+    }
+
+    /**
+     * Unsigned remainder for two numbers.
+     */
+    public static int remainder(int a, int b) {
+        return unsignedRemainder(Kind.Int, a, b);
+    }
+
+    /**
+     * Unsigned division for two numbers.
+     */
+    public static long divide(long a, long b) {
+        return unsignedDivide(Kind.Long, a, b);
+    }
+
+    /**
+     * Unsigned remainder for two numbers.
+     */
+    public static long remainder(long a, long b) {
+        return unsignedRemainder(Kind.Long, a, b);
+    }
+
+    @NodeIntrinsic(UnsignedDivNode.class)
+    private static native int unsignedDivide(@ConstantNodeParameter Kind kind, int a, int b);
+
+    @NodeIntrinsic(UnsignedDivNode.class)
+    private static native long unsignedDivide(@ConstantNodeParameter Kind kind, long a, long b);
+
+    @NodeIntrinsic(UnsignedRemNode.class)
+    private static native int unsignedRemainder(@ConstantNodeParameter Kind kind, int a, int b);
+
+    @NodeIntrinsic(UnsignedRemNode.class)
+    private static native long unsignedRemainder(@ConstantNodeParameter Kind kind, long a, long b);
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java	Wed Jan 02 18:52:33 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +0,0 @@
-/*
- * 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.snippets;
-
-import static com.oracle.graal.snippets.Word.Opcode.*;
-
-import java.lang.annotation.*;
-
-//JaCoCo Exclude
-
-/**
- * Special type for use in snippets to represent machine word sized data.
- */
-public final class Word {
-
-    /**
-     * Links a method to a canonical operation represented by an {@link Opcode} value.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.METHOD)
-    public @interface Operation {
-        Opcode value();
-    }
-
-    /**
-     * The canonical {@link Operation} represented by a method in the {@link Word} class.
-     */
-    public enum Opcode {
-        ZERO,
-        W2A,
-        A2W,
-        L2W,
-        I2W,
-        W2L,
-        W2I,
-        PLUS,
-        MINUS,
-        OR,
-        AND,
-        XOR,
-        READ_INT,
-        READ_WORD,
-        READ_OBJECT,
-        READ_FINAL_OBJECT,
-        BELOW,
-        BELOW_EQUAL,
-        ABOVE,
-        ABOVE_EQUAL;
-    }
-
-    private Word(long value, Object object) {
-        assert object == null || value == 0L;
-        this.value = value;
-        this.object = object;
-    }
-
-    private final long value;
-    private final Object object;
-
-    @Operation(ZERO)
-    public static Word zero() {
-        return new Word(0L, null);
-    }
-
-    @Operation(W2A)
-    public Object toObject() {
-        assert value == 0L;
-        return object;
-    }
-
-    @Operation(A2W)
-    public static Word fromObject(Object value) {
-        return new Word(0L, value);
-    }
-
-    @Operation(L2W)
-    public static Word fromLong(long value) {
-        return new Word(value, null);
-    }
-
-    @Operation(I2W)
-    public static Word fromInt(int value) {
-        return new Word(value, null);
-    }
-
-    @Operation(W2I)
-    public int toInt() {
-        assert object == null;
-        return (int) value;
-    }
-
-    @Operation(W2L)
-    public long toLong() {
-        assert object == null;
-        return value;
-    }
-
-    @Operation(ABOVE)
-    public boolean above(Word other) {
-        assert object == null;
-        assert other.object == null;
-        long a = value;
-        long b = other.value;
-        return (a > b) ^ ((a < 0) != (b < 0));
-    }
-
-    @Operation(ABOVE_EQUAL)
-    public boolean aboveOrEqual(Word other) {
-        assert object == null;
-        assert other.object == null;
-        long a = value;
-        long b = other.value;
-        return (a >= b) ^ ((a < 0) != (b < 0));
-    }
-
-    @Operation(BELOW)
-    public boolean below(Word other) {
-        assert object == null;
-        assert other.object == null;
-        long a = value;
-        long b = other.value;
-        return (a < b) ^ ((a < 0) != (b < 0));
-    }
-
-    @Operation(BELOW_EQUAL)
-    public boolean belowOrEqual(Word other) {
-        assert object == null;
-        assert other.object == null;
-        long a = value;
-        long b = other.value;
-        return (a <= b) ^ ((a < 0) != (b < 0));
-    }
-
-    @Operation(PLUS)
-    public Word plus(int addend) {
-        assert object == null;
-        return new Word(value + addend, null);
-    }
-
-    @Operation(PLUS)
-    public Word plus(long addend) {
-        assert object == null;
-        return new Word(value + addend, null);
-    }
-
-    @Operation(PLUS)
-    public Word plus(Word addend) {
-        assert object == null;
-        return new Word(value + addend.value, null);
-    }
-
-    @Operation(MINUS)
-    public Word minus(int addend) {
-        assert object == null;
-        return new Word(value - addend, null);
-    }
-
-    @Operation(MINUS)
-    public Word minus(long addend) {
-        assert object == null;
-        return new Word(value - addend, null);
-    }
-
-    @Operation(MINUS)
-    public Word minus(Word addend) {
-        assert object == null;
-        return new Word(value - addend.value, null);
-    }
-
-    @Operation(OR)
-    public Word or(int other) {
-        assert object == null;
-        return new Word(value | other, null);
-    }
-
-    @Operation(OR)
-    public Word or(long other) {
-        assert object == null;
-        return new Word(value | other, null);
-    }
-
-    @Operation(OR)
-    public Word or(Word other) {
-        assert object == null;
-        return new Word(value | other.value, null);
-    }
-
-    @Operation(AND)
-    public Word and(int other) {
-        assert object == null;
-        return new Word(value & other, null);
-    }
-
-    @Operation(AND)
-    public Word and(long other) {
-        assert object == null;
-        return new Word(value & other, null);
-    }
-
-    @Operation(AND)
-    public Word and(Word other) {
-        assert object == null;
-        return new Word(value & other.value, null);
-    }
-
-    @Operation(XOR)
-    public Word xor(int other) {
-        assert object == null;
-        return new Word(value | other, null);
-    }
-
-    @Operation(XOR)
-    public Word xor(long other) {
-        assert object == null;
-        return new Word(value | other, null);
-    }
-
-    @Operation(XOR)
-    public Word xor(Word other) {
-        assert object == null;
-        return new Word(value | other.value, null);
-    }
-
-    @Operation(READ_INT)
-    public native int readInt(int offset);
-
-    @Operation(READ_WORD)
-    public native Word readWord(int offset);
-
-    @Operation(READ_OBJECT)
-    public native Object readObject(int offset);
-
-    /**
-     * Reads an object value from a location that is guaranteed not be to modified after this read.
-     *
-     * @param offset the offset from this base address of the location to be read
-     */
-    @Operation(READ_FINAL_OBJECT)
-    public native Object readFinalObject(int offset);
-}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Wed Jan 02 18:52:33 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-/*
- * 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.snippets;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.ConvertNode.Op;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.util.*;
-import com.oracle.graal.snippets.Word.Opcode;
-import com.oracle.graal.snippets.Word.Operation;
-
-/**
- * Transforms all uses of the {@link Word} class into unsigned
- * operations on {@code int} or {@code long} values, depending
- * on the word kind of the underlying platform.
- */
-public class WordTypeRewriterPhase extends Phase {
-
-    public static final String WordClassName = MetaUtil.toInternalName(Word.class.getName());
-
-    private final Kind wordKind;
-
-    public WordTypeRewriterPhase(Kind wordKind) {
-        this.wordKind = wordKind;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (Node n : GraphOrder.forwardGraph(graph)) {
-            if (n instanceof ValueNode) {
-                ValueNode valueNode = (ValueNode) n;
-                if (isWord(valueNode)) {
-                    changeToWord(valueNode);
-                }
-            }
-        }
-
-        // Remove unnecessary/redundant unsafe casts
-        for (UnsafeCastNode unsafeCastNode : graph.getNodes().filter(UnsafeCastNode.class).snapshot()) {
-            if (!unsafeCastNode.isDeleted() && unsafeCastNode.object().stamp() == unsafeCastNode.stamp()) {
-                graph.replaceFloating(unsafeCastNode, unsafeCastNode.object());
-            }
-        }
-
-        // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words
-        for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) {
-            ValueNode x = objectEqualsNode.x();
-            ValueNode y = objectEqualsNode.y();
-            if (x.kind() == wordKind || y.kind() == wordKind) {
-                assert x.kind() == wordKind;
-                assert y.kind() == wordKind;
-                graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y)));
-            }
-        }
-
-        // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words
-        for (LoadIndexedNode load : graph.getNodes().filter(LoadIndexedNode.class).snapshot()) {
-            if (isWord(load)) {
-                load.setStamp(StampFactory.forKind(wordKind));
-            }
-        }
-
-        for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) {
-            ResolvedJavaMethod targetMethod = callTargetNode.targetMethod();
-            Operation operation = targetMethod.getAnnotation(Word.Operation.class);
-            if (operation != null) {
-                NodeInputList<ValueNode> arguments = callTargetNode.arguments();
-                Invoke invoke = (Invoke) callTargetNode.usages().first();
-                assert invoke != null : callTargetNode.targetMethod();
-
-                Opcode opcode = operation.value();
-                switch (opcode) {
-                    case ZERO: {
-                        assert arguments.size() == 0;
-                        replace(invoke, wordKind == Kind.Long ? ConstantNode.forLong(0L, graph) : ConstantNode.forInt(0, graph));
-                        break;
-                    }
-
-                    case ABOVE: {
-                        assert arguments.size() == 2;
-                        replace(invoke, compare(Condition.AT, graph, arguments.first(), arguments.last()));
-                        break;
-                    }
-
-                    case ABOVE_EQUAL: {
-                        assert arguments.size() == 2;
-                        replace(invoke, compare(Condition.AE, graph, arguments.first(), arguments.last()));
-                        break;
-                    }
-
-                    case BELOW: {
-                        assert arguments.size() == 2;
-                        replace(invoke, compare(Condition.BT, graph, arguments.first(), arguments.last()));
-                        break;
-                    }
-
-                    case BELOW_EQUAL: {
-                        assert arguments.size() == 2;
-                        replace(invoke, compare(Condition.BE, graph, arguments.first(), arguments.last()));
-                        break;
-                    }
-
-                    case PLUS: {
-                        ValueNode addend = asWordKind(graph, arguments.last());
-                        IntegerAddNode op = graph.unique(new IntegerAddNode(wordKind, arguments.first(), addend));
-                        replace(invoke, op);
-                        break;
-                    }
-
-                    case MINUS: {
-                        ValueNode addend = asWordKind(graph, arguments.last());
-                        IntegerSubNode op = graph.unique(new IntegerSubNode(wordKind, arguments.first(), addend));
-                        replace(invoke, op);
-                        break;
-                    }
-
-                    case AND: {
-                        ValueNode operand = asWordKind(graph, arguments.last());
-                        AndNode op = graph.unique(new AndNode(wordKind, arguments.first(), operand));
-                        replace(invoke, op);
-                        break;
-                    }
-
-                    case OR: {
-                        ValueNode operand = asWordKind(graph, arguments.last());
-                        OrNode op = graph.unique(new OrNode(wordKind, arguments.first(), operand));
-                        replace(invoke, op);
-                        break;
-                    }
-
-                    case XOR: {
-                        ValueNode operand = asWordKind(graph, arguments.last());
-                        XorNode op = graph.unique(new XorNode(wordKind, arguments.first(), operand));
-                        replace(invoke, op);
-                        break;
-                    }
-
-                    case W2A: {
-                        assert arguments.size() == 1;
-                        ValueNode value = arguments.first();
-                        UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, ((ValueNode) invoke).stamp()));
-                        replace(invoke, cast);
-                        break;
-                    }
-
-                    case W2I: {
-                        assert arguments.size() == 1;
-                        ValueNode value = arguments.first();
-                        ValueNode intValue = fromWordKindTo(graph, value, Kind.Int);
-                        replace(invoke, intValue);
-                        break;
-                    }
-
-                    case W2L: {
-                        assert arguments.size() == 1;
-                        ValueNode value = arguments.first();
-                        ValueNode longValue = fromWordKindTo(graph, value, Kind.Long);
-                        replace(invoke, longValue);
-                        break;
-                    }
-
-                    case A2W: {
-                        assert arguments.size() == 1;
-                        ValueNode value = arguments.first();
-                        assert value.kind() == Kind.Object : value + ", " + targetMethod;
-                        UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, StampFactory.forKind(wordKind)));
-                        replace(invoke, cast);
-                        break;
-                    }
-
-                    case L2W: {
-                        assert arguments.size() == 1;
-                        ValueNode value = arguments.first();
-                        assert value.kind() == Kind.Long;
-                        ValueNode wordValue = asWordKind(graph, value);
-                        replace(invoke, wordValue);
-                        break;
-                    }
-
-                    case I2W: {
-                        assert arguments.size() == 1;
-                        ValueNode value = arguments.first();
-                        assert value.kind() == Kind.Int;
-                        replace(invoke, asWordKind(graph, value));
-                        break;
-                    }
-
-                    case READ_INT:
-                    case READ_OBJECT:
-                    case READ_WORD: {
-                        replaceRead(graph, arguments, invoke, LocationNode.ANY_LOCATION);
-                        break;
-                    }
-
-                    case READ_FINAL_OBJECT: {
-                        replaceRead(graph, arguments, invoke, LocationNode.FINAL_LOCATION);
-                        break;
-                    }
-
-                    default: {
-                        throw new GraalInternalError("Unknown opcode: %s", opcode);
-                    }
-                }
-            }
-        }
-    }
-
-    protected void replaceRead(StructuredGraph graph, NodeInputList<ValueNode> arguments, Invoke invoke, Object locationIdentity) {
-        assert arguments.size() == 2;
-        ValueNode base = arguments.first();
-        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, invoke.node().kind(), 0, arguments.last(), graph, false);
-        ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp()));
-        graph.addBeforeFixed(invoke.node(), read);
-        // The read must not float outside its block otherwise it may float above an explicit zero check on its base address
-        read.dependencies().add(BeginNode.prevBegin(invoke.node()));
-        replace(invoke, read);
-    }
-
-    protected void replace(Invoke invoke, ValueNode value) {
-        FixedNode next = invoke.next();
-        invoke.setNext(null);
-        invoke.node().replaceAtPredecessor(next);
-        invoke.node().replaceAtUsages(value);
-        GraphUtil.killCFG(invoke.node());
-    }
-
-    /**
-     * Creates comparison node for a given condition and two input values.
-     */
-    private ValueNode compare(Condition condition, StructuredGraph graph, ValueNode left, ValueNode right) {
-        assert condition.isUnsigned() : condition;
-        assert left.kind() == wordKind;
-        assert right.kind() == wordKind;
-
-        // mirroring gets the condition into canonical form
-        boolean mirror = condition.canonicalMirror();
-
-        ValueNode a = mirror ? right : left;
-        ValueNode b = mirror ? left : right;
-
-        MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b)));
-
-        ValueNode op;
-        if (condition.canonicalNegate()) {
-            op = (ValueNode) materialize.negate();
-        } else {
-            op = materialize;
-        }
-        return op;
-    }
-
-    /**
-     * Adds a node if necessary to convert a given value into the word kind.
-     *
-     * @return the node for {@code value} producing a value of word kind
-     */
-    private ValueNode asWordKind(StructuredGraph graph, ValueNode value) {
-        if (value.kind() != wordKind) {
-            Op op;
-            if (wordKind == Kind.Long) {
-                assert value.kind().getStackKind() == Kind.Int;
-                op = Op.I2L;
-            } else {
-                assert wordKind.getStackKind() == Kind.Int;
-                assert value.kind() == Kind.Long;
-                op = Op.L2I;
-            }
-            return graph.unique(new ConvertNode(op, value));
-        }
-        return value;
-    }
-
-    private static ValueNode fromWordKindTo(StructuredGraph graph, ValueNode value, Kind to) {
-        Kind from = value.kind();
-        if (from != to) {
-            Op op;
-            if (from == Kind.Long) {
-                op = Op.L2I;
-            } else {
-                assert from.getStackKind() == Kind.Int;
-                op = Op.I2L;
-            }
-            return graph.unique(new ConvertNode(op, value));
-        }
-        return value;
-    }
-
-    public static boolean isWord(ValueNode node) {
-        node.inferStamp();
-        if (node.stamp() == StampFactory.forWord()) {
-            return true;
-        }
-        if (node instanceof LoadIndexedNode) {
-            return isWord(((LoadIndexedNode) node).array().objectStamp().type().getComponentType());
-        }
-        if (node.kind() == Kind.Object) {
-            return isWord(node.objectStamp().type());
-        }
-        return false;
-    }
-
-    public static boolean isWord(ResolvedJavaType type) {
-        if (type != null && type.getName().equals(WordClassName)) {
-            return true;
-        }
-        return false;
-    }
-
-    private void changeToWord(ValueNode valueNode) {
-        assert !(valueNode instanceof ConstantNode) : "boxed Word constants should not appear in a snippet graph: " + valueNode + ", stamp: " + valueNode.stamp();
-        valueNode.setStamp(StampFactory.forKind(wordKind));
-    }
-}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java	Wed Jan 02 18:52:33 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java	Fri Jan 04 12:08:11 2013 -0800
@@ -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.graal.snippets.*;
+import com.oracle.graal.word.*;
 
 /**
  * A special purpose store node that differs from {@link UnsafeStoreNode} in that
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2012, 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.word;
+
+public interface Pointer extends Unsigned {
+
+    /**
+     * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type checks are performed.
+     * The caller must ensure that the Pointer contains a valid Java object that can i.e., processed by the garbage
+     * collector.
+     *
+     * @return this Pointer cast to Object.
+     */
+    Object toObject();
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    byte readByte(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    char readChar(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    short readShort(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    int readInt(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    long readLong(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    float readFloat(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    double readDouble(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Word readWord(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Object readObject(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    byte readByte(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    char readChar(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    short readShort(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    int readInt(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    long readLong(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    float readFloat(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    double readDouble(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Word readWord(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Object readObject(int offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    byte readFinalByte(WordBase offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    char readFinalChar(WordBase offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    short readFinalShort(WordBase offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    int readFinalInt(WordBase offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    long readFinalLong(WordBase offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    float readFinalFloat(WordBase offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    double readFinalDouble(WordBase offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Word readFinalWord(WordBase offset);
+
+    /**
+     * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore
+     * eliminate memory accesses more aggressively. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Object readFinalObject(WordBase offset);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeByte(WordBase offset, byte val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeChar(WordBase offset, char val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeShort(WordBase offset, Short val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeInt(WordBase offset, int val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeLong(WordBase offset, long val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeFloat(WordBase offset, float val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeDouble(WordBase offset, double val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeWord(WordBase offset, WordBase val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. <br>
+     * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the
+     * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned
+     * value is never used).
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeObject(WordBase offset, Object val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeByte(int offset, byte val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeChar(int offset, char val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeShort(int offset, short val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeInt(int offset, int val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeLong(int offset, long val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeFloat(int offset, float val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeDouble(int offset, double val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeWord(int offset, WordBase val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeObject(int offset, Object val);
+
+    // Math functions that are defined in Unsigned, but known to preserve the pointer-characteristics.
+    // It is therefore safe that they return a static type of Pointer instead of Unsigned.
+
+    @Override
+    Pointer add(Unsigned val);
+
+    @Override
+    Pointer add(int val);
+
+    @Override
+    Pointer subtract(Unsigned val);
+
+    @Override
+    Pointer subtract(int val);
+
+    @Override
+    Pointer and(Unsigned val);
+
+    @Override
+    Pointer and(int val);
+
+    @Override
+    Pointer or(Unsigned val);
+
+    @Override
+    Pointer or(int val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2012, 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.word;
+
+public interface Signed extends WordBase {
+
+    /**
+     * Returns a Signed whose value is {@code (this + val)}.
+     *
+     * @param val value to be added to this Signed.
+     * @return {@code this + val}
+     */
+    Signed add(Signed val);
+
+    /**
+     * Returns a Signed whose value is {@code (this - val)}.
+     *
+     * @param val value to be subtracted from this Signed.
+     * @return {@code this - val}
+     */
+    Signed subtract(Signed val);
+
+    /**
+     * Returns a Signed whose value is {@code (this * val)}.
+     *
+     * @param val value to be multiplied by this Signed.
+     * @return {@code this * val}
+     */
+    Signed multiply(Signed val);
+
+    /**
+     * Returns a Signed whose value is {@code (this / val)}.
+     *
+     * @param val value by which this Signed is to be divided.
+     * @return {@code this / val}
+     */
+    Signed signedDivide(Signed val);
+
+    /**
+     * Returns a Signed whose value is {@code (this % val)}.
+     *
+     * @param val value by which this Signed is to be divided, and the remainder computed.
+     * @return {@code this % val}
+     */
+    Signed signedRemainder(Signed val);
+
+    /**
+     * Returns a Signed whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     */
+    Signed shiftLeft(Unsigned n);
+
+    /**
+     * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this >> n}
+     */
+    Signed signedShiftRight(Unsigned n);
+
+    /**
+     * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed if and only if this
+     * and val are both negative.)
+     *
+     * @param val value to be AND'ed with this Signed.
+     * @return {@code this & val}
+     */
+    Signed and(Signed val);
+
+    /**
+     * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed if and only if
+     * either this or val is negative.)
+     *
+     * @param val value to be OR'ed with this Signed.
+     * @return {@code this | val}
+     */
+    Signed or(Signed val);
+
+    /**
+     * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed if and only if
+     * exactly one of this and val are negative.)
+     *
+     * @param val value to be XOR'ed with this Signed.
+     * @return {@code this ^ val}
+     */
+    Signed xor(Signed val);
+
+    /**
+     * Returns a Signed whose value is {@code (~this)}. (This method returns a negative value if and only if this Signed
+     * is non-negative.)
+     *
+     * @return {@code ~this}
+     */
+    Signed not();
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this < val}
+     */
+    boolean lessThan(Signed val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this <= val}
+     */
+    boolean lessOrEqual(Signed val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this > val}
+     */
+    boolean greaterThan(Signed val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this >= val}
+     */
+    boolean greaterOrEqual(Signed val);
+
+
+
+    /**
+     * Returns a Signed whose value is {@code (this + val)}.
+     *
+     * @param val value to be added to this Signed.
+     * @return {@code this + val}
+     */
+    Signed add(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this - val)}.
+     *
+     * @param val value to be subtracted from this Signed.
+     * @return {@code this - val}
+     */
+    Signed subtract(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this * val)}.
+     *
+     * @param val value to be multiplied by this Signed.
+     * @return {@code this * val}
+     */
+    Signed multiply(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this / val)}.
+     *
+     * @param val value by which this Signed is to be divided.
+     * @return {@code this / val}
+     */
+    Signed signedDivide(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this % val)}.
+     *
+     * @param val value by which this Signed is to be divided, and the remainder computed.
+     * @return {@code this % val}
+     */
+    Signed signedRemainder(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     */
+    Signed shiftLeft(int n);
+
+    /**
+     * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this >> n}
+     */
+    Signed signedShiftRight(int n);
+
+    /**
+     * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed if and only if this
+     * and val are both negative.)
+     *
+     * @param val value to be AND'ed with this Signed.
+     * @return {@code this & val}
+     */
+    Signed and(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed if and only if
+     * either this or val is negative.)
+     *
+     * @param val value to be OR'ed with this Signed.
+     * @return {@code this | val}
+     */
+    Signed or(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed if and only if
+     * exactly one of this and val are negative.)
+     *
+     * @param val value to be XOR'ed with this Signed.
+     * @return {@code this ^ val}
+     */
+    Signed xor(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this < val}
+     */
+    boolean lessThan(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this <= val}
+     */
+    boolean lessOrEqual(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this > val}
+     */
+    boolean greaterThan(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this >= val}
+     */
+    boolean greaterOrEqual(int val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2012, 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.word;
+
+public interface Unsigned extends WordBase {
+
+    /**
+     * Returns a Unsigned whose value is {@code (this + val)}.
+     *
+     * @param val value to be added to this Unsigned.
+     * @return {@code this + val}
+     */
+    Unsigned add(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this - val)}.
+     *
+     * @param val value to be subtracted from this Unsigned.
+     * @return {@code this - val}
+     */
+    Unsigned subtract(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this * val)}.
+     *
+     * @param val value to be multiplied by this Unsigned.
+     * @return {@code this * val}
+     */
+    Unsigned multiply(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this / val)}.
+     *
+     * @param val value by which this Unsigned is to be divided.
+     * @return {@code this / val}
+     */
+    Unsigned unsignedDivide(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this % val)}.
+     *
+     * @param val value by which this Unsigned is to be divided, and the remainder computed.
+     * @return {@code this % val}
+     */
+    Unsigned unsignedRemainder(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     */
+    Unsigned shiftLeft(Unsigned n);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this >> n}
+     */
+    Unsigned unsignedShiftRight(Unsigned n);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this & val)}.
+     *
+     * @param val value to be AND'ed with this Unsigned.
+     * @return {@code this & val}
+     */
+    Unsigned and(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this | val)}.
+     *
+     * @param val value to be OR'ed with this Unsigned.
+     * @return {@code this | val}
+     */
+    Unsigned or(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this ^ val)}.
+     *
+     * @param val value to be XOR'ed with this Unsigned.
+     * @return {@code this ^ val}
+     */
+    Unsigned xor(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (~this)}.
+     *
+     * @return {@code ~this}
+     */
+    Unsigned not();
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this < val}
+     */
+    boolean belowThan(Unsigned val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this <= val}
+     */
+    boolean belowOrEqual(Unsigned val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this > val}
+     */
+    boolean aboveThan(Unsigned val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this >= val}
+     */
+    boolean aboveOrEqual(Unsigned val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this + val)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to be added to this Unsigned.
+     * @return {@code this + val}
+     */
+    Unsigned add(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this - val)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to be subtracted from this Unsigned.
+     * @return {@code this - val}
+     */
+    Unsigned subtract(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this * val)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to be multiplied by this Unsigned.
+     * @return {@code this * val}
+     */
+    Unsigned multiply(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this / val)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value by which this Unsigned is to be divided.
+     * @return {@code this / val}
+     */
+    Unsigned unsignedDivide(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this % val)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value by which this Unsigned is to be divided, and the remainder computed.
+     * @return {@code this % val}
+     */
+    Unsigned unsignedRemainder(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this << n)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     */
+    Unsigned shiftLeft(int n);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this >> n}
+     */
+    Unsigned unsignedShiftRight(int n);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this & val)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to be AND'ed with this Unsigned.
+     * @return {@code this & val}
+     */
+    Unsigned and(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this | val)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to be OR'ed with this Unsigned.
+     * @return {@code this | val}
+     */
+    Unsigned or(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this ^ val)}. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to be XOR'ed with this Unsigned.
+     * @return {@code this ^ val}
+     */
+    Unsigned xor(int val);
+
+    /**
+     * Compares this Unsigned with the specified value. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this < val}
+     */
+    boolean belowThan(int val);
+
+    /**
+     * Compares this Unsigned with the specified value. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this <= val}
+     */
+    boolean belowOrEqual(int val);
+
+    /**
+     * Compares this Unsigned with the specified value. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this > val}
+     */
+    boolean aboveThan(int val);
+
+    /**
+     * Compares this Unsigned with the specified value. <br>
+     * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result
+     * is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this >= val}
+     */
+    boolean aboveOrEqual(int val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,756 @@
+/*
+ * Copyright (c) 2012, 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.word;
+
+import static com.oracle.graal.graph.UnsafeAccess.*;
+
+import java.lang.annotation.*;
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
+public abstract class Word implements Signed, Unsigned, Pointer {
+      /**
+      * Links a method to a canonical operation represented by an {@link Opcode} val.
+      */
+     @Retention(RetentionPolicy.RUNTIME)
+     @Target(ElementType.METHOD)
+     public @interface Operation {
+         Class<? extends ValueNode> node() default ValueNode.class;
+         boolean rightOperandIsInt() default false;
+         Opcode opcode() default Opcode.NODE_CLASS;
+         Condition condition() default Condition.EQ;
+     }
+
+     /**
+      * The canonical {@link Operation} represented by a method in the {@link Word} class.
+      */
+     public enum Opcode {
+         NODE_CLASS,
+         COMPARISON,
+         NOT,
+         READ,
+         READ_FINAL,
+         WRITE,
+         ZERO,
+         FROM_UNSIGNED,
+         FROM_SIGNED,
+         FROM_OBJECT,
+         TO_OBJECT,
+         TO_RAW_VALUE,
+    }
+
+    private static Word box(long val) {
+        return HostedWord.box(val);
+    }
+
+    protected abstract long unbox();
+
+    private static Word intParam(int val) {
+        return box(val);
+    }
+
+
+    /**
+     * The constant 0, i.e., the word with no bits set. There is no difference between a signed and unsigned zero.
+     * @return the constant 0.
+     */
+    @Operation(opcode = Opcode.ZERO)
+    public static Word zero() {
+        return box(0L);
+    }
+
+    /**
+     * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned 64-bit value (in contrast to the semantics of a Java long).
+     * @param val a 64 bit unsigned value
+     * @return the value cast to Word
+     */
+    @Operation(opcode = Opcode.FROM_UNSIGNED)
+    public static Word unsigned(long val) {
+        return box(val);
+    }
+
+    /**
+     * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned 32-bit value (in contrast to the semantics of a Java int).
+     * @param val a 32 bit unsigned value
+     * @return the value cast to Word
+     */
+    @Operation(opcode = Opcode.FROM_UNSIGNED)
+    public static Word unsigned(int val) {
+        return box(val & 0xffffffffL);
+    }
+
+    /**
+     * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed 64-bit value (unchanged semantics of a Java long).
+     * @param val a 64 bit signed value
+     * @return the value cast to Word
+     */
+    @Operation(opcode = Opcode.FROM_SIGNED)
+    public static Word signed(long val) {
+        return box(val);
+    }
+
+    /**
+     * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed 32-bit value (unchanged semantics of a Java int).
+     * @param val a 32 bit signed value
+     * @return the value cast to Word
+     */
+    @Operation(opcode = Opcode.FROM_SIGNED)
+    public static Word signed(int val) {
+        return box(val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.TO_RAW_VALUE)
+    public long rawValue() {
+        return unbox();
+    }
+
+    @Operation(opcode = Opcode.FROM_OBJECT)
+    public static native Pointer fromObject(Object val);
+
+    @Override
+    @Operation(opcode = Opcode.TO_OBJECT)
+    public native Object toObject();
+
+
+    @Override
+    @Operation(node = IntegerAddNode.class)
+    public Word add(Signed val) {
+        return add((Word) val);
+    }
+    @Override
+    @Operation(node = IntegerAddNode.class)
+    public Word add(Unsigned val) {
+        return add((Word) val);
+    }
+    @Override
+    @Operation(node = IntegerAddNode.class)
+    public Word add(int val) {
+        return add(intParam(val));
+    }
+    @Operation(node = IntegerAddNode.class)
+    public Word add(Word val) {
+        return box(unbox() + val.unbox());
+    }
+
+    @Override
+    @Operation(node = IntegerSubNode.class)
+    public Word subtract(Signed val) {
+        return subtract((Word) val);
+    }
+    @Override
+    @Operation(node = IntegerSubNode.class)
+    public Word subtract(Unsigned val) {
+        return subtract((Word) val);
+    }
+    @Override
+    @Operation(node = IntegerSubNode.class)
+    public Word subtract(int val) {
+        return subtract(intParam(val));
+    }
+    @Operation(node = IntegerSubNode.class)
+    public Word subtract(Word val) {
+        return box(unbox() - val.unbox());
+    }
+
+    @Override
+    @Operation(node = IntegerMulNode.class)
+    public Word multiply(Signed val) {
+        return multiply((Word) val);
+    }
+    @Override
+    @Operation(node = IntegerMulNode.class)
+    public Word multiply(Unsigned val) {
+        return multiply((Word) val);
+    }
+    @Override
+    @Operation(node = IntegerMulNode.class)
+    public Word multiply(int val) {
+        return multiply(intParam(val));
+    }
+    @Operation(node = IntegerMulNode.class)
+    public Word multiply(Word val) {
+        return box(unbox() * val.unbox());
+    }
+
+    @Override
+    @Operation(node = IntegerDivNode.class)
+    public Word signedDivide(Signed val) {
+        return signedDivide((Word) val);
+    }
+    @Override
+    @Operation(node = IntegerMulNode.class)
+    public Word signedDivide(int val) {
+        return signedDivide(intParam(val));
+    }
+    @Operation(node = IntegerMulNode.class)
+    public Word signedDivide(Word val) {
+        return box(unbox() / val.unbox());
+    }
+
+    @Override
+    @Operation(node = UnsignedDivNode.class)
+    public Word unsignedDivide(Unsigned val) {
+        return unsignedDivide((Word) val);
+    }
+    @Override
+    @Operation(node = UnsignedDivNode.class)
+    public Word unsignedDivide(int val) {
+        return signedDivide(intParam(val));
+    }
+    @Operation(node = UnsignedDivNode.class)
+    public Word unsignedDivide(Word val) {
+        return box(UnsignedMath.divide(unbox(), val.unbox()));
+    }
+
+    @Override
+    @Operation(node = IntegerRemNode.class)
+    public Word signedRemainder(Signed val) {
+        return signedRemainder((Word) val);
+    }
+    @Override
+    @Operation(node = IntegerRemNode.class)
+    public Word signedRemainder(int val) {
+        return signedRemainder(intParam(val));
+    }
+    @Operation(node = IntegerRemNode.class)
+    public Word signedRemainder(Word val) {
+        return box(unbox() % val.unbox());
+    }
+
+    @Override
+    @Operation(node = UnsignedRemNode.class)
+    public Word unsignedRemainder(Unsigned val) {
+        return unsignedRemainder((Word) val);
+    }
+    @Override
+    @Operation(node = UnsignedRemNode.class)
+    public Word unsignedRemainder(int val) {
+        return signedRemainder(intParam(val));
+    }
+    @Operation(node = UnsignedRemNode.class)
+    public Word unsignedRemainder(Word val) {
+        return box(UnsignedMath.remainder(unbox(), val.unbox()));
+    }
+
+    @Override
+    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
+    public Word shiftLeft(Unsigned val) {
+        return shiftLeft((Word) val);
+    }
+    @Override
+    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
+    public Word shiftLeft(int val) {
+        return shiftLeft(intParam(val));
+    }
+    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
+    public Word shiftLeft(Word val) {
+        return box(unbox() << val.unbox());
+    }
+
+    @Override
+    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
+    public Word signedShiftRight(Unsigned val) {
+        return signedShiftRight((Word) val);
+    }
+    @Override
+    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
+    public Word signedShiftRight(int val) {
+        return signedShiftRight(intParam(val));
+    }
+    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
+    public Word signedShiftRight(Word val) {
+        return box(unbox() >> val.unbox());
+    }
+
+    @Override
+    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
+    public Word unsignedShiftRight(Unsigned val) {
+        return unsignedShiftRight((Word) val);
+    }
+    @Override
+    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
+    public Word unsignedShiftRight(int val) {
+        return unsignedShiftRight(intParam(val));
+    }
+    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
+    public Word unsignedShiftRight(Word val) {
+        return box(unbox() >>> val.unbox());
+    }
+
+    @Override
+    @Operation(node = AndNode.class)
+    public Word and(Signed val) {
+        return and((Word) val);
+    }
+    @Override
+    @Operation(node = AndNode.class)
+    public Word and(Unsigned val) {
+        return and((Word) val);
+    }
+    @Override
+    @Operation(node = AndNode.class)
+    public Word and(int val) {
+        return and(intParam(val));
+    }
+    @Operation(node = AndNode.class)
+    public Word and(Word val) {
+        return box(unbox() & val.unbox());
+    }
+
+    @Override
+    @Operation(node = OrNode.class)
+    public Word or(Signed val) {
+        return or((Word) val);
+    }
+    @Override
+    @Operation(node = OrNode.class)
+    public Word or(Unsigned val) {
+        return or((Word) val);
+    }
+    @Override
+    @Operation(node = OrNode.class)
+    public Word or(int val) {
+        return or(intParam(val));
+    }
+    @Operation(node = OrNode.class)
+    public Word or(Word val) {
+        return box(unbox() | val.unbox());
+    }
+
+    @Override
+    @Operation(node = XorNode.class)
+    public Word xor(Signed val) {
+        return xor((Word) val);
+    }
+    @Override
+    @Operation(node = XorNode.class)
+    public Word xor(Unsigned val) {
+        return xor((Word) val);
+    }
+    @Override
+    @Operation(node = XorNode.class)
+    public Word xor(int val) {
+        return xor(intParam(val));
+    }
+    @Operation(node = XorNode.class)
+    public Word xor(Word val) {
+        return box(unbox() ^ val.unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.NOT)
+    public Word not() {
+        return box(~unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
+    public boolean lessThan(Signed val) {
+        return lessThan((Word) val);
+    }
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
+    public boolean lessThan(int val) {
+        return lessThan(intParam(val));
+    }
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
+    public boolean lessThan(Word val) {
+        return unbox() < val.unbox();
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
+    public boolean lessOrEqual(Signed val) {
+        return lessOrEqual((Word) val);
+    }
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
+    public boolean lessOrEqual(int val) {
+        return lessOrEqual(intParam(val));
+    }
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
+    public boolean lessOrEqual(Word val) {
+        return unbox() <= val.unbox();
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
+    public boolean greaterThan(Signed val) {
+        return greaterThan((Word) val);
+    }
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
+    public boolean greaterThan(int val) {
+        return greaterThan(intParam(val));
+    }
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
+    public boolean greaterThan(Word val) {
+        return unbox() > val.unbox();
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
+    public boolean greaterOrEqual(Signed val) {
+        return greaterOrEqual((Word) val);
+    }
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
+    public boolean greaterOrEqual(int val) {
+        return greaterOrEqual(intParam(val));
+    }
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
+    public boolean greaterOrEqual(Word val) {
+        return unbox() >= val.unbox();
+    }
+
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
+    public boolean belowThan(Unsigned val) {
+        return belowThan((Word) val);
+    }
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
+    public boolean belowThan(int val) {
+        return belowThan(intParam(val));
+    }
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
+    public boolean belowThan(Word val) {
+        return UnsignedMath.belowThan(unbox(), val.unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
+    public boolean belowOrEqual(Unsigned val) {
+        return belowOrEqual((Word) val);
+    }
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
+    public boolean belowOrEqual(int val) {
+        return belowOrEqual(intParam(val));
+    }
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
+    public boolean belowOrEqual(Word val) {
+        return UnsignedMath.belowOrEqual(unbox(), val.unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
+    public boolean aboveThan(Unsigned val) {
+        return aboveThan((Word) val);
+    }
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
+    public boolean aboveThan(int val) {
+        return aboveThan(intParam(val));
+    }
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
+    public boolean aboveThan(Word val) {
+        return UnsignedMath.aboveThan(unbox(), val.unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
+    public boolean aboveOrEqual(Unsigned val) {
+        return aboveOrEqual((Word) val);
+    }
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
+    public boolean aboveOrEqual(int val) {
+        return aboveOrEqual(intParam(val));
+    }
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
+    public boolean aboveOrEqual(Word val) {
+        return UnsignedMath.aboveOrEqual(unbox(), val.unbox());
+    }
+
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public byte readByte(WordBase offset) {
+        return unsafe.getByte(add((Word) offset).unbox());
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public char readChar(WordBase offset) {
+        return unsafe.getChar(add((Word) offset).unbox());
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public short readShort(WordBase offset) {
+        return unsafe.getShort(add((Word) offset).unbox());
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public int readInt(WordBase offset) {
+        return unsafe.getInt(add((Word) offset).unbox());
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public long readLong(WordBase offset) {
+        return unsafe.getLong(add((Word) offset).unbox());
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public float readFloat(WordBase offset) {
+        return unsafe.getFloat(add((Word) offset).unbox());
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public double readDouble(WordBase offset) {
+        return unsafe.getDouble(add((Word) offset).unbox());
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Word readWord(WordBase offset) {
+        return box(unsafe.getAddress(add((Word) offset).unbox()));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public native Object readObject(WordBase offset);
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public byte readByte(int offset) {
+        return readByte(signed(offset));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public char readChar(int offset) {
+        return readChar(signed(offset));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public short readShort(int offset) {
+        return readShort(signed(offset));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public int readInt(int offset) {
+        return readInt(signed(offset));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public long readLong(int offset) {
+        return readLong(signed(offset));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public float readFloat(int offset) {
+        return readFloat(signed(offset));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public double readDouble(int offset) {
+        return readDouble(signed(offset));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Word readWord(int offset) {
+        return readWord(signed(offset));
+    }
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Object readObject(int offset) {
+        return readObject(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public byte readFinalByte(WordBase offset) {
+        return readByte(offset);
+    }
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public char readFinalChar(WordBase offset) {
+        return readChar(offset);
+    }
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public short readFinalShort(WordBase offset) {
+        return readShort(offset);
+    }
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public int readFinalInt(WordBase offset) {
+        return readInt(offset);
+    }
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public long readFinalLong(WordBase offset) {
+        return readLong(offset);
+    }
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public float readFinalFloat(WordBase offset) {
+        return readFloat(offset);
+    }
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public double readFinalDouble(WordBase offset) {
+        return readDouble(offset);
+    }
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public Word readFinalWord(WordBase offset) {
+        return readWord(offset);
+    }
+    @Override
+    @Operation(opcode = Opcode.READ_FINAL)
+    public Object readFinalObject(WordBase offset) {
+        return readObject(offset);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeByte(WordBase offset, byte val) {
+        unsafe.putByte(add((Word) offset).unbox(), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeChar(WordBase offset, char val) {
+        unsafe.putChar(add((Word) offset).unbox(), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeShort(WordBase offset, Short val) {
+        unsafe.putShort(add((Word) offset).unbox(), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeInt(WordBase offset, int val) {
+        unsafe.putInt(add((Word) offset).unbox(), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeLong(WordBase offset, long val) {
+        unsafe.putLong(add((Word) offset).unbox(), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeFloat(WordBase offset, float val) {
+        unsafe.putFloat(add((Word) offset).unbox(), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeDouble(WordBase offset, double val) {
+        unsafe.putDouble(add((Word) offset).unbox(), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeWord(WordBase offset, WordBase val) {
+        unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public native void writeObject(WordBase offset, Object val);
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeByte(int offset, byte val) {
+        writeByte(signed(offset), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeChar(int offset, char val) {
+        writeChar(signed(offset), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeShort(int offset, short val) {
+        writeShort(signed(offset), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeInt(int offset, int val) {
+        writeInt(signed(offset), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeLong(int offset, long val) {
+        writeLong(signed(offset), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeFloat(int offset, float val) {
+        writeFloat(signed(offset), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeDouble(int offset, double val) {
+        writeDouble(signed(offset), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeWord(int offset, WordBase val) {
+        writeWord(signed(offset), val);
+    }
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeObject(int offset, Object val) {
+        writeObject(signed(offset), val);
+    }
+}
+
+final class HostedWord extends Word {
+    private static final int SMALL_FROM = -1;
+    private static final int SMALL_TO = 100;
+
+    private static final HostedWord[] smallCache = new HostedWord[SMALL_TO - SMALL_FROM + 1];
+    private static final ConcurrentHashMap<Long, HostedWord> cache = new ConcurrentHashMap<>();
+
+    static {
+        for (int i = SMALL_FROM; i <= SMALL_TO; i++) {
+            smallCache[i - SMALL_FROM] = new HostedWord(i);
+        }
+    }
+
+    private final long rawValue;
+
+    private HostedWord(long rawValue) {
+       this.rawValue = rawValue;
+    }
+
+    protected static Word box(long val) {
+        if (val >= SMALL_FROM && val <= SMALL_TO) {
+            return smallCache[(int) val - SMALL_FROM];
+        }
+        Long key = val;
+        HostedWord result = cache.get(key);
+        if (result != null) {
+            return result;
+        }
+        HostedWord newValue = new HostedWord(val);
+        HostedWord oldValue = cache.putIfAbsent(key, newValue);
+        return oldValue == null ? newValue : oldValue;
+    }
+
+    @Override
+    protected long unbox() {
+        return rawValue;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/WordBase.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012, 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.word;
+
+public interface WordBase {
+
+    long rawValue();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,311 @@
+/*
+ * 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.word.phases;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.word.*;
+import com.oracle.graal.word.Word.Operation;
+
+/**
+ * Transforms all uses of the {@link Word} class into unsigned operations on {@code int} or {@code long} values,
+ * depending on the word kind of the underlying platform.
+ */
+public class WordTypeRewriterPhase extends Phase {
+
+    private final ResolvedJavaType wordBaseType;
+    private final ResolvedJavaType wordImplType;
+    private final Kind wordKind;
+
+    public WordTypeRewriterPhase(MetaAccessProvider metaAccess, Kind wordKind) {
+        this.wordKind = wordKind;
+        this.wordBaseType = metaAccess.lookupJavaType(WordBase.class);
+        this.wordImplType = metaAccess.lookupJavaType(Word.class);
+    }
+
+    public ResolvedJavaType getWordBaseType() {
+        return wordBaseType;
+    }
+
+    public ResolvedJavaType getWordImplType() {
+        return wordImplType;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (Node n : GraphOrder.forwardGraph(graph)) {
+            if (n instanceof ValueNode) {
+                ValueNode valueNode = (ValueNode) n;
+                if (isWord(valueNode)) {
+                    changeToWord(valueNode);
+                }
+            }
+        }
+
+        // Remove casts between different word types (which are by now no longer have kind Object)
+        for (CheckCastNode checkCastNode : graph.getNodes().filter(CheckCastNode.class).snapshot()) {
+            if (!checkCastNode.isDeleted() && checkCastNode.kind() == wordKind) {
+                checkCastNode.replaceAtUsages(checkCastNode.object());
+                graph.removeFixed(checkCastNode);
+            }
+        }
+
+        // Remove unnecessary/redundant unsafe casts
+        for (UnsafeCastNode unsafeCastNode : graph.getNodes().filter(UnsafeCastNode.class).snapshot()) {
+            if (!unsafeCastNode.isDeleted() && unsafeCastNode.object().stamp() == unsafeCastNode.stamp()) {
+                graph.replaceFloating(unsafeCastNode, unsafeCastNode.object());
+            }
+        }
+
+        // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words
+        for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) {
+            ValueNode x = objectEqualsNode.x();
+            ValueNode y = objectEqualsNode.y();
+            if (x.kind() == wordKind || y.kind() == wordKind) {
+                assert x.kind() == wordKind;
+                assert y.kind() == wordKind;
+                graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y)));
+            }
+        }
+
+        // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words
+        for (LoadIndexedNode load : graph.getNodes().filter(LoadIndexedNode.class).snapshot()) {
+            if (isWord(load)) {
+                load.setStamp(StampFactory.forKind(wordKind));
+            }
+        }
+
+        for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) {
+            ResolvedJavaMethod targetMethod = callTargetNode.targetMethod();
+            if (!callTargetNode.isStatic() && (callTargetNode.receiver().kind() == wordKind || isWord(callTargetNode.receiver()))) {
+                targetMethod = getWordImplType().resolveMethod(targetMethod);
+            }
+            Operation operation = targetMethod.getAnnotation(Word.Operation.class);
+            if (operation != null) {
+                NodeInputList<ValueNode> arguments = callTargetNode.arguments();
+                Invoke invoke = (Invoke) callTargetNode.usages().first();
+                assert invoke != null : callTargetNode.targetMethod();
+
+                switch (operation.opcode()) {
+                    case NODE_CLASS:
+                        assert arguments.size() == 2;
+                        ValueNode left = arguments.get(0);
+                        ValueNode right = operation.rightOperandIsInt() ? toUnsigned(graph, arguments.get(1), Kind.Int) : fromSigned(graph, arguments.get(1));
+                        replace(invoke, nodeClassOp(graph, operation.node(), left, right));
+                        break;
+
+                    case COMPARISON:
+                        assert arguments.size() == 2;
+                        replace(invoke, comparisonOp(graph, operation.condition(), arguments.get(0), fromSigned(graph, arguments.get(1))));
+                        break;
+
+                    case NOT:
+                        assert arguments.size() == 1;
+                        replace(invoke, graph.unique(new XorNode(wordKind, arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph))));
+                        break;
+
+                    case READ:
+                        assert arguments.size() == 2;
+                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.ANY_LOCATION));
+                        break;
+
+                    case READ_FINAL:
+                        assert arguments.size() == 2;
+                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.FINAL_LOCATION));
+                        break;
+
+                    case WRITE:
+                        assert arguments.size() == 3;
+                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, LocationNode.ANY_LOCATION));
+                        break;
+
+                    case ZERO:
+                        assert arguments.size() == 0;
+                        replace(invoke, ConstantNode.forIntegerKind(wordKind, 0L, graph));
+                        break;
+
+                    case FROM_UNSIGNED:
+                        assert arguments.size() == 1;
+                        replace(invoke, fromUnsigned(graph, arguments.get(0)));
+                        break;
+
+                    case FROM_SIGNED:
+                        assert arguments.size() == 1;
+                        replace(invoke, fromSigned(graph, arguments.get(0)));
+                        break;
+
+                    case TO_RAW_VALUE:
+                        assert arguments.size() == 1;
+                        replace(invoke, toUnsigned(graph, arguments.get(0), Kind.Long));
+                        break;
+
+                    case FROM_OBJECT:
+                        assert arguments.size() == 1;
+                        replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), StampFactory.forKind(wordKind))));
+                        break;
+
+                    case TO_OBJECT:
+                        assert arguments.size() == 1;
+                        replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.node().stamp())));
+                        break;
+
+                    default:
+                        throw new GraalInternalError("Unknown opcode: %s", operation.opcode());
+                }
+            }
+        }
+    }
+
+    private ValueNode fromUnsigned(StructuredGraph graph, ValueNode value) {
+        return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L);
+    }
+
+    private ValueNode fromSigned(StructuredGraph graph, ValueNode value) {
+        return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.I2L);
+    }
+
+    private static ValueNode toUnsigned(StructuredGraph graph, ValueNode value, Kind toKind) {
+        return convert(graph, value, toKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L);
+    }
+
+    private static ValueNode convert(StructuredGraph graph, ValueNode value, Kind toKind, ConvertNode.Op longToIntOp, ConvertNode.Op intToLongOp) {
+        assert longToIntOp.from == Kind.Long && longToIntOp.to == Kind.Int;
+        assert intToLongOp.from == Kind.Int && intToLongOp.to == Kind.Long;
+        if (value.kind() == toKind) {
+            return value;
+        }
+
+        if (toKind == Kind.Int) {
+            assert value.kind() == Kind.Long;
+            return graph.unique(new ConvertNode(longToIntOp, value));
+        } else {
+            assert toKind == Kind.Long;
+            assert value.kind().getStackKind() == Kind.Int;
+            return graph.unique(new ConvertNode(intToLongOp, value));
+        }
+    }
+
+    private ValueNode nodeClassOp(StructuredGraph graph, Class<? extends ValueNode> nodeClass, ValueNode left, ValueNode right) {
+        try {
+            Constructor< ? extends ValueNode> constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class);
+            return graph.add(constructor.newInstance(wordKind, left, right));
+        } catch (Throwable ex) {
+            throw new GraalInternalError(ex).addContext(nodeClass.getName());
+        }
+    }
+
+    private ValueNode comparisonOp(StructuredGraph graph, Condition condition, ValueNode left, ValueNode right) {
+        assert left.kind() == wordKind && right.kind() == wordKind;
+
+        // mirroring gets the condition into canonical form
+        boolean mirror = condition.canonicalMirror();
+
+        ValueNode a = mirror ? right : left;
+        ValueNode b = mirror ? left : right;
+
+
+        CompareNode comparison;
+        if (condition == Condition.EQ || condition == Condition.NE) {
+            comparison = new IntegerEqualsNode(a, b);
+        } else if (condition.isUnsigned()) {
+            comparison = new IntegerBelowThanNode(a, b);
+        } else {
+            comparison = new IntegerLessThanNode(a, b);
+        }
+        MaterializeNode materialize = MaterializeNode.create(graph.unique(comparison));
+
+        ValueNode op;
+        if (condition.canonicalNegate()) {
+            op = (ValueNode) materialize.negate();
+        } else {
+            op = materialize;
+        }
+        return op;
+    }
+
+    private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Object locationIdentity) {
+        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, invoke.node().kind(), 0, offset, graph, false);
+        ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp()));
+        graph.addBeforeFixed(invoke.node(), read);
+        // The read must not float outside its block otherwise it may float above an explicit zero check on its base address
+        read.dependencies().add(BeginNode.prevBegin(invoke.node()));
+        return read;
+    }
+
+    private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Object locationIdentity) {
+        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, value.kind(), 0, offset, graph, false);
+        WriteNode write = graph.add(new WriteNode(base, value, location));
+        graph.addBeforeFixed(invoke.node(), write);
+        return write;
+    }
+
+    private static void replace(Invoke invoke, ValueNode value) {
+        FixedNode next = invoke.next();
+        invoke.setNext(null);
+        invoke.node().replaceAtPredecessor(next);
+        invoke.node().replaceAtUsages(value);
+        GraphUtil.killCFG(invoke.node());
+    }
+
+    public boolean isWord(ValueNode node) {
+        node.inferStamp();
+        if (node.stamp() == StampFactory.forWord()) {
+            return true;
+        }
+        if (node instanceof LoadIndexedNode) {
+            return isWord(((LoadIndexedNode) node).array().objectStamp().type().getComponentType());
+        }
+        if (node.kind() == Kind.Object) {
+            return isWord(node.objectStamp().type());
+        }
+        return false;
+    }
+
+    public boolean isWord(ResolvedJavaType type) {
+        if (type != null && wordBaseType.isAssignableFrom(type)) {
+            return true;
+        }
+        return false;
+    }
+
+    private void changeToWord(ValueNode valueNode) {
+        if (valueNode.isConstant() && valueNode.asConstant().getKind() == Kind.Object) {
+            WordBase value = (WordBase) valueNode.asConstant().asObject();
+            ConstantNode newConstant = ConstantNode.forIntegerKind(wordKind, value.rawValue(), valueNode.graph());
+            ((StructuredGraph) valueNode.graph()).replaceFloating((ConstantNode) valueNode, newConstant);
+        } else {
+            assert !(valueNode instanceof ConstantNode) : "boxed Word constants should not appear in a snippet graph: " + valueNode + ", stamp: " + valueNode.stamp();
+            valueNode.setStamp(StampFactory.forKind(wordKind));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Fri Jan 04 12:08:11 2013 -0800
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2011, 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.word.phases;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.word.*;
+import com.oracle.graal.word.Word.Operation;
+
+/**
+ * Verifies invariants that must hold for snippet code above and beyond normal
+ * bytecode verification.
+ */
+public class WordTypeVerificationPhase extends Phase {
+
+    private final WordTypeRewriterPhase wordAccess;
+
+    public WordTypeVerificationPhase(MetaAccessProvider metaAccess, Kind wordKind) {
+        this.wordAccess = new WordTypeRewriterPhase(metaAccess, wordKind);
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (ValueNode node : graph.getNodes().filter(ValueNode.class)) {
+            for (Node usage : node.usages()) {
+                if (usage instanceof AccessMonitorNode) {
+                    verify(!isWord(node), node, usage, "word value has no monitor");
+                } else if (usage instanceof LoadFieldNode) {
+                    verify(!isWord(node) || ((LoadFieldNode) usage).object() != node, node, usage, "cannot load from word value");
+                } else if (usage instanceof StoreFieldNode) {
+                    verify(!isWord(node) || ((StoreFieldNode) usage).object() != node, node, usage, "cannot store to word value");
+                } else if (usage instanceof CheckCastNode) {
+                    verify(!isWord(node), node, usage, "word value cannot be cast");
+                    verify(!isWord(((CheckCastNode) usage).type()), node, usage, "cannot cast to word value");
+                } else if (usage instanceof LoadIndexedNode) {
+                    verify(!isWord(node) || ((LoadIndexedNode) usage).array() != node, node, usage, "cannot load from word value");
+                    verify(!isWord(node) || ((LoadIndexedNode) usage).index() != node, node, usage, "cannot use word value as index");
+                } else if (usage instanceof StoreIndexedNode) {
+                    verify(!isWord(node) || ((StoreIndexedNode) usage).array() != node, node, usage, "cannot store to word value");
+                    verify(!isWord(node) || ((StoreIndexedNode) usage).index() != node, node, usage, "cannot use word value as index");
+                    verify(!isWord(node) || ((StoreIndexedNode) usage).value() != node, node, usage, "cannot store word value to array");
+                } else if (usage instanceof MethodCallTargetNode) {
+                    MethodCallTargetNode callTarget = (MethodCallTargetNode) usage;
+                    ResolvedJavaMethod method = callTarget.targetMethod();
+                    if (method.getAnnotation(NodeIntrinsic.class) == null) {
+                        Invoke invoke = (Invoke) callTarget.usages().first();
+                        NodeInputList<ValueNode> arguments = callTarget.arguments();
+                        boolean isStatic = Modifier.isStatic(method.getModifiers());
+                        int argc = 0;
+                        if (!isStatic) {
+                            ValueNode receiver = arguments.get(argc);
+                            if (receiver == node && isWord(node)) {
+                                ResolvedJavaMethod resolvedMethod = wordAccess.getWordImplType().resolveMethod(method);
+                                verify(resolvedMethod != null, node, invoke.node(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method));
+                                Operation operation = resolvedMethod.getAnnotation(Word.Operation.class);
+                                verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod);
+                            }
+                            argc++;
+                        }
+                        Signature signature = method.getSignature();
+                        for (int i = 0; i < signature.getParameterCount(false); i++) {
+                            ValueNode argument = arguments.get(argc);
+                            if (argument == node) {
+                                ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass());
+                                verify(isWord(type) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa");
+                            }
+                            argc++;
+                        }
+                    }
+                } else if (usage instanceof ObjectEqualsNode) {
+                    ObjectEqualsNode compare = (ObjectEqualsNode) usage;
+                    if (compare.x() == node || compare.y() == node) {
+                        verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and non-word type in use of '==' or '!='");
+                    }
+                } else if (usage instanceof ArrayLengthNode) {
+                    verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value");
+                } else if (usage instanceof PhiNode) {
+                    if (!(node instanceof MergeNode)) {
+                        PhiNode phi = (PhiNode) usage;
+                        for (ValueNode input : phi.values()) {
+                            verify(isWord(node) == isWord(input), node, input, "cannot merge word and non-word values");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean isWord(ValueNode node) {
+        return wordAccess.isWord(node);
+    }
+
+    private boolean isWord(ResolvedJavaType type) {
+        return wordAccess.isWord(type);
+    }
+
+    private static void verify(boolean condition, Node node, Node usage, String message) {
+        if (!condition) {
+            error(node, usage, message);
+        }
+    }
+
+    private static void error(Node node, Node usage, String message) {
+        throw new GraalInternalError(String.format("Snippet verification error: %s" +
+                        "%n   node: %s (%s)" +
+                        "%n  usage: %s (%s)", message, node, sourceLocation(node), usage, sourceLocation(usage)));
+    }
+
+    private static String sourceLocation(Node n) {
+        if (n instanceof PhiNode) {
+            StringBuilder buf = new StringBuilder();
+            for (Node usage : n.usages()) {
+                String loc = sourceLocation(usage);
+                if (!loc.equals("<unknown>")) {
+                    if (buf.length() != 0) {
+                        buf.append(", ");
+                    }
+                    buf.append(loc);
+                }
+            }
+            return buf.toString();
+        } else {
+            String loc = GraphUtil.approxSourceLocation(n);
+            return loc == null ? "<unknown>" : loc;
+        }
+    }
+}
--- a/mx/projects	Wed Jan 02 18:52:33 2013 +0100
+++ b/mx/projects	Fri Jan 04 12:08:11 2013 -0800
@@ -137,10 +137,17 @@
 project@com.oracle.graal.alloc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.alloc@javaCompliance=1.7
 
+# graal.word
+project@com.oracle.graal.word@subDir=graal
+project@com.oracle.graal.word@sourceDirs=src
+project@com.oracle.graal.word@dependencies=com.oracle.graal.nodes,com.oracle.graal.phases
+project@com.oracle.graal.word@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.word@javaCompliance=1.7
+
 # graal.snippets
 project@com.oracle.graal.snippets@subDir=graal
 project@com.oracle.graal.snippets@sourceDirs=src
-project@com.oracle.graal.snippets@dependencies=com.oracle.graal.compiler,com.oracle.graal.java
+project@com.oracle.graal.snippets@dependencies=com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.word
 project@com.oracle.graal.snippets@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.snippets@javaCompliance=1.7
 
--- a/src/share/vm/runtime/arguments.cpp	Wed Jan 02 18:52:33 2013 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Fri Jan 04 12:08:11 2013 -0800
@@ -2249,6 +2249,7 @@
           "com.oracle.graal.hotspot",
           "com.oracle.graal.asm",
           "com.oracle.graal.alloc",
+          "com.oracle.graal.word",
           "com.oracle.graal.snippets",
           "com.oracle.graal.compiler",
           "com.oracle.graal.loop",