changeset 9927:81b298e0868b

Merge.
author Christian Haeubl <haeubl@ssw.jku.at>
date Fri, 07 Jun 2013 14:15:38 +0200
parents fe9a97ee352b (current diff) 44fcf49b746f (diff)
children a9311ec68721
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallStateSplitNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyValueUsage.java
diffstat 329 files changed, 10519 insertions(+), 2649 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Jun 07 13:43:13 2013 +0200
+++ b/.hgignore	Fri Jun 07 14:15:38 2013 +0200
@@ -72,3 +72,5 @@
 *.jar.*
 eclipse-build.xml
 rebuild-launch.out
+coverage
+jacoco.exec
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -259,6 +259,7 @@
 
     public Assumptions(boolean useOptimisticAssumptions) {
         this.useOptimisticAssumptions = useOptimisticAssumptions;
+        list = new Assumption[4];
     }
 
     /**
@@ -362,6 +363,10 @@
         count++;
     }
 
+    public Assumption[] getAssumptions() {
+        return list;
+    }
+
     public void record(Assumptions assumptions) {
         for (int i = 0; i < assumptions.count; i++) {
             record(assumptions.list[i]);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Fri Jun 07 14:15:38 2013 +0200
@@ -82,6 +82,13 @@
      */
     public final int numLocks;
 
+    /**
+     * True if this is a position inside an exception handler before the exception object has been
+     * consumed. In this case, {@link #numStack == 1} and {@link #getStackValue(int)
+     * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
+     * position, the interpreter will rethrow the exception instead of executing the bytecode
+     * instruction at this position.
+     */
     public final boolean rethrowException;
 
     public final boolean duringCall;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Fri Jun 07 14:15:38 2013 +0200
@@ -492,6 +492,9 @@
      * @return the code annotations or {@code null} if there are none
      */
     public List<CodeAnnotation> getAnnotations() {
+        if (annotations == null) {
+            return Collections.emptyList();
+        }
         return annotations;
     }
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ForeignCallLinkage.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ForeignCallLinkage.java	Fri Jun 07 14:15:38 2013 +0200
@@ -55,4 +55,11 @@
      *         this target
      */
     boolean destroysRegisters();
+
+    /**
+     * Determines if this is call to a function that does not deoptimize, and therefore also does
+     * not lock, GC or throw exceptions. That is, the thread's execution state during the call is
+     * never inspected by another thread.
+     */
+    boolean canDeoptimize();
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Fri Jun 07 14:15:38 2013 +0200
@@ -213,7 +213,8 @@
     public boolean equals(Object obj) {
         if (obj instanceof Register) {
             Register other = (Register) obj;
-            if (number == other.number && name.equals(other.name)) {
+            if (number == other.number) {
+                assert name.equals(other.name);
                 assert encoding == other.encoding;
                 assert registerCategory == other.registerCategory;
                 return true;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Fri Jun 07 14:15:38 2013 +0200
@@ -120,7 +120,7 @@
     }
 
     public static boolean sameRegister(Value v1, Value v2) {
-        return isRegister(v1) && isRegister(v2) && asRegister(v1) == asRegister(v2);
+        return isRegister(v1) && isRegister(v2) && asRegister(v1).equals(asRegister(v2));
     }
 
     public static boolean sameRegister(Value v1, Value v2, Value v3) {
@@ -128,7 +128,7 @@
     }
 
     public static boolean differentRegisters(Value v1, Value v2) {
-        return !isRegister(v1) || !isRegister(v2) || asRegister(v1) != asRegister(v2);
+        return !isRegister(v1) || !isRegister(v2) || !asRegister(v1).equals(asRegister(v2));
     }
 
     public static boolean differentRegisters(Value v1, Value v2, Value v3) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Fri Jun 07 14:15:38 2013 +0200
@@ -147,7 +147,8 @@
             } else {
                 Kind componentKind = type.getComponentType().getKind().getStackKind();
                 for (int i = 0; i < values.length; i++) {
-                    assert values[i].getKind().getStackKind() == componentKind : values[i].getKind() + " != " + componentKind;
+                    assert values[i].getKind().getStackKind() == componentKind || componentKind.getBitCount() >= values[i].getKind().getStackKind().getBitCount() : values[i].getKind() + " != " +
+                                    componentKind;
                 }
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/MethodUniverse.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.meta.test;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Context for method related api.meta tests.
+ */
+public class MethodUniverse extends TypeUniverse {
+
+    public final Map<Method, ResolvedJavaMethod> methods = new HashMap<>();
+    public final Map<Constructor, ResolvedJavaMethod> constructors = new HashMap<>();
+
+    public MethodUniverse() {
+        for (Class c : classes) {
+            for (Method m : c.getDeclaredMethods()) {
+                ResolvedJavaMethod method = runtime.lookupJavaMethod(m);
+                methods.put(m, method);
+            }
+            for (Constructor m : c.getDeclaredConstructors()) {
+                constructors.put(m, runtime.lookupJavaConstructor(m));
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java	Fri Jun 07 14:15:38 2013 +0200
@@ -30,7 +30,7 @@
 /**
  * Tests for {@link BytecodeDisassemblerProvider}.
  */
-public class TestBytecodeDisassemblerProvider {
+public class TestBytecodeDisassemblerProvider extends MethodUniverse {
 
     public TestBytecodeDisassemblerProvider() {
     }
@@ -43,7 +43,7 @@
         BytecodeDisassemblerProvider dis = Graal.getRuntime().getCapability(BytecodeDisassemblerProvider.class);
         if (dis != null) {
             int count = 0;
-            for (ResolvedJavaMethod m : TestJavaMethod.methods.values()) {
+            for (ResolvedJavaMethod m : methods.values()) {
                 String disasm1 = dis.disassemble(m);
                 String disasm2 = dis.disassemble(m);
                 if (disasm1 == null) {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaMethod.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaMethod.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api.meta.test;
 
-import static com.oracle.graal.api.meta.test.TestMetaAccessProvider.*;
 import static org.junit.Assert.*;
 
 import java.lang.reflect.*;
@@ -35,24 +34,7 @@
 /**
  * Tests for {@link JavaMethod}.
  */
-public class TestJavaMethod {
-
-    public TestJavaMethod() {
-    }
-
-    public static final Map<Method, ResolvedJavaMethod> methods = new HashMap<>();
-    public static final Map<Constructor, ResolvedJavaMethod> constructors = new HashMap<>();
-    static {
-        for (Class c : classes) {
-            for (Method m : c.getDeclaredMethods()) {
-                ResolvedJavaMethod method = runtime.lookupJavaMethod(m);
-                methods.put(m, method);
-            }
-            for (Constructor m : c.getDeclaredConstructors()) {
-                constructors.put(m, runtime.lookupJavaConstructor(m));
-            }
-        }
-    }
+public class TestJavaMethod extends MethodUniverse {
 
     @Test
     public void getNameTest() {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api.meta.test;
 
-import static com.oracle.graal.api.meta.test.TestMetaAccessProvider.*;
 import static org.junit.Assert.*;
 
 import org.junit.*;
@@ -32,7 +31,7 @@
 /**
  * Tests for {@link JavaType}.
  */
-public class TestJavaType {
+public class TestJavaType extends TypeUniverse {
 
     public TestJavaType() {
     }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,125 +25,16 @@
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static org.junit.Assert.*;
 
-import java.io.*;
 import java.lang.reflect.*;
-import java.util.*;
 
 import org.junit.*;
 
-import sun.misc.Unsafe;
-
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
 
 /**
  * Tests for {@link MetaAccessProvider}.
  */
-public class TestMetaAccessProvider {
-
-    public static final Unsafe unsafe;
-    static {
-        Unsafe theUnsafe = null;
-        try {
-            theUnsafe = Unsafe.getUnsafe();
-        } catch (Exception e) {
-            try {
-                Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
-                theUnsafeField.setAccessible(true);
-                theUnsafe = (Unsafe) theUnsafeField.get(null);
-            } catch (Exception e1) {
-                throw (InternalError) new InternalError("unable to initialize unsafe").initCause(e1);
-            }
-        }
-        unsafe = theUnsafe;
-    }
-
-    public TestMetaAccessProvider() {
-    }
-
-    public static final MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class);
-    public static final Collection<Class<?>> classes = new HashSet<>();
-    public static final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
-
-    public static synchronized Class<?> getArrayClass(Class componentType) {
-        Class<?> arrayClass = arrayClasses.get(componentType);
-        if (arrayClass == null) {
-            arrayClass = Array.newInstance(componentType, 0).getClass();
-            arrayClasses.put(componentType, arrayClass);
-        }
-        return arrayClass;
-    }
-
-    public static int dimensions(Class c) {
-        if (c.getComponentType() != null) {
-            return 1 + dimensions(c.getComponentType());
-        }
-        return 0;
-    }
-
-    private static void addClass(Class c) {
-        if (classes.add(c)) {
-            if (c.getSuperclass() != null) {
-                addClass(c.getSuperclass());
-            }
-            for (Class sc : c.getInterfaces()) {
-                addClass(sc);
-            }
-            for (Class dc : c.getDeclaredClasses()) {
-                addClass(dc);
-            }
-            for (Method m : c.getDeclaredMethods()) {
-                addClass(m.getReturnType());
-                for (Class p : m.getParameterTypes()) {
-                    addClass(p);
-                }
-            }
-
-            if (c != void.class && dimensions(c) < 2) {
-                Class<?> arrayClass = Array.newInstance(c, 0).getClass();
-                arrayClasses.put(c, arrayClass);
-                addClass(arrayClass);
-            }
-        }
-    }
-
-    static {
-        Class[] initialClasses = {void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, ClassLoader.class,
-                        String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class, HashMap.class,
-                        LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class};
-        for (Class c : initialClasses) {
-            addClass(c);
-        }
-    }
-
-    public static final List<Constant> constants = new ArrayList<>();
-    static {
-        for (Field f : Constant.class.getDeclaredFields()) {
-            int mods = f.getModifiers();
-            if (f.getType() == Constant.class && Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) {
-                try {
-                    Constant c = (Constant) f.get(null);
-                    if (c != null) {
-                        constants.add(c);
-                    }
-                } catch (Exception e) {
-                }
-            }
-        }
-        for (Class c : classes) {
-            if (c != void.class && !c.isArray()) {
-                constants.add(Constant.forObject(Array.newInstance(c, 42)));
-            }
-        }
-        constants.add(Constant.forObject(new ArrayList<>()));
-        constants.add(Constant.forObject(new IdentityHashMap<>()));
-        constants.add(Constant.forObject(new LinkedHashMap<>()));
-        constants.add(Constant.forObject(new TreeMap<>()));
-        constants.add(Constant.forObject(new ArrayDeque<>()));
-        constants.add(Constant.forObject(new LinkedList<>()));
-        constants.add(Constant.forObject("a string"));
-        constants.add(Constant.forObject(42));
-    }
+public class TestMetaAccessProvider extends TypeUniverse {
 
     @Test
     public void lookupJavaTypeTest() {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.api.meta.test;
 
-import static com.oracle.graal.api.meta.test.TestJavaMethod.*;
 import static java.lang.reflect.Modifier.*;
 import static org.junit.Assert.*;
 
+import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
 
@@ -36,7 +36,7 @@
 /**
  * Tests for {@link ResolvedJavaMethod}.
  */
-public class TestResolvedJavaMethod {
+public class TestResolvedJavaMethod extends MethodUniverse {
 
     public TestResolvedJavaMethod() {
     }
@@ -94,21 +94,6 @@
     }
 
     @Test
-    public void getCompilationComplexityTest() {
-        // TODO
-    }
-
-    @Test
-    public void getMaxLocalsTest() {
-        // TODO
-    }
-
-    @Test
-    public void getMaxStackSizeTest() {
-        // TODO
-    }
-
-    @Test
     public void getModifiersTest() {
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
             ResolvedJavaMethod m = e.getValue();
@@ -148,52 +133,168 @@
 
     @Test
     public void canBeStaticallyBoundTest() {
-        // TODO
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers()));
+        }
+        for (Map.Entry<Constructor, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers()));
+        }
     }
 
-    @Test
-    public void getExceptionHandlersTest() {
-        // TODO
+    private static boolean canBeStaticallyBound(int modifiers) {
+        return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) && !Modifier.isAbstract(modifiers);
+    }
+
+    private static String methodWithExceptionHandlers(String p1, Object o2) {
+        try {
+            return p1.substring(100) + o2.toString();
+        } catch (IndexOutOfBoundsException e) {
+            e.printStackTrace();
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+        } catch (RuntimeException e) {
+            e.printStackTrace();
+        }
+        return null;
     }
 
     @Test
-    public void asStackTraceElementTest() {
-        // TODO
+    public void getExceptionHandlersTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithExceptionHandlers", String.class, Object.class));
+        ExceptionHandler[] handlers = method.getExceptionHandlers();
+        assertNotNull(handlers);
+        assertEquals(handlers.length, 3);
+        handlers[0].getCatchType().equals(runtime.lookupJavaType(IndexOutOfBoundsException.class));
+        handlers[1].getCatchType().equals(runtime.lookupJavaType(NullPointerException.class));
+        handlers[2].getCatchType().equals(runtime.lookupJavaType(RuntimeException.class));
+    }
+
+    private static String nullPointerExceptionOnFirstLine(Object o, String ignored) {
+        return o.toString() + ignored;
     }
 
     @Test
-    public void getProfilingInfoTest() {
-        // TODO
-    }
-
-    @Test
-    public void getCompilerStorageTest() {
-        // TODO
+    public void asStackTraceElementTest() throws NoSuchMethodException {
+        try {
+            nullPointerExceptionOnFirstLine(null, "ignored");
+            Assert.fail("should not reach here");
+        } catch (NullPointerException e) {
+            StackTraceElement expected = e.getStackTrace()[0];
+            ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+            StackTraceElement actual = method.asStackTraceElement(0);
+            assertEquals(expected, actual);
+        }
     }
 
     @Test
     public void getConstantPoolTest() {
-        // TODO
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            ConstantPool cp = m.getConstantPool();
+            assertTrue(cp.length() > 0);
+        }
+    }
+
+    @Test(timeout = 1000L)
+    public void getAnnotationTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationTest"));
+        Test annotation = method.getAnnotation(Test.class);
+        assertNotNull(annotation);
+        assertEquals(1000L, annotation.timeout());
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.PARAMETER)
+    @interface NonNull {
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.PARAMETER)
+    @interface Special {
+    }
+
+    private static native void methodWithAnnotatedParameters(@NonNull HashMap<String, String> p1, @Special @NonNull Class<? extends Annotation> p2);
+
+    @Test
+    public void getParameterAnnotationsTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+        Annotation[][] annotations = method.getParameterAnnotations();
+        assertEquals(2, annotations.length);
+        assertEquals(1, annotations[0].length);
+        assertEquals(NonNull.class, annotations[0][0].annotationType());
+        assertEquals(2, annotations[1].length);
+        assertEquals(Special.class, annotations[1][0].annotationType());
+        assertEquals(NonNull.class, annotations[1][1].annotationType());
     }
 
     @Test
-    public void getAnnotationTest() {
-        // TODO
+    public void getGenericParameterTypesTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+        Type[] genericParameterTypes = method.getGenericParameterTypes();
+        assertEquals(2, genericParameterTypes.length);
+        assertEquals("java.util.HashMap<java.lang.String, java.lang.String>", genericParameterTypes[0].toString());
+        assertEquals("java.lang.Class<? extends java.lang.annotation.Annotation>", genericParameterTypes[1].toString());
     }
 
     @Test
-    public void getParameterAnnotationsTest() {
-        // TODO
-    }
-
-    @Test
-    public void getGenericParameterTypesTest() {
-        // TODO
+    public void getMaxLocalsTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method1 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+        ResolvedJavaMethod method2 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+        assertEquals(0, method1.getMaxLocals());
+        assertEquals(2, method2.getMaxLocals());
 
     }
 
     @Test
-    public void canBeInlinedTest() {
-        // TODO
+    public void getMaxStackSizeTest() throws NoSuchMethodException {
+        ResolvedJavaMethod method1 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
+        ResolvedJavaMethod method2 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
+        assertEquals(0, method1.getMaxStackSize());
+        // some versions of javac produce bytecode with a stacksize of 2 for this method
+        assertTrue(3 == method2.getMaxStackSize() || 2 == method2.getMaxStackSize());
+    }
+
+    private Method findTestMethod(Method apiMethod) {
+        String testName = apiMethod.getName() + "Test";
+        for (Method m : getClass().getDeclaredMethods()) {
+            if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    // @formatter:off
+    private static final String[] untestedApiMethods = {
+        "invoke",
+        "newInstance",
+        "getDeclaringClass",
+        "getEncoding",
+        "getProfilingInfo",
+        "reprofile",
+        "getCompilerStorage",
+        "canBeInlined",
+        "getLineNumberTable",
+        "getLocalVariableTable",
+        "isInVirtualMethodTable"
+    };
+    // @formatter:on
+
+    /**
+     * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
+     * for them or are added to {@link #untestedApiMethods}.
+     */
+    @Test
+    public void testCoverage() {
+        Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
+        for (Method m : ResolvedJavaMethod.class.getDeclaredMethods()) {
+            if (findTestMethod(m) == null) {
+                assertTrue("test missing for " + m, known.contains(m.getName()));
+            } else {
+                assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
+            }
+        }
     }
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api.meta.test;
 
-import static com.oracle.graal.api.meta.test.TestMetaAccessProvider.*;
 import static java.lang.Integer.*;
 import static java.lang.reflect.Modifier.*;
 import static org.junit.Assert.*;
@@ -41,7 +40,7 @@
 /**
  * Tests for {@link ResolvedJavaType}.
  */
-public class TestResolvedJavaType {
+public class TestResolvedJavaType extends TypeUniverse {
 
     public TestResolvedJavaType() {
     }
@@ -83,7 +82,7 @@
     }
 
     @Test
-    public void isArrayClassTest() {
+    public void isArrayTest() {
         for (Class c : classes) {
             ResolvedJavaType type = runtime.lookupJavaType(c);
             boolean expected = c.isArray();
@@ -103,7 +102,7 @@
     }
 
     @Test
-    public void isAssignableToTest() {
+    public void isAssignableFromTest() {
         Class[] all = classes.toArray(new Class[classes.size()]);
         for (int i = 0; i < all.length; i++) {
             Class<?> c1 = all[i];
@@ -194,7 +193,7 @@
         }
     }
 
-    public static Class getSupertype(Class c) {
+    public Class getSupertype(Class c) {
         assert !c.isPrimitive();
         if (c.isArray()) {
             Class componentType = c.getComponentType();
@@ -209,7 +208,7 @@
         return c.getSuperclass();
     }
 
-    public static Class findLeastCommonAncestor(Class<?> c1Initial, Class<?> c2Initial) {
+    public Class findLeastCommonAncestor(Class<?> c1Initial, Class<?> c2Initial) {
         if (c1Initial.isPrimitive() || c2Initial.isPrimitive()) {
             return null;
         } else {
@@ -270,7 +269,7 @@
     abstract static class Abstract4 extends Concrete3 {
     }
 
-    static void checkConcreteSubtype(ResolvedJavaType type, Class expected) {
+    void checkConcreteSubtype(ResolvedJavaType type, Class expected) {
         ResolvedJavaType subtype = type.findUniqueConcreteSubtype();
         if (subtype == null) {
             // findUniqueConcreteSubtype() is conservative
@@ -455,8 +454,10 @@
     }
 
     @Test
-    public void findUniqueConcreteMethodTest() {
-        // TODO
+    public void findUniqueConcreteMethodTest() throws NoSuchMethodException {
+        ResolvedJavaMethod thisMethod = runtime.lookupJavaMethod(getClass().getDeclaredMethod("findUniqueConcreteMethodTest"));
+        ResolvedJavaMethod ucm = runtime.lookupJavaType(getClass()).findUniqueConcreteMethod(thisMethod);
+        assertEquals(thisMethod, ucm);
     }
 
     public static Set<Field> getInstanceFields(Class c, boolean includeSuperclasses) {
@@ -475,12 +476,12 @@
         return result;
     }
 
-    public static boolean fieldsEqual(Field f, ResolvedJavaField rjf) {
+    public boolean fieldsEqual(Field f, ResolvedJavaField rjf) {
         return rjf.getDeclaringClass().equals(runtime.lookupJavaType(f.getDeclaringClass())) && rjf.getName().equals(f.getName()) &&
                         rjf.getType().resolve(rjf.getDeclaringClass()).equals(runtime.lookupJavaType(f.getType()));
     }
 
-    public static ResolvedJavaField lookupField(ResolvedJavaField[] fields, Field key) {
+    public ResolvedJavaField lookupField(ResolvedJavaField[] fields, Field key) {
         for (ResolvedJavaField rf : fields) {
             if (fieldsEqual(key, rf)) {
                 assert (fieldModifiers() & key.getModifiers()) == rf.getModifiers() : key + ": " + toHexString(key.getModifiers()) + " != " + toHexString(rf.getModifiers());
@@ -490,7 +491,7 @@
         return null;
     }
 
-    public static Field lookupField(Set<Field> fields, ResolvedJavaField key) {
+    public Field lookupField(Set<Field> fields, ResolvedJavaField key) {
         for (Field f : fields) {
             if (fieldsEqual(f, key)) {
                 assert key.getModifiers() == (fieldModifiers() & f.getModifiers()) : key + ": " + toHexString(key.getModifiers()) + " != " + toHexString(f.getModifiers());
@@ -500,7 +501,7 @@
         return null;
     }
 
-    private static boolean isHiddenFromReflection(ResolvedJavaField f) {
+    private boolean isHiddenFromReflection(ResolvedJavaField f) {
         if (f.getDeclaringClass().equals(runtime.lookupJavaType(Throwable.class)) && f.getName().equals("backtrace")) {
             return true;
         }
@@ -574,4 +575,50 @@
             }
         }
     }
+
+    private Method findTestMethod(Method apiMethod) {
+        String testName = apiMethod.getName() + "Test";
+        for (Method m : getClass().getDeclaredMethods()) {
+            if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    // @formatter:off
+    private static final String[] untestedApiMethods = {
+        "initialize",
+        "isPrimitive",
+        "newArray",
+        "getDeclaredMethods",
+        "getDeclaredConstructors",
+        "isInitialized",
+        "getEncoding",
+        "hasFinalizableSubclass",
+        "hasFinalizer",
+        "getSourceFileName",
+        "getClassFilePath",
+        "isLocal",
+        "isMember",
+        "getEnclosingType"
+    };
+    // @formatter:on
+
+    /**
+     * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written
+     * for them or are added to {@link #untestedApiMethods}.
+     */
+    @Test
+    public void testCoverage() {
+        Set<String> known = new HashSet<>(Arrays.asList(untestedApiMethods));
+        for (Method m : ResolvedJavaType.class.getDeclaredMethods()) {
+            if (findTestMethod(m) == null) {
+                assertTrue("test missing for " + m, known.contains(m.getName()));
+            } else {
+                assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName()));
+            }
+        }
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.meta.test;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Queue;
+
+import org.junit.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+
+/**
+ * Context for type related api.meta tests.
+ */
+public class TypeUniverse {
+
+    public final Unsafe unsafe;
+    public final MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class);
+    public final Collection<Class<?>> classes = new HashSet<>();
+    public final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
+    public final List<Constant> constants = new ArrayList<>();
+
+    public TypeUniverse() {
+        Unsafe theUnsafe = null;
+        try {
+            theUnsafe = Unsafe.getUnsafe();
+        } catch (Exception e) {
+            try {
+                Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+                theUnsafeField.setAccessible(true);
+                theUnsafe = (Unsafe) theUnsafeField.get(null);
+            } catch (Exception e1) {
+                throw (InternalError) new InternalError("unable to initialize unsafe").initCause(e1);
+            }
+        }
+        unsafe = theUnsafe;
+
+        Class[] initialClasses = {void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, ClassLoader.class,
+                        String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class, HashMap.class,
+                        LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class};
+        for (Class c : initialClasses) {
+            addClass(c);
+        }
+        for (Field f : Constant.class.getDeclaredFields()) {
+            int mods = f.getModifiers();
+            if (f.getType() == Constant.class && Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) {
+                try {
+                    Constant c = (Constant) f.get(null);
+                    if (c != null) {
+                        constants.add(c);
+                    }
+                } catch (Exception e) {
+                }
+            }
+        }
+        for (Class c : classes) {
+            if (c != void.class && !c.isArray()) {
+                constants.add(Constant.forObject(Array.newInstance(c, 42)));
+            }
+        }
+        constants.add(Constant.forObject(new ArrayList<>()));
+        constants.add(Constant.forObject(new IdentityHashMap<>()));
+        constants.add(Constant.forObject(new LinkedHashMap<>()));
+        constants.add(Constant.forObject(new TreeMap<>()));
+        constants.add(Constant.forObject(new ArrayDeque<>()));
+        constants.add(Constant.forObject(new LinkedList<>()));
+        constants.add(Constant.forObject("a string"));
+        constants.add(Constant.forObject(42));
+    }
+
+    public synchronized Class<?> getArrayClass(Class componentType) {
+        Class<?> arrayClass = arrayClasses.get(componentType);
+        if (arrayClass == null) {
+            arrayClass = Array.newInstance(componentType, 0).getClass();
+            arrayClasses.put(componentType, arrayClass);
+        }
+        return arrayClass;
+    }
+
+    public static int dimensions(Class c) {
+        if (c.getComponentType() != null) {
+            return 1 + dimensions(c.getComponentType());
+        }
+        return 0;
+    }
+
+    private void addClass(Class c) {
+        if (classes.add(c)) {
+            if (c.getSuperclass() != null) {
+                addClass(c.getSuperclass());
+            }
+            for (Class sc : c.getInterfaces()) {
+                addClass(sc);
+            }
+            for (Class dc : c.getDeclaredClasses()) {
+                addClass(dc);
+            }
+            for (Method m : c.getDeclaredMethods()) {
+                addClass(m.getReturnType());
+                for (Class p : m.getParameterTypes()) {
+                    addClass(p);
+                }
+            }
+
+            if (c != void.class && dimensions(c) < 2) {
+                Class<?> arrayClass = Array.newInstance(c, 0).getClass();
+                arrayClasses.put(c, arrayClass);
+                addClass(arrayClass);
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java	Fri Jun 07 14:15:38 2013 +0200
@@ -33,6 +33,9 @@
  * <li>The callee has different register saving semantics. For example, the callee may save all
  * registers (apart from some specified temporaries) in which case the register allocator doesn't
  * not need to spill all live registers around the call site.</li>
+ * <li>The call does not occur at an INVOKE* bytecode. Such a call could be transformed into a
+ * standard Java call if the foreign routine is a normal Java method and the runtime supports
+ * linking Java calls at arbitrary bytecodes.</li>
  * </ul>
  */
 public class ForeignCallDescriptor {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Fri Jun 07 14:15:38 2013 +0200
@@ -362,8 +362,12 @@
             case Char:
             case Short:
                 return 16;
+            case Float:
+                return 32;
             case Int:
                 return 32;
+            case Double:
+                return 64;
             case Long:
                 return 64;
             default:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LocationIdentity.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011, 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.api.meta;
+
+/**
+ * Marker interface for location identities. Apart from the special values {@link #ANY_LOCATION} and
+ * {@link #FINAL_LOCATION}, a different location identity of two memory accesses guarantees that the
+ * two accesses do not interfere.
+ */
+public interface LocationIdentity {
+
+    /**
+     * Denotes any location. A write to such a location kills all values in a memory map during an
+     * analysis of memory accesses. A read from this location cannot be moved or coalesced with
+     * other reads because its interaction with other reads is not known.
+     */
+    LocationIdentity ANY_LOCATION = new NamedLocationIdentity("ANY_LOCATION");
+
+    /**
+     * Denotes the location of a value that is guaranteed to be final.
+     */
+    LocationIdentity FINAL_LOCATION = new NamedLocationIdentity("FINAL_LOCATION");
+
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Fri Jun 07 14:15:38 2013 +0200
@@ -96,8 +96,20 @@
     Constant readUnsafeConstant(Kind kind, Object base, long displacement);
 
     /**
-     * Determines if a given foreign call has a side-effect. Deoptimization cannot return execution
-     * to a point before a foreign call that has a side effect.
+     * Determines if a given foreign call is side-effect free. Deoptimization cannot return
+     * execution to a point before a foreign call that has a side effect.
      */
-    boolean hasSideEffect(ForeignCallDescriptor descriptor);
+    boolean isReexecutable(ForeignCallDescriptor descriptor);
+
+    /**
+     * Gets the set of memory locations killed by a given foreign call. Returning the special value
+     * {@link LocationIdentity#ANY_LOCATION} denotes that the call kills all memory locations.
+     * Returning any empty array denotes that the call does not kill any memory locations.
+     */
+    LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor);
+
+    /**
+     * Determines if deoptimization can occur during a given foreign call.
+     */
+    boolean canDeoptimize(ForeignCallDescriptor descriptor);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/NamedLocationIdentity.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 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.api.meta;
+
+import java.util.*;
+
+/**
+ * A {@link LocationIdentity} with a name.
+ */
+public class NamedLocationIdentity implements LocationIdentity {
+
+    protected final String name;
+
+    /**
+     * Creates a named unique location identity for read and write operations.
+     * 
+     * @param name the name of the new location identity
+     */
+    public NamedLocationIdentity(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    /**
+     * Returns the named location identity for an array of the given element kind. Array accesses of
+     * the same kind must have the same location identity unless an alias analysis guarantees that
+     * two distinct arrays are accessed.
+     */
+    public static LocationIdentity getArrayLocation(Kind elementKind) {
+        return ARRAY_LOCATIONS.get(elementKind);
+    }
+
+    private static final EnumMap<Kind, LocationIdentity> ARRAY_LOCATIONS = initArrayLocations();
+
+    private static EnumMap<Kind, LocationIdentity> initArrayLocations() {
+        EnumMap<Kind, LocationIdentity> result = new EnumMap<>(Kind.class);
+        for (Kind kind : Kind.values()) {
+            result.put(kind, new NamedLocationIdentity("Array: " + kind.getJavaName()));
+        }
+        return result;
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Fri Jun 07 14:15:38 2013 +0200
@@ -198,7 +198,8 @@
      * Resolves the method implementation for virtual dispatches on objects of this dynamic type.
      * 
      * @param method the method to select the implementation of
-     * @return the method implementation that would be selected at runtime
+     * @return the method implementation that would be selected at runtime, or {@code null} if the
+     *         runtime cannot resolve the method at this point in time.
      */
     ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method);
 
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Fri Jun 07 14:15:38 2013 +0200
@@ -114,11 +114,11 @@
         StringBuilder s = new StringBuilder();
         s.append("[");
         String sep = "";
-        if (getBase() != Register.None) {
+        if (!getBase().equals(Register.None)) {
             s.append(getBase());
             sep = " + ";
         }
-        if (getIndex() != Register.None) {
+        if (!getIndex().equals(Register.None)) {
             s.append(sep).append(getIndex()).append(" * ").append(getScale().value);
             sep = " + ";
         }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri Jun 07 14:15:38 2013 +0200
@@ -216,7 +216,7 @@
     }
 
     protected void emitOperandHelper(Register reg, AMD64Address addr) {
-        assert reg != Register.None;
+        assert !reg.equals(Register.None);
         emitOperandHelper(encode(reg), addr);
     }
 
@@ -230,14 +230,14 @@
         AMD64Address.Scale scale = addr.getScale();
         int disp = addr.getDisplacement();
 
-        if (base == Register.Frame) {
+        if (base.equals(Register.Frame)) {
             assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration";
             base = frameRegister;
         }
 
-        if (base == AMD64.rip) { // also matches Placeholder
+        if (base.equals(AMD64.rip)) { // also matches Placeholder
             // [00 000 101] disp32
-            assert index == Register.None : "cannot use RIP relative addressing with index register";
+            assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
             emitByte(0x05 | regenc);
             emitInt(disp);
         } else if (base.isValid()) {
@@ -245,28 +245,28 @@
             if (index.isValid()) {
                 int indexenc = encode(index) << 3;
                 // [base + indexscale + disp]
-                if (disp == 0 && base != rbp && (base != r13)) {
+                if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
                     // [base + indexscale]
                     // [00 reg 100][ss index base]
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x04 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                 } else if (isByte(disp)) {
                     // [base + indexscale + imm8]
                     // [01 reg 100][ss index base] imm8
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x44 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                     emitByte(disp & 0xFF);
                 } else {
                     // [base + indexscale + disp32]
                     // [10 reg 100][ss index base] disp32
-                    assert index != rsp : "illegal addressing mode";
+                    assert !index.equals(rsp) : "illegal addressing mode";
                     emitByte(0x84 | regenc);
                     emitByte(scale.log2 << 6 | indexenc | baseenc);
                     emitInt(disp);
                 }
-            } else if (base == rsp || (base == r12)) {
+            } else if (base.equals(rsp) || base.equals(r12)) {
                 // [rsp + disp]
                 if (disp == 0) {
                     // [rsp]
@@ -288,8 +288,8 @@
                 }
             } else {
                 // [base + disp]
-                assert base != rsp && (base != r12) : "illegal addressing mode";
-                if (disp == 0 && base != rbp && (base != r13)) {
+                assert !base.equals(rsp) && !base.equals(r12) : "illegal addressing mode";
+                if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
                     // [base]
                     // [00 reg base]
                     emitByte(0x00 | regenc | baseenc);
@@ -310,7 +310,7 @@
                 int indexenc = encode(index) << 3;
                 // [indexscale + disp]
                 // [00 reg 100][ss index 101] disp32
-                assert index != rsp : "illegal addressing mode";
+                assert !index.equals(rsp) : "illegal addressing mode";
                 emitByte(0x04 | regenc);
                 emitByte(scale.log2 << 6 | indexenc | 0x05);
                 emitInt(disp);
@@ -531,7 +531,7 @@
             // cmpxchg r,[m] is equivalent to X86.rax, = CAS (m, X86.rax, r)
             cmpl(rax, adr);
             movl(rax, adr);
-            if (reg != rax) {
+            if (reg.equals(rax)) {
                 Label l = new Label();
                 jccb(ConditionFlag.NotEqual, l);
                 movl(adr, reg);
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/AbstractSPARCAssembler.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/AbstractSPARCAssembler.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,10 +26,11 @@
 import com.oracle.graal.api.code.Register;
 import com.oracle.graal.api.code.TargetDescription;
 import com.oracle.graal.asm.AbstractAssembler;
-import com.oracle.graal.asm.Label;
 
 public abstract class AbstractSPARCAssembler extends AbstractAssembler {
 
+    public static final String UNBOUND_TARGET = "L" + Integer.MAX_VALUE;
+
     public AbstractSPARCAssembler(TargetDescription target) {
         super(target);
     }
@@ -40,11 +41,6 @@
     }
 
     @Override
-    public void jmp(Label l) {
-        // SPARC: Implement jump.
-    }
-
-    @Override
     protected void patchJumpTarget(int branch, int jumpTarget) {
         // SPARC: Implement patching of jump target.
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.asm.sparc;
+
+import com.oracle.graal.api.code.AbstractAddress;
+import com.oracle.graal.api.code.Register;
+
+public class SPARCAddress extends AbstractAddress {
+
+    private final Register base;
+    private final int displacement; // need Register offset / displacement CompositeValue?
+
+    /**
+     * Creates an {@link SPARCAddress} with given base register, no scaling and a given
+     * displacement.
+     * 
+     * @param base the base register
+     * @param displacement the displacement
+     */
+    public SPARCAddress(Register base, int displacement) {
+        this.base = base;
+        this.displacement = displacement;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("[");
+        if (!getBase().equals(Register.None)) {
+            s.append(getBase());
+        }
+        // later: displacement CompositeValue?
+        s.append("]");
+        return s.toString();
+    }
+
+    /**
+     * @return Base register that defines the start of the address computation. If not present, is
+     *         denoted by {@link Register#None}.
+     */
+    public Register getBase() {
+        return base;
+    }
+
+    /**
+     * @return Optional additive displacement.
+     */
+    public int getDisplacement() {
+        return displacement;
+    }
+}
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,21 +22,230 @@
  */
 package com.oracle.graal.asm.sparc;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.sparc.*;
+import com.oracle.graal.api.code.Register;
+import com.oracle.graal.api.code.RegisterConfig;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.hotspot.HotSpotGraalRuntime;
+import com.oracle.graal.sparc.SPARC;
 
 /**
  * This class implements an assembler that can encode most SPARC instructions.
  */
 public class SPARCAssembler extends AbstractSPARCAssembler {
 
+    // @formatter:off
+
+    public static class Fmt1 {
+        public Fmt1(SPARCAssembler masm, int op, int disp30) {
+            assert op == 1;
+            assert ((disp30 & 0xc0000000) == 0);
+
+            masm.emitInt(op << 30 | disp30);
+        }
+    }
+
+    public static class Fmt2a {
+        public Fmt2a(SPARCAssembler masm, int op, int rd, int op2, int imm22) {
+            assert op == 0;
+            assert rd < 0x40;
+            assert op2 < 0x8;
+
+            masm.emitInt(op << 30 | rd << 25 | op2 << 22 | (imm22 & 0x003fffff));
+        }
+    }
+
+    public static class Fmt2b {
+        public Fmt2b(SPARCAssembler masm, int op, int a, int cond, int op2, int disp22) {
+            assert op == 0;
+            assert op == 0;
+            assert cond < 0x10;
+            assert op2 < 0x8;
+
+            masm.emitInt(op << 30 | a << 29 | cond << 25 | op2 << 22 | (disp22 & 0x003fffff));
+        }
+    }
+
+    public static class Fmt2c {
+        public Fmt2c(SPARCAssembler masm, int op, int a, int cond, int op2, int cc, int predict, int disp19) {
+            assert predict < 2;
+            assert op == 0;
+            assert cond < 0x10;
+            assert op2 < 0x8;
+
+            masm.emitInt(op << 30 | a << 29 | cond << 25 | op2 << 22 | cc << 20 | predict | (disp19 & 0x0007ffff));
+        }
+    }
+
+    public static class Fmt2d {
+        public Fmt2d(SPARCAssembler masm, int op, int a, int rcond, int op2, int d16hi, int predict, int rs1, int d16lo) {
+            assert predict == 0 || predict == 1;
+            assert rcond >= 0 && rcond < 0x8;
+            assert op == 0;
+            assert op2 >= 0 && op2 < 0x8;
+            assert rs1 >= 0 && rs1 < 0x20;
+
+            masm.emitInt(op << 30 | a << 29 | rcond << 25 | op2 << 22 | d16hi & 3 | predict << 18 | rs1 << 14 | (d16lo & 0x003fff));
+        }
+    }
+
+    public static class Fmt3a {
+        public Fmt3a(SPARCAssembler masm, int op, int rd, int op3, int rs1, int rs2) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert rs2 >= 0 && rs2 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 |  rs1 << 14 | rs2);
+        }
+    }
+
+    public static class Fmt3b {
+        public Fmt3b(SPARCAssembler masm, int op, int op3, int rs1, int regOrImmediate, int rd) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 |  rs1 << 14 | (regOrImmediate & 0x1fff));
+        }
+    }
+
+    public static class Fmt3c {
+        public Fmt3c(SPARCAssembler masm, int op, int op3, int rs1, int rs2) {
+            assert  op == 2;
+            assert op3 >= 0 && op3 < 0x40;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert rs2 >= 0 && rs2 < 0x20;
+
+            masm.emitInt(op << 30 | op3 << 19 | rs1 << 14 | rs2);
+        }
+    }
+
+    public static class Fmt3d {
+        public Fmt3d(SPARCAssembler masm, int op, int op3, int rs1, int simm13) {
+            assert  op == 2;
+            assert op3 >= 0 && op3 < 0x40;
+            assert rs1 >= 0 && rs1 < 0x20;
+
+            masm.emitInt(op << 30 | op3 << 19 | rs1 << 14 | ImmedTrue | simm13);
+        }
+    }
+
+    public static class Fmt3e {
+        public Fmt3e(SPARCAssembler masm, int op, int op3, int rcond, int rs1, int rs2, int rd) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert rcond >= 0 && rcond < 0x8;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert rs2 >= 0 && rs2 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 |  rs1 << 14 | rcond << 10 | rs2);
+        }
+    }
+
+    public static class Fmt3f {
+        public Fmt3f(SPARCAssembler masm, int op, int op3, int rcond, int rs1, int simm10, int rd) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | ImmedTrue | rs1 << 14 | rcond << 10 | (simm10 & 0x000003ff));
+        }
+    }
+
+    public static class Fmt3p {
+        public Fmt3p(SPARCAssembler masm, int op, int op3, int opf, int rs1, int rs2, int rd) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert opf >= 0 && opf < 0x200;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert rs2 >= 0 && rs2 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 |  rs1 << 14 | opf << 5 | rs2);
+        }
+    }
+
+    public static class Fmt3n {
+        public Fmt3n(SPARCAssembler masm, int op, int op3, int opf, int rs2, int rd) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert opf >= 0 && opf < 0x200;
+            assert rs2 >= 0 && rs2 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | opf << 5 | rs2);
+        }
+    }
+
+    public static class Fmt3q {
+        public Fmt3q(SPARCAssembler masm, int op, int op3, int rs1, int rd) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | rs1 << 14);
+        }
+    }
+
+    public static class Fmt3r {
+        public Fmt3r(SPARCAssembler masm, int op, int fcn, int op3) {
+            assert  op == 23;
+            assert op3 >= 0 && op3 < 0x40;
+            assert fcn >= 0 && fcn < 0x40;
+
+            masm.emitInt(op << 30 | fcn << 25 | op3 << 19);
+        }
+    }
+
+    public static class Fmt4a {
+        public Fmt4a(SPARCAssembler masm, int op, int op3, int cc, int rs1, int regOrImmediate, int rd) {
+            assert  op == 2;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert  rd >= 0 &&  rd < 0x10;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | ((cc << 11) & 0x000001800) | regOrImmediate);
+        }
+    }
+
+    public static class Fmt4c {
+        public Fmt4c(SPARCAssembler masm, int op, int op3, int cond, int cc, int rs2, int rd) {
+            assert op == 2;
+            assert op3 >= 0 && op3 < 0x40;
+            assert  cc >= 0 &&  cc < 0x8;
+            assert cond >= 0 && cond < 0x10;
+            assert rs2 >= 0 && rs2 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | ((cc << 15) & 0x00040000) | cond << 14 | ((cc << 11) & 0x3) | rs2);
+        }
+    }
+
+    public static class Fmt4d {
+        public Fmt4d(SPARCAssembler masm, int op, int op3, int cond, int cc, int simm11, int rd) {
+            assert op == 2;
+            assert op3 >= 0 && op3 < 0x40;
+            assert  cc >= 0 &&  cc < 0x8;
+            assert cond >= 0 && cond < 0x10;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | ImmedTrue | ((cc << 15) & 0x00040000) | cond << 14 | ((cc << 11) & 0x3) | simm11 & 0x00004000);
+        }
+    }
+
     public static final int ImmedTrue = 0x00002000;
 
     public enum Ops {
-        CallOp(0x40000000),
-        BranchOp(0x00000000),
-        ArithOp(0x80000000),
-        LdstOp(0xC0000000);
+        CallOp(1),
+        BranchOp(0),
+        ArithOp(2),
+        LdstOp(3);
 
         private final int value;
 
@@ -49,53 +258,119 @@
         }
     }
 
+    public enum Op2s {
+        Bpr(3),
+        Fb(6),
+        Fbp(5),
+        Br(2),
+        Bp(1),
+        Cb(7),
+        Sethi(4);
+
+        private final int value;
+
+        private Op2s(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
     public enum Op3s {
-        Add((0x00 << 19) & 0x01F80000, "add"),
-        And((0x01 << 19) & 0x01F80000, "and"),
-        Or((0x02 << 19) & 0x01F80000, "or"),
-        Xor((0x03 << 19) & 0x01F80000, "xor"),
-        Sub((0x04 << 19) & 0x01F80000, "sub"),
-        Andn((0x05 << 19) & 0x01F80000, "andn"),
-        Orn((0x06 << 19) & 0x01F80000, "orn"),
-        Xnor((0x07 << 19) & 0x01F80000, "xnor"),
-        Addc((0x08 << 19) & 0x01F80000, "addc"),
-        Mulx((0x09 << 19) & 0x01F80000, "mulx"),
-        Umul((0x0A << 19) & 0x01F80000, "umul"),
-        Smul((0x0B << 19) & 0x01F80000, "smul"),
-        Subc((0x0C << 19) & 0x01F80000, "subc"),
-        Udivx((0x0D << 19) & 0x01F80000, "udivx"),
-        Udiv((0x0E << 19) & 0x01F80000, "udiv"),
-        Sdiv((0x0F << 19) & 0x01F80000, "sdiv"),
+        Add(0x00, "add"),
+        And(0x01, "and"),
+        Or(0x02, "or"),
+        Xor(0x03, "xor"),
+        Sub(0x04, "sub"),
+        Andn(0x05, "andn"),
+        Orn(0x06, "orn"),
+        Xnor(0x07, "xnor"),
+        Addc(0x08, "addc"),
+        Mulx(0x09, "mulx"),
+        Umul(0x0A, "umul"),
+        Smul(0x0B, "smul"),
+        Subc(0x0C, "subc"),
+        Udivx(0x0D, "udivx"),
+        Udiv(0x0E, "udiv"),
+        Sdiv(0x0F, "sdiv"),
+
+        Addcc(0x10, "addcc"),
+        Andcc(0x11, "andcc"),
+        Orcc(0x12, "orcc"),
+        Xorcc(0x13, "xorcc"),
+        Subcc(0x14, "subcc"),
+        Andncc(0x15, "andncc"),
+        Orncc(0x16, "orncc"),
+        Xnorcc(0x17, "xnorcc"),
+        Addccc(0x18, "addccc"),
+        Mulxcc(0x19, "mulxcc"),
+        Umulcc(0x1A, "umulcc"),
+        Smulcc(0x1B, "smulcc"),
+        Subccc(0x1C0, "subccc"),
+        Udivcc(0x1E, "udivcc"),
+        Sdivcc(0x1F, "sdivcc"),
 
-        Addcc((0x10 << 19) & 0x01F80000, "addcc"),
-        Andcc((0x11 << 19) & 0x01F80000, "andcc"),
-        Orcc((0x12 << 19) & 0x01F80000, "orcc"),
-        Xorcc((0x13 << 19) & 0x01F80000, "xorcc"),
-        Subcc((0x14 << 19) & 0x01F80000, "subcc"),
-        Andncc((0x15 << 19) & 0x01F80000, "andncc"),
-        Orncc((0x16 << 19) & 0x01F80000, "orncc"),
-        Xnorcc((0x17 << 19) & 0x01F80000, "xnorcc"),
-        Addccc((0x18 << 19) & 0x01F80000, "addccc"),
-        Mulxcc((0x19 << 19) & 0x01F80000, "mulxcc"),
-        Umulcc((0x1A << 19) & 0x01F80000, "umulcc"),
-        Smulcc((0x1B << 19) & 0x01F80000, "smulcc"),
-        Subccc((0x1C << 19) & 0x01F80000, "subccc"),
-        Udivcc((0x1E << 19) & 0x01F80000, "udivcc"),
-        Sdivcc((0x1F << 19) & 0x01F80000, "sdivcc"),
+        Taddcc(0x20, "taddcc"),
+        Tsubcc(0x21, "tsubcc"),
+        Taddcctv(0x22, "taddcctv"),
+        Tsubcctv(0x23, "tsubcctv"),
+        Mulscc(0x24, "mulscc"),
+        Sll(0x25, "sll"),
+        Sllx(0x25, "sllx"),
+        Srl(0x26, "srl"),
+        Srlx(0x26, "srlx"),
+        Sra(0x27, "srax"),
+        Srax(0x27, "srax"),
+        Rdreg(0x28, "rdreg"),
+        Membar(0x28, "membar"),
+
+        Flushw(0x2B, "flushw"),
+        Movcc(0x2C, "movcc"),
+        Sdivx(0x2D, "sdivx"),
+        Popc(0x2E, "popc"),
+        Movr(0x2F, "movr"),
+
+        Sir(0x30, "sir"),
+        Wrreg(0x30, "wrreg"),
+        Saved(0x31, "saved"),
 
-        Taddcc((0x20 << 19) & 0x01F80000, "taddcc"),
-        Tsubcc((0x21 << 19) & 0x01F80000, "tsubcc"),
-        Taddcctv((0x22 << 19) & 0x01F80000, "taddcctv"),
-        Tsubcctv((0x23 << 19) & 0x01F80000, "tsubcctv"),
-        Mulscc((0x23 << 19) & 0x01F80000, "mulscc"),
-        Sll((0x25 << 19) & 0x01F80000, "sll"),
-        Sllx((0x25 << 19) & 0x01F80000, "sllx"),
-        Srl((0x26 << 19) & 0x01F80000, "srl"),
-        Srlx((0x26 << 19) & 0x01F80000, "srlx"),
-        Sra((0x27 << 19) & 0x01F80000, "srax"),
-        Srax((0x27 << 19) & 0x01F80000, "srax"),
-        Rdreg((0x27 << 19) & 0x01F80000, "rdreg"),
-        Membar((0x27 << 19) & 0x01F80000, "membar");
+        Fpop1(0x34, "fpop1"),
+        Fpop2(0x35, "fpop2"),
+        Impdep1(0x36, "impdep1"),
+        Impdep2(0x37, "impdep2"),
+        Jmpl(0x38, "jmpl"),
+        Rett(0x39, "rett"),
+        Trap(0x3a, "trap"),
+        Flush(0x3b, "flush"),
+        Save(0x3c, "save"),
+        Restore(0x3d, "restore"),
+        Done(0x3e, "done"),
+        Retry(0x3e, "retry"),
+
+        Lduw(0x00, "lduw"),
+        Ldub(0x01, "ldub"),
+        Lduh(0x02, "lduh"),
+        Ldd(0x03, "ldd"),
+        Stw(0x04, "stw"),
+        Stb(0x05, "stb"),
+        Sth(0x06, "sth"),
+        Std(0x07, "std"),
+        Ldsw(0x08, "ldsw"),
+        Ldsb(0x09, "ldsb"),
+        Ldsh(0x0A, "ldsh"),
+        Ldx(0x0b, "ldx"),
+        Stx(0x0e, "stx"),
+
+        Ldf(0x20, "ldf"),
+        Ldfsr(0x21, "ldfsr"),
+        Ldaf(0x22, "ldaf"),
+        Lddf(0x23, "lddf"),
+        Stf(0x24, "stf"),
+        Stfsr(0x25, "stfsr"),
+        Staf(0x26, "staf"),
+        Stdf(0x27, "stdf");
 
         private final int value;
         private final String operator;
@@ -114,23 +389,214 @@
         }
     }
 
-    @SuppressWarnings("unused")
-    public SPARCAssembler(TargetDescription target) {
-        super(target);
-        // TODO Auto-generated constructor stub
-        SPARC sparc;
+    public enum Opfs {
+        Fmovs(0x01, "fmovs"),
+        Fmovd(0x02, "fmovd"),
+        Fmovq(0x03, "fmovq"),
+        Fnegs(0x05, "fnegs"),
+        Fnegd(0x06, "fnegd"),
+        Fnegq(0x07, "fnegq"),
+        Fabss(0x09, "fabss"),
+        Fabsd(0x0A, "fabsd"),
+        Fabsq(0x0B, "fabsq"),
+        Fadds(0x41, "fadds"),
+        Faddd(0x42, "faddd"),
+        Faddq(0x43, "faddq"),
+        Fsubs(0x45, "fsubs"),
+        Fsubd(0x46, "fsubd"),
+        Fsubq(0x47, "fsubq"),
+        Fmuls(0x49, "fmuls"),
+        Fmuld(0x4A, "fmuld"),
+        Fdivs(0x4C, "fdivs"),
+        Fdivd(0x4D, "fdivd"),
+        Fdivq(0x4E, "fdivq"),
+
+        Fsqrts(0x29, "fsqrts"),
+        Fsqrtd(0x2A, "fsqrtd"),
+        Fsqrtq(0x2B, "fsqrtq"),
+
+        Fsmuld(0x69, "fsmuld"),
+        Fmulq(0x6B, "fmulq"),
+        Fdmuldq(0x6E, "fdmulq"),
+
+        Fstoi(0xD1, "fstoi"),
+        Fdtoi(0xD2, "fdtoi");
+
+        private final int value;
+        private final String operator;
+
+        private Opfs(int value, String op) {
+            this.value = value;
+            this.operator = op;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
+    }
+
+    public enum MembarMask {
+        StoreStore(1 << 3, "storestore"),
+        LoadStore(1 << 2, "loadstore"),
+        StoreLoad(1 << 1, "storeload"),
+        LoadLoad(1 << 0, "loadload"),
+        Sync(1 << 6, "sync"),
+        MemIssue(1 << 5, "memissue"),
+        LookAside(1 << 4, "lookaside");
+
+        private final int value;
+        private final String operator;
+
+        private MembarMask(int value, String op) {
+            this.value = value;
+            this.operator = op;
+        }
+
+        public int getValue() {
+            return value | 0x2000;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
+    }
+
+    public enum CC {
+        Icc(4, "icc"),
+        Xcc(6, "xcc"),
+        Ptrcc(HotSpotGraalRuntime.wordKind() == Kind.Long ? Xcc.getValue() : Icc.getValue(), "ptrcc"),
+        Fcc0(0, "fcc0"),
+        Fcc1(1, "fcc1"),
+        Fcc2(2, "fcc2"),
+        Fcc3(3, "fcc3");
+
+        private final int value;
+        private final String operator;
+
+        private CC(int value, String op) {
+            this.value = value;
+            this.operator = op;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
     }
 
-    public static final int rs1(int val) {
-        return val;
+    public enum ConditionFlag {
+        // for FBfcc & FBPfcc instruction
+
+        F_Never(0, "f_never"),
+        F_NotEqual(1, "f_notEqual"),
+        F_NotZero(1, "f_notZero"),
+        F_LessOrGreater(2, "f_lessOrGreater"),
+        F_UnorderedOrLess(3, "f_unorderedOrLess"),
+        F_Less(4, "f_less"),
+        F_UnorderedOrGreater(5, "f_unorderedOrGreater"),
+        F_Greater(6, "f_greater"),
+        F_Unordered(7, "f_unordered"),
+        F_Always(8, "f_always"),
+        F_Equal(9, "f_equal"),
+        F_Zero(9, "f_zero"),
+        F_UnorderedOrEqual(10, "f_unorderedOrEqual"),
+        F_GreaterOrEqual(11, "f_greaterOrEqual"),
+        F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"),
+        F_LessOrEqual(13, "f_lessOrEqual"),
+        F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"),
+        F_Ordered(15, "f_ordered"),
+
+        // for integers
+        Never(0, "never"),
+        Equal(1, "equal"),
+        Zero(1, "zero"),
+        LessEqual(2, "lessEqual"),
+        Less(3, "less"),
+        LessEqualUnsigned(4, "lessEqualUnsigned"),
+        LessUnsigned(5, "lessUnsigned"),
+        CarrySet(5, "carrySet"),
+        Negative(6, "negative"),
+        OverflowSet(7, "overflowSet"),
+        Always(8, "always"),
+        NotEqual(9, "notEqual"),
+        NotZero(9, "notZero"),
+        Greater(10, "greater"),
+        GreaterEqual(11, "greaterEqual"),
+        GreaterUnsigned(12, "greaterUnsigned"),
+        GreaterEqualUnsigned(13, "greaterEqualUnsigned"),
+        CarryClear(13, "carryClear"),
+        Positive(14, "positive"),
+        OverflowClear(15, "overflowClear");
+
+        private final int value;
+        private final String operator;
+
+        private ConditionFlag(int value, String op) {
+            this.value = value;
+            this.operator = op;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
     }
 
-    public static final int rs2(int val) {
-        return val;
+    public enum RCondition {
+        Rc_z(1, "rc_z"),
+        Rc_lez(2, "rc_lez"),
+        Rc_lz(3, "rc_lz"),
+        Rc_nz(5, "rc_nz"),
+        Rc_gz(6, "rc_gz"),
+        Rc_gez(7, "rc_gez"),
+        Rc_last(Rc_gez.getValue(), "rc_last");
+
+        private final int value;
+        private final String operator;
+
+        private RCondition(int value, String op) {
+            this.value = value;
+            this.operator = op;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
     }
 
-    public static final int rd(int val) {
-        return val;
+    public static int getFloatEncoding(int reg) {
+        assert reg < 32;
+        return reg;
+    }
+
+    public static int getDoubleEncoding(int reg) {
+            assert reg < 64 && ((reg & 1) == 0);
+            // ignore v8 assertion for now
+            return (reg & 0x1e) | ((reg & 0x20) >> 5);
+    }
+
+    public static int getQuadEncoding(int reg) {
+            assert reg < 64 && ((reg & 3) == 0);
+            // ignore v8 assertion for now
+            return (reg & 0x1c) | ((reg & 0x20) >> 5);
+    }
+
+    public SPARCAssembler(TargetDescription target, @SuppressWarnings("unused") RegisterConfig registerConfig) {
+        super(target);
     }
 
     public static final int sx1 = 0x00001000;
@@ -140,372 +606,1004 @@
         return x & ((1 << nbits) - 1);
     }
 
-    public final void add(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Add.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    private static final int max13 = ((1 << 12) - 1);
+    private static final int min13 = -(1 << 12);
+
+    public static boolean isSimm13(int src) {
+        return min13 <= src && src <= max13;
+    }
+
+    public static final int hi22(int x) {
+        return x >> 10;
+    }
+
+    public static final int lo10(int x) {
+        return x & ((1 << 10) - 1);
+    }
+
+    @Override
+    @SuppressWarnings("unused")
+    public void jmp(Label l) {
+         new Bpa(this, l);
     }
 
-    public final void add(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Add.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Add extends Fmt3b {
+        public Add(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Add.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Add(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Add.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Addc extends Fmt3b {
+        public Addc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Addc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Addc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Addc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Addcc extends Fmt3b {
+        public Addcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Addcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Addcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Addcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Addccc extends Fmt3b {
+        public Addccc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Addccc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Addccc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Addccc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void addcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Addcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class And extends Fmt3b {
+        public And(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.And.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public And(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.And.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Andcc extends Fmt3b {
+        public Andcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Andcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Andcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Andcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Andn extends Fmt3b {
+        public Andn(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Andn.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Andn(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Andn.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void addcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Addcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Andncc extends Fmt3b {
+        public Andncc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Andncc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Andncc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Andncc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Bpa extends Fmt2c {
+        public Bpa(SPARCAssembler masm, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Always.getValue(),
+                            Op2s.Bp.getValue(), CC.Icc.getValue(), 1, simmm19);
+        }
+        public Bpa(SPARCAssembler masm, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Always.getValue(),
+                            Op2s.Bp.getValue(), CC.Icc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void addc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Addc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Bpcc extends Fmt2c {
+        public Bpcc(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.CarryClear.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpcc(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.CarryClear.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void addc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Addc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Bpcs extends Fmt2c {
+        public Bpcs(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.CarrySet.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpcs(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.CarrySet.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void addccc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Addccc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Bpe extends Fmt2c {
+        public Bpe(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Equal.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpe(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Equal.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    public static class Bpg extends Fmt2c {
+        public Bpg(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Greater.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpg(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Greater.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void addccc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Addccc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Bpge extends Fmt2c {
+        public Bpge(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.GreaterEqual.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpge(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.GreaterEqual.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void and(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.And.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Bpgu extends Fmt2c {
+        public Bpgu(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.GreaterUnsigned.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpgu(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.GreaterUnsigned.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    public static class Bpl extends Fmt2c {
+        public Bpl(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Less.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpl(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Less.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void and(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.And.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Bple extends Fmt2c {
+        public Bple(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.LessEqual.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bple(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.LessEqual.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void andcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Andcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Bpleu extends Fmt2c {
+        public Bpleu(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.LessEqualUnsigned.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpleu(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.LessEqualUnsigned.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    public static class Bpn extends Fmt2c {
+        public Bpn(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Never.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpn(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Never.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void andcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Andcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Bpne extends Fmt2c {
+        public Bpne(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.NotZero.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpne(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.NotZero.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void andn(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Andn.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Bpneg extends Fmt2c {
+        public Bpneg(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Negative.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpneg(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Negative.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void andn(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Andn.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Bppos extends Fmt2c {
+        public Bppos(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Positive.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bppos(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Positive.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    public static class Bpvc extends Fmt2c {
+        public Bpvc(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.OverflowClear.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpvc(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.OverflowClear.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
     }
 
-    public final void andncc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Andncc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Bpvs extends Fmt2c {
+        public Bpvs(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.OverflowSet.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpvs(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.OverflowSet.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    private static int patchUnbound(SPARCAssembler masm, Label label) {
+        label.addPatchAt(masm.codeBuffer.position());
+        return 0;
+    }
+
+    public static class Fadds extends Fmt3p {
+        public Fadds(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fadds.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Faddd extends Fmt3p {
+        public Faddd(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Faddd.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void andncc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Andncc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Faddq extends Fmt3p {
+        public Faddq(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Faddq.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fdivs extends Fmt3p {
+        public Fdivs(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdivs.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void mulscc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Mulscc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Fdivd extends Fmt3p {
+        public Fdivd(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdivd.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmuls extends Fmt3p {
+        public Fmuls(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fmuls.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmuld extends Fmt3p {
+        public Fmuld(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fmuld.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void mulscc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Mulscc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Fnegs extends Fmt3n {
+        public Fnegs(SPARCAssembler masm, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnegs.getValue(),
+                  src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnegd extends Fmt3n {
+        public Fnegd(SPARCAssembler masm, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnegd.getValue(),
+                  src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fstoi extends Fmt3n {
+        public Fstoi(SPARCAssembler masm, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fstoi.getValue(),
+                  src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fdtoi extends Fmt3n {
+        public Fdtoi(SPARCAssembler masm, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdtoi.getValue(),
+                  src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Flushw extends Fmt3r {
+        public Flushw(SPARCAssembler masm) {
+            super(masm, Ops.ArithOp.getValue(), 0, Op3s.Flushw.getValue());
+        }
     }
 
-    public final void mulx(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Mulx.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Fsqrtd extends Fmt3p {
+        public Fsqrtd(SPARCAssembler masm, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fsqrtd.getValue(),
+                  0, src2.encoding(), dst.encoding());
+        }
+    }
+
+
+    public static class Fsubs extends Fmt3p {
+        public Fsubs(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fsubs.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void mulx(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Mulx.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Fsubd extends Fmt3p {
+        public Fsubd(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fsubd.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void or(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Or.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Fsubq extends Fmt3p {
+        public Fsubq(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fsubq.getValue(),
+                    src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Jmpl extends Fmt3b {
+        public Jmpl(SPARCAssembler asm, SPARCAddress src, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Jmpl.getValue(),
+                  src.getBase().encoding(), src.getDisplacement(), dst.encoding());
+        }
+    }
+
+    public static class Lddf extends Fmt3b {
+        public Lddf(SPARCAssembler masm, SPARCAddress src, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Lddf.getValue(),
+                  src.getBase().encoding(), src.getDisplacement(), dst.encoding());
+        }
     }
 
-    public final void or(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Or.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Ldf extends Fmt3b {
+        public Ldf(SPARCAssembler masm, SPARCAddress src, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Ldf.getValue(),
+                  src.getBase().encoding(), src.getDisplacement(), dst.encoding());
+        }
+    }
+
+    public static class Ldsb extends Fmt3b {
+        public Ldsb(SPARCAssembler masm, SPARCAddress src, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Ldsb.getValue(),
+                  src.getBase().encoding(), src.getDisplacement(), dst.encoding());
+        }
+    }
+
+    public static class Ldsh extends Fmt3b {
+        public Ldsh(SPARCAssembler masm, SPARCAddress src, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Ldsh.getValue(),
+                  src.getBase().encoding(), src.getDisplacement(), dst.encoding());
+        }
+    }
+
+    public static class Ldsw extends Fmt3b {
+        public Ldsw(SPARCAssembler masm, SPARCAddress src, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Ldsw.getValue(),
+                  src.getBase().encoding(), src.getDisplacement(), dst.encoding());
+        }
+    }
+
+    public static class Lduw extends Fmt3b {
+        public Lduw(SPARCAssembler masm, SPARCAddress src, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Lduw.getValue(),
+                  src.getBase().encoding(), src.getDisplacement(), dst.encoding());
+        }
     }
 
-    public final void orcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Orcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Ldx extends Fmt3b {
+        public Ldx(SPARCAssembler masm, SPARCAddress src, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Ldx.getValue(),
+                  src.getBase().encoding(), src.getDisplacement(), dst.encoding());
+        }
+    }
+
+    public static class Membar extends Fmt3b {
+        public Membar(SPARCAssembler masm, int barriers) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Membar.getValue(),
+                  SPARC.r15.encoding(), ImmedTrue | barriers, SPARC.r0.encoding());
+        }
     }
 
-    public final void orcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Orcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Movcc extends Fmt4c {
+        public Movcc(SPARCAssembler masm, ConditionFlag cond, CC cca, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Movcc.getValue(), cond.getValue(), cca.getValue(),
+                  src2.encoding(), dst.encoding());
+        }
+        public Movcc(SPARCAssembler masm, ConditionFlag cond, CC cca, int simm11a, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Movcc.getValue(), cond.getValue(), cca.getValue(),
+                  simm11a, dst.encoding());
+        }
+    }
+
+    public static class Movr extends Fmt3f {
+        public Movr(SPARCAssembler masm, RCondition rc,  Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Movr.getValue(), rc.getValue(),
+                  src1.encoding(), src2.encoding(), dst.encoding());
+        }
+        public Movr(SPARCAssembler masm, RCondition rc, Register src1, int simm10, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Movr.getValue(), rc.getValue(),
+                    src1.encoding(), simm10, dst.encoding());
+        }
     }
 
-    public final void orn(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Orn.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    @Deprecated
+    public static class Mulscc extends Fmt3b {
+        @Deprecated
+        public Mulscc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Mulscc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        @Deprecated
+        public Mulscc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Mulscc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void orn(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Orn.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Mulx extends Fmt3b {
+        public Mulx(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Mulx.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Mulx(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Mulx.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class NullCheck extends Fmt3b {
+        public NullCheck(SPARCAssembler masm, SPARCAddress src) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Ldx.getValue(),
+                            src.getBase().encoding(), src.getDisplacement(), SPARC.r0.encoding());
+        }
     }
 
-    public final void orncc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Orncc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Or extends Fmt3b {
+        public Or(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Or.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Or(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Or.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Orcc extends Fmt3b {
+        public Orcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Orcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Orcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Orcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void orncc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Orncc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Orn extends Fmt3b {
+        public Orn(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Orn.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Orn(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Orn.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void rdy(Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()));
+    public static class Orncc extends Fmt3b {
+        public Orncc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Orncc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Orncc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Orncc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Popc extends Fmt3b {
+        public Popc(SPARCAssembler masm, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Popc.getValue(), 0, simm13, dst.encoding());
+        }
+        public Popc(SPARCAssembler masm, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Popc.getValue(), 0, src2.encoding(), dst.encoding());
+        }
     }
 
     // A.44 Read State Register
 
-    public final void rdccr(Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x00008000);
+    @Deprecated
+    public static class Rdy extends Fmt3q {
+        public Rdy(SPARCAssembler masm, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Rdreg.getValue(), 0, dst.encoding());
+        }
+    }
+
+    public static class Rdccr extends Fmt3q {
+        public Rdccr(SPARCAssembler masm, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Rdreg.getValue(), 2, dst.encoding());
+        }
     }
 
-    public final void rdasi(Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x0000C000);
+    public static class Rdasi extends Fmt3q {
+        public Rdasi(SPARCAssembler masm, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Rdreg.getValue(), 3, dst.encoding());
+        }
+    }
+
+    public static class Rdtick extends Fmt3q {
+        public Rdtick(SPARCAssembler masm, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Rdreg.getValue(), 4, dst.encoding());
+        }
+    }
+
+    public static class Rdpc extends Fmt3q {
+        public Rdpc(SPARCAssembler masm, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Rdreg.getValue(), 5, dst.encoding());
+        }
+    }
+
+    public static class Rdfprs extends Fmt3q {
+        public Rdfprs(SPARCAssembler masm, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Rdreg.getValue(), 6, dst.encoding());
+        }
     }
 
-    public final void rdtick(Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x00010000);
+    public static class Restore extends Fmt3b {
+        public Restore(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Restore.getValue(),
+                  src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Restored extends Fmt3r {
+        public Restored(SPARCAssembler asm) {
+            super(asm, Ops.ArithOp.getValue(), 1, Op3s.Saved.getValue());
+        }
+    }
+
+    public static class Return extends Fmt3d {
+        public Return(SPARCAssembler masm, Register src1, int simm13) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Rett.getValue(), src1.encoding(), simm13);
+        }
+        public Return(SPARCAssembler masm, Register src1, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Rett.getValue(), src1.encoding(), src2.encoding());
+        }
     }
 
-    public final void rdpc(Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x00014000);
+    public static class Save extends Fmt3b {
+        public Save(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Save.getValue(),
+                  src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void rdfprs(Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x00018000);
+    public static class Saved extends Fmt3r {
+        public Saved(SPARCAssembler asm) {
+            super(asm, Ops.ArithOp.getValue(), 0, Op3s.Saved.getValue());
+        }
+    }
+
+    @Deprecated
+    public static class Sdiv extends Fmt3b {
+        @Deprecated
+        public Sdiv(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sdiv.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        @Deprecated
+        public Sdiv(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sdiv.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
     @Deprecated
-    public final void sdiv(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sdiv.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Sdivcc extends Fmt3b {
+        @Deprecated
+        public Sdivcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sdivcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        @Deprecated
+        public Sdivcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sdivcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Sdivx extends Fmt3b {
+        public Sdivx(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sdivx.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Sdivx(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sdivx.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Sethi extends Fmt2a {
+        public Sethi(SPARCAssembler masm, int simm22, Register dst) {
+            super(masm, Ops.BranchOp.getValue(), Op2s.Sethi.getValue(), simm22, dst.encoding());
+        }
+    }
+
+    public static class Sir extends Fmt3b {
+        public Sir(SPARCAssembler asm, int simm13) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Sir.getValue(),
+                  SPARC.r0.encoding(), simm13, SPARC.r15.encoding());
+        }
+    }
+
+    public static class Sll extends Fmt3b {
+        public Sll(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sll.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Sll(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sll.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Sllx extends Fmt3b {
+        public Sllx(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sllx.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Sllx(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sllx.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Smul extends Fmt3b {
+        public Smul(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Smul.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Smul(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Smul.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
     @Deprecated
-    public final void sdiv(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sdiv.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Smulcc extends Fmt3b {
+        public Smulcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Smulcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Smulcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Smulcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Sra extends Fmt3b {
+        public Sra(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sra.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Sra(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sra.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    @Deprecated
-    public final void sdivcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sdivcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Srax extends Fmt3b {
+        public Srax(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Srax.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Srax(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Srax.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Srl extends Fmt3b {
+        public Srl(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Srl.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Srl(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Srl.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Srlx extends Fmt3b {
+        public Srlx(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Srlx.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Srlx(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Srlx.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
     @Deprecated
-    public final void sdivcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sdivcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
-    }
-
-    public final void sll(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sll.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void sll(Register src1, int imm5a, Register dst) {
-        assert imm5a < 0x40;
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sll.getValue() | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    public static class Stbar extends Fmt3b {
+        public Stbar(SPARCAssembler masm) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Membar.getValue(),
+                  SPARC.r15.encoding(), 0, SPARC.r0.encoding());
+        }
     }
 
-    public final void sllx(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sllx.getValue() | sx1 | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Stb extends Fmt3b {
+        public Stb(SPARCAssembler masm, Register dst, SPARCAddress addr) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Stb.getValue(),
+                            addr.getBase().encoding(), addr.getDisplacement(), dst.encoding());
+        }
     }
 
-    public final void sllx(Register src1, int imm5a, Register dst) {
-        assert imm5a < 0x40;
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sllx.getValue() | sx1 | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
-    }
-
-    public final void smul(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Smul.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void smul(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Smul.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Sth extends Fmt3b {
+        public Sth(SPARCAssembler masm, Register dst, SPARCAddress addr) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sth.getValue(),
+                            addr.getBase().encoding(), addr.getDisplacement(), dst.encoding());
+        }
     }
 
-    public final void smulcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Smulcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void smulcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Smulcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Stw extends Fmt3b {
+        public Stw(SPARCAssembler masm, Register dst, SPARCAddress addr) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Stw.getValue(),
+                            addr.getBase().encoding(), addr.getDisplacement(), dst.encoding());
+        }
     }
 
-    public final void sra(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sra.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void sra(Register src1, int imm5a, Register dst) {
-        assert imm5a < 0x40;
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sra.getValue() | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    public static class Stx extends Fmt3b {
+        public Stx(SPARCAssembler masm, Register dst, SPARCAddress addr) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Stx.getValue(),
+                            addr.getBase().encoding(), addr.getDisplacement(), dst.encoding());
+        }
     }
 
-    public final void srax(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Srax.getValue() | sx1 | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Sub extends Fmt3b {
+        public Sub(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sub.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Sub(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Sub.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void srax(Register src1, int imm5a, Register dst) {
-        assert imm5a < 0x40;
-        emitInt(Ops.ArithOp.getValue() | Op3s.Srax.getValue() | sx1 | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
-    }
-
-    public final void srl(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Srl.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void srl(Register src1, int imm5a, Register dst) {
-        assert imm5a < 0x40;
-        emitInt(Ops.ArithOp.getValue() | Op3s.Srl.getValue() | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    public static class Subc extends Fmt3b {
+        public Subc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Subc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Subc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Subc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void srlx(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Srlx.getValue() | sx1 | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void srlx(Register src1, int imm5a, Register dst) {
-        assert imm5a < 0x40;
-        emitInt(Ops.ArithOp.getValue() | Op3s.Srlx.getValue() | sx1 | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
-    }
-
-    public final void sub(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sub.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Subcc extends Fmt3b {
+        public Subcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Subcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Subcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Subcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void sub(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Sub.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
-    }
-
-    public final void subcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Subcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Subccc extends Fmt3b {
+        public Subccc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Subccc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Subccc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Subccc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void subcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Subcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
-    }
-
-    public final void subc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Subc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void subc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Subc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Ta extends Fmt4a {
+        public Ta(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Always.getValue());
+        }
+        public Ta(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Always.getValue());
+        }
     }
 
-    public final void subccc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Subccc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void subccc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Subccc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
-    }
-
-    public final void taddcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Taddcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void taddcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Taddcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Taddcc extends Fmt3b {
+        public Taddcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Taddcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Taddcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Taddcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void taddcctv(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Taddcctv.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void taddcctv(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Taddcctv.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    @Deprecated
+    public static class Taddcctv extends Fmt3b {
+        @Deprecated
+        public Taddcctv(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Taddcctv.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        @Deprecated
+        public Taddcctv(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), dst.encoding(), Op3s.Taddcctv.getValue(), src2.encoding(), src1.encoding());
+        }
     }
 
-    public final void tsubcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Tsubcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void tsubcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Tsubcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
-    }
-
-    public final void tsubcctv(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Tsubcctv.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void tsubcctv(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Tsubcctv.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Tsubcc extends Fmt3b {
+        public Tsubcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Tsubcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Tsubcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Tsubcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
     @Deprecated
-    public final void udiv(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Udiv.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Tsubcctv extends Fmt3b {
+        @Deprecated
+        public Tsubcctv(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Tsubcctv.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        @Deprecated
+        public Tsubcctv(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Tsubcctv.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
     @Deprecated
-    public final void udiv(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Udiv.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Udiv extends Fmt3b {
+        @Deprecated
+        public Udiv(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Udiv.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        @Deprecated
+        public Udiv(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Udiv.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Udivcc extends Fmt3b {
+        public Udivcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Udivcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Udivcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Udivcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    @Deprecated
-    public final void udivcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Udivcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Udivx extends Fmt3b {
+        public Udivx(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Udivx.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Udivx(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Udivx.getValue(), dst.encoding(), src2.encoding(), src1.encoding());
+        }
+    }
+
+    public static class Umul extends Fmt3b {
+        public Umul(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Umul.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Umul(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Umul.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Umulcc extends Fmt3b {
+        public Umulcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Umulcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Umulcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Umulcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
     @Deprecated
-    public final void udivcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Udivcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
-    }
-
-    public final void udivx(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Udivx.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void udivx(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Udivx.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Wry extends Fmt3b {
+        @Deprecated
+        public Wry(SPARCAssembler masm, int simm13, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Wrreg.getValue(), 0, src2.encoding(), simm13);
+        }
+        @Deprecated
+        public Wry(SPARCAssembler masm, Register src1, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Wrreg.getValue(), 0, src2.encoding(), src1.encoding());
+        }
     }
 
-    public final void umul(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Umul.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Wrccr extends Fmt3b {
+        public Wrccr(SPARCAssembler masm, int simm13, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Wrreg.getValue(), 2, src2.encoding(), simm13);
+        }
+        public Wrccr(SPARCAssembler masm, Register src1, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Wrreg.getValue(), 2, src2.encoding(), src1.encoding());
+        }
     }
 
-    public final void umul(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Umul.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
-    }
-
-    public final void umulcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Umulcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void umulcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Umulcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Wrasi extends Fmt3b {
+        public Wrasi(SPARCAssembler masm, int simm13, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Wrreg.getValue(), 3, src2.encoding(), simm13);
+        }
+        public Wrasi(SPARCAssembler masm, Register src1, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Wrreg.getValue(), 3, src2.encoding(), src1.encoding());
+        }
     }
 
-    public final void xor(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Xor.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Wrfprs extends Fmt3b {
+        public Wrfprs(SPARCAssembler masm, int simm13, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Wrreg.getValue(), 6, src2.encoding(), simm13);
+        }
+        public Wrfprs(SPARCAssembler masm, Register src1, Register src2) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Wrreg.getValue(), 6, src2.encoding(), src1.encoding());
+        }
     }
 
-    public final void xor(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Xor.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
-    }
-
-    public final void xorcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Xorcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void xorcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Xorcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Xor extends Fmt3b {
+        public Xor(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Xor.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Xor(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Xor.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void xnor(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Xnor.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
-    }
-
-    public final void xnor(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Xnor.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Xorcc extends Fmt3b {
+        public Xorcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Xorcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Xorcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Xorcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void xnorcc(Register src1, Register src2, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Xnorcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    public static class Xnor extends Fmt3b {
+        public Xnor(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Xnor.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Xnor(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Xnor.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
 
-    public final void xnorcc(Register src1, int simm13, Register dst) {
-        emitInt(Ops.ArithOp.getValue() | Op3s.Xnorcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    public static class Xnorcc extends Fmt3b {
+        public Xnorcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Xnorcc.getValue(), src1.encoding(), simm13, dst.encoding());
+        }
+        public Xnorcc(SPARCAssembler masm, Register src1, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Xnorcc.getValue(), src1.encoding(), src2.encoding(), dst.encoding());
+        }
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.asm.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCAssembler.CC.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.sparc.*;
+
+public class SPARCMacroAssembler extends SPARCAssembler {
+
+    public SPARCMacroAssembler(TargetDescription target, RegisterConfig registerConfig) {
+        super(target, registerConfig);
+    }
+
+    @SuppressWarnings("unused")
+    public static class Bclr {
+
+        public Bclr(SPARCAssembler asm, Register src, Register dst) {
+            new Andn(asm, dst, src, dst);
+        }
+
+        public Bclr(SPARCAssembler asm, int simm13, Register dst) {
+            new Andn(asm, dst, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Bset {
+
+        public Bset(SPARCAssembler asm, Register src, Register dst) {
+            new Or(asm, dst, src, dst);
+        }
+
+        public Bset(SPARCAssembler asm, int simm13, Register dst) {
+            new Or(asm, dst, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Btog {
+
+        public Btog(SPARCAssembler asm, Register src, Register dst) {
+            new Xor(asm, dst, src, dst);
+        }
+
+        public Btog(SPARCAssembler asm, int simm13, Register dst) {
+            new Xor(asm, dst, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Btst {
+
+        public Btst(SPARCAssembler asm, Register src1, Register src2) {
+            new Andcc(asm, src1, src2, SPARC.g0);
+        }
+
+        public Btst(SPARCAssembler asm, Register src1, int simm13) {
+            new Andcc(asm, src1, simm13, SPARC.g0);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Clr {
+
+        public Clr(SPARCAssembler asm, Register dst) {
+            new Or(asm, SPARC.g0, SPARC.g0, dst);
+        }
+
+        public Clr(SPARCAssembler asm, SPARCAddress addr) {
+            new Stw(asm, SPARC.g0, addr);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Clrb {
+
+        public Clrb(SPARCAssembler asm, SPARCAddress addr) {
+            new Stb(asm, SPARC.g0, addr);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Clrh {
+
+        public Clrh(SPARCAssembler asm, SPARCAddress addr) {
+            new Sth(asm, SPARC.g0, addr);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Clrx {
+
+        public Clrx(SPARCAssembler asm, SPARCAddress addr) {
+            new Stx(asm, SPARC.g0, addr);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Clruw {
+
+        public Clruw(SPARCAssembler asm, Register src1, Register dst) {
+            assert src1.encoding() != dst.encoding();
+            new Srl(asm, src1, SPARC.g0, dst);
+        }
+
+        public Clruw(SPARCAssembler asm, Register dst) {
+            new Srl(asm, dst, SPARC.g0, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Cmp {
+
+        public Cmp(SPARCAssembler asm, Register a, Register b) {
+            new Subcc(asm, a, b, SPARC.g0);
+        }
+
+        public Cmp(SPARCAssembler asm, Register a, int simm13) {
+            new Subcc(asm, a, simm13, SPARC.g0);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Dec {
+
+        public Dec(SPARCAssembler asm, Register dst) {
+            new Sub(asm, dst, 1, dst);
+        }
+
+        public Dec(SPARCAssembler asm, int simm13, Register dst) {
+            new Sub(asm, dst, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Deccc {
+
+        public Deccc(SPARCAssembler asm, Register dst) {
+            new Subcc(asm, dst, 1, dst);
+        }
+
+        public Deccc(SPARCAssembler asm, int simm13, Register dst) {
+            new Subcc(asm, dst, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Inc {
+
+        public Inc(SPARCAssembler asm, Register dst) {
+            new Add(asm, dst, 1, dst);
+        }
+
+        public Inc(SPARCAssembler asm, int simm13, Register dst) {
+            new Add(asm, dst, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Inccc {
+
+        public Inccc(SPARCAssembler asm, Register dst) {
+            new Addcc(asm, dst, 1, dst);
+        }
+
+        public Inccc(SPARCAssembler asm, int simm13, Register dst) {
+            new Addcc(asm, dst, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Jmp {
+
+        public Jmp(SPARCAssembler asm, SPARCAddress address) {
+            new Jmpl(asm, address, SPARC.g0);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Neg {
+
+        public Neg(SPARCAssembler asm, Register src2, Register dst) {
+            assert src2.encoding() != dst.encoding();
+            new Sub(asm, SPARC.g0, src2, dst);
+        }
+
+        public Neg(SPARCAssembler asm, Register dst) {
+            new Sub(asm, SPARC.g0, dst, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Not {
+
+        public Not(SPARCAssembler asm, Register src1, Register dst) {
+            assert src1.encoding() != dst.encoding();
+            new Xnor(asm, src1, SPARC.g0, dst);
+        }
+
+        public Not(SPARCAssembler asm, Register dst) {
+            new Xnor(asm, dst, SPARC.g0, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class RestoreWindow {
+
+        public RestoreWindow(SPARCAssembler asm) {
+            new Restore(asm, SPARC.g0, SPARC.g0, SPARC.g0);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Ret {
+
+        public Ret(SPARCAssembler asm) {
+            new Jmpl(asm, new SPARCAddress(SPARC.i0, 8), SPARC.g0);
+
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class SaveWindow {
+
+        public SaveWindow(SPARCAssembler asm) {
+            new Save(asm, SPARC.g0, SPARC.g0, SPARC.g0);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Setuw {
+
+        public Setuw(SPARCAssembler asm, int value, Register dst) {
+            if (value >= 0 && ((value & 0x3FFF) == 0)) {
+                new Sethi(asm, hi22(value), dst);
+            } else if (-4095 <= value && value <= 4096) {
+                new Or(asm, SPARC.g0, value, dst);
+            } else {
+                new Sethi(asm, hi22(value), dst);
+                new Or(asm, dst, lo10(value), dst);
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Setx {
+
+        public Setx(SPARCAssembler asm, long value, Register tmp, Register dst) {
+            int hi = (int) (value >> 32);
+            int lo = (int) (value & ~0);
+
+            if (isSimm13(lo) && value == lo) {
+                new Or(asm, SPARC.g0, lo, dst);
+            } else if (hi == 0) {
+                new Sethi(asm, lo, dst);   // hardware version zero-extends to upper 32
+                if (lo10(lo) != 0) {
+                    new Or(asm, dst, lo10(lo), dst);
+                }
+            } else if (hi == -1) {
+                new Sethi(asm, ~lo, dst);  // hardware version zero-extends to upper 32
+                new Xor(asm, dst, lo10(lo) ^ ~lo10(~0), dst);
+            } else if (lo == 0) {
+                if (isSimm13(hi)) {
+                    new Or(asm, SPARC.g0, hi, dst);
+                } else {
+                    new Sethi(asm, hi, dst);   // hardware version zero-extends to upper 32
+                    if (lo10(hi) != 0) {
+                        new Or(asm, dst, lo10(hi), dst);
+                    }
+                }
+                new Sllx(asm, dst, 32, dst);
+            } else {
+                new Sethi(asm, hi, tmp);
+                new Sethi(asm, lo, dst); // macro assembler version sign-extends
+                if (lo10(hi) != 0) {
+                    new Or(asm, tmp, lo10(hi), tmp);
+                }
+                if (lo10(lo) != 0) {
+                    new Or(asm, dst, lo10(lo), dst);
+                }
+                new Sllx(asm, tmp, 32, tmp);
+                new Or(asm, dst, tmp, dst);
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Signx {
+
+        public Signx(SPARCAssembler asm, Register src1, Register dst) {
+            assert src1.encoding() != dst.encoding();
+            new Sra(asm, src1, SPARC.g0, dst);
+        }
+
+        public Signx(SPARCAssembler asm, Register dst) {
+            new Sra(asm, dst, SPARC.g0, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class Trap {
+
+        public Trap(SPARCAssembler asm, int trap) {
+            assert trap >= 0 && trap <= 0x7f;
+            new Ta(asm, Icc, SPARC.g0, trap);
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Jun 07 14:15:38 2013 +0200
@@ -59,18 +59,13 @@
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.SequentialSwitchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.SwitchRangesOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
-import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaOp;
-import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MembarOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp;
-import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
-import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -215,31 +210,6 @@
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) {
-        AMD64AddressValue loadAddress = asAddressValue(address);
-        Variable result = newVariable(kind);
-        append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
-        return result;
-    }
-
-    @Override
-    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
-        AMD64AddressValue storeAddress = asAddressValue(address);
-        LIRFrameState state = deopting != null ? state(deopting) : null;
-
-        if (isConstant(inputVal)) {
-            Constant c = asConstant(inputVal);
-            if (canStoreConstant(c)) {
-                append(new StoreConstantOp(kind, storeAddress, c, state));
-                return;
-            }
-        }
-
-        Variable input = load(inputVal);
-        append(new StoreOp(kind, storeAddress, input, state));
-    }
-
-    @Override
     public Variable emitAddress(StackSlot address) {
         Variable result = newVariable(target().wordKind);
         append(new StackLeaOp(result, address));
@@ -882,34 +852,6 @@
     }
 
     @Override
-    public void visitCompareAndSwap(CompareAndSwapNode node) {
-        Kind kind = node.newValue().kind();
-        assert kind == node.expected().kind();
-
-        Value expected = loadNonConst(operand(node.expected()));
-        Variable newValue = load(operand(node.newValue()));
-
-        AMD64AddressValue address;
-        int displacement = node.displacement();
-        Value index = operand(node.offset());
-        if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) {
-            assert !runtime.needsDataPatch(asConstant(index));
-            displacement += (int) asConstant(index).asLong();
-            address = new AMD64AddressValue(kind, load(operand(node.object())), displacement);
-        } else {
-            address = new AMD64AddressValue(kind, load(operand(node.object())), load(index), Scale.Times1, displacement);
-        }
-
-        RegisterValue rax = AMD64.rax.asValue(kind);
-        emitMove(rax, expected);
-        append(new CompareAndSwapOp(rax, address, rax, newValue));
-
-        Variable result = newVariable(node.kind());
-        append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE));
-        setResult(node, result);
-    }
-
-    @Override
     public void visitBreakpointNode(BreakpointNode node) {
         JavaType[] sig = new JavaType[node.arguments().size()];
         for (int i = 0; i < sig.length; i++) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/ArraySPARCTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.sparc.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+public class ArraySPARCTest extends SPARCTestBase {
+
+    @Test
+    public void testArray() {
+        compile("testArray1I");
+        compile("testArray1J");
+        compile("testArray1B");
+        compile("testArray1S");
+        compile("testArray1C");
+        compile("testArray1F");
+        compile("testArray1D");
+        compile("testArray1L");
+        compile("testStoreArray1I");
+        compile("testStoreArray1J");
+        compile("testStoreArray1B");
+        compile("testStoreArray1S");
+        compile("testStoreArray1F");
+        compile("testStoreArray1D");
+    }
+
+    public static int testArray1I(int[] array, int i) {
+        return array[i];
+    }
+
+    public static long testArray1J(long[] array, int i) {
+        return array[i];
+    }
+
+    public static byte testArray1B(byte[] array, int i) {
+        return array[i];
+    }
+
+    public static short testArray1S(short[] array, int i) {
+        return array[i];
+    }
+
+    public static char testArray1C(char[] array, int i) {
+        return array[i];
+    }
+
+    public static float testArray1F(float[] array, int i) {
+        return array[i];
+    }
+
+    public static double testArray1D(double[] array, int i) {
+        return array[i];
+    }
+
+    public static Object testArray1L(Object[] array, int i) {
+        return array[i];
+    }
+
+    public static void testStoreArray1I(int[] array, int i, int val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1B(byte[] array, int i, byte val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1S(short[] array, int i, short val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1J(long[] array, int i, long val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1F(float[] array, int i, float val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1D(double[] array, int i, double val) {
+        array[i] = val;
+    }
+
+    public static void main(String[] args) {
+        ArraySPARCTest test = new ArraySPARCTest();
+        for (Method m : ArraySPARCTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/BasicSPARCTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.sparc.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+
+public class BasicSPARCTest extends SPARCTestBase {
+
+    @Test
+    public void testAdd() {
+        compile("testAddConst1I");
+    }
+
+    public int testAddConst1I(int a) {
+        return a + 1;
+    }
+
+    public static void main(String[] args) {
+        BasicSPARCTest test = new BasicSPARCTest();
+        Method[] methods = BasicSPARCTest.class.getMethods();
+        for (Method m : methods) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/ControlSPARCTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.sparc.test;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+public class ControlSPARCTest extends SPARCTestBase {
+
+    @Test
+    public void testControl() {
+        compile("testSwitch1I");
+        // compile("testStatic");
+        compile("testCall");
+        compile("testLookupSwitch1I");
+    }
+
+    public static int testSwitch1I(int a) {
+        switch (a) {
+            case 1:
+                return 2;
+            case 2:
+                return 3;
+            default:
+                return 4;
+        }
+    }
+
+    public static int testLookupSwitch1I(int a) {
+        switch (a) {
+            case 0:
+                return 1;
+            case 1:
+                return 2;
+            case 2:
+                return 3;
+            case 3:
+                return 1;
+            case 4:
+                return 2;
+            case 5:
+                return 3;
+            case 6:
+                return 1;
+            case 7:
+                return 2;
+            case 8:
+                return 3;
+            case 9:
+                return 1;
+            case 10:
+                return 2;
+            case 11:
+                return 3;
+            default:
+                return -1;
+        }
+    }
+
+    @SuppressWarnings("unused") private static Object foo = null;
+
+    public static boolean testStatic(Object o) {
+        foo = o;
+        return true;
+    }
+
+    private static int method(int a, int b) {
+        return a + b;
+    }
+
+    public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) {
+        return method(a, b);
+    }
+
+    public static void main(String[] args) {
+        ControlSPARCTest test = new ControlSPARCTest();
+        for (Method m : ControlSPARCTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/FloatSPARCTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.sparc.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+public class FloatSPARCTest extends SPARCTestBase {
+
+    @Test
+    public void testAdd() {
+        compile("testAdd2F");
+        compile("testAdd2D");
+        // compile("testAddFConst");
+        // compile("testAddConstF");
+        // compile("testAddDConst");
+        // compile("testAddConstD");
+    }
+
+    public static float testAdd2F(float a, float b) {
+        return a + b;
+    }
+
+    public static double testAdd2D(double a, double b) {
+        return a + b;
+    }
+
+    public static float testAddFConst(float a) {
+        return a + 32.0F;
+    }
+
+    public static float testAddConstF(float a) {
+        return 32.0F + a;
+    }
+
+    public static double testAddDConst(double a) {
+        return a + 32.0;
+    }
+
+    public static double testAddConstD(double a) {
+        return 32.0 + a;
+    }
+
+    @Test
+    public void testSub() {
+        compile("testSub2F");
+        compile("testSub2D");
+        // compile("testSubFConst");
+        // compile("testSubConstF");
+        // compile("testSubDConst");
+        // compile("testSubConstD");
+    }
+
+    public static float testSub2F(float a, float b) {
+        return a - b;
+    }
+
+    public static double testSub2D(double a, double b) {
+        return a - b;
+    }
+
+    public static float testSubFConst(float a) {
+        return a - 32.0F;
+    }
+
+    public static float testSubConstF(float a) {
+        return 32.0F - a;
+    }
+
+    public static double testSubDConst(double a) {
+        return a - 32.0;
+    }
+
+    public static double testSubConstD(double a) {
+        return 32.0 - a;
+    }
+
+    @Test
+    public void testMul() {
+        compile("testMul2F");
+        compile("testMul2D");
+        // compile("testMulFConst");
+        // compile("testMulConstF");
+        // compile("testMulDConst");
+        // compile("testMulConstD");
+    }
+
+    public static float testMul2F(float a, float b) {
+        return a * b;
+    }
+
+    public static double testMul2D(double a, double b) {
+        return a * b;
+    }
+
+    public static float testMulFConst(float a) {
+        return a * 32.0F;
+    }
+
+    public static float testMulConstF(float a) {
+        return 32.0F * a;
+    }
+
+    public static double testMulDConst(double a) {
+        return a * 32.0;
+    }
+
+    public static double testMulConstD(double a) {
+        return 32.0 * a;
+    }
+
+    @Test
+    public void testDiv() {
+        compile("testDiv2F");
+        compile("testDiv2D");
+        // compile("testDivFConst");
+        // compile("testDivConstF");
+        // compile("testDivDConst");
+        // compile("testDivConstD");
+    }
+
+    public static float testDiv2F(float a, float b) {
+        return a / b;
+    }
+
+    public static double testDiv2D(double a, double b) {
+        return a / b;
+    }
+
+    public static float testDivFConst(float a) {
+        return a / 32.0F;
+    }
+
+    public static float testDivConstF(float a) {
+        return 32.0F / a;
+    }
+
+    public static double testDivDConst(double a) {
+        return a / 32.0;
+    }
+
+    public static double testDivConstD(double a) {
+        return 32.0 / a;
+    }
+
+    @Test
+    public void testNeg() {
+        compile("testNeg2F");
+        compile("testNeg2D");
+    }
+
+    public static float testNeg2F(float a) {
+        return -a;
+    }
+
+    public static double testNeg2D(double a) {
+        return -a;
+    }
+
+    @Test
+    public void testRem() {
+        // need linkage to PTX remainder()
+        // compile("testRem2F");
+        // compile("testRem2D");
+    }
+
+    public static float testRem2F(float a, float b) {
+        return a % b;
+    }
+
+    public static double testRem2D(double a, double b) {
+        return a % b;
+    }
+
+    @Test
+    public void testFloatConversion() {
+        // compile("testF2I");
+        // compile("testF2L");
+        // compile("testF2D");
+        // compile("testD2I");
+        // compile("testD2L");
+        // compile("testD2F");
+    }
+
+    public static int testF2I(float a) {
+        return (int) a;
+    }
+
+    public static long testF2L(float a) {
+        return (long) a;
+    }
+
+    public static double testF2D(float a) {
+        return a;
+    }
+
+    public static int testD2I(double a) {
+        return (int) a;
+    }
+
+    public static long testD2L(double a) {
+        return (long) a;
+    }
+
+    public static float testD2F(double a) {
+        return (float) a;
+    }
+
+    public static void main(String[] args) {
+        FloatSPARCTest test = new FloatSPARCTest();
+        for (Method m : FloatSPARCTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test") && name.startsWith("testRem") == false) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/IntegerSPARCTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.sparc.test;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+public class IntegerSPARCTest extends SPARCTestBase {
+
+    @Test
+    public void testAdd() {
+        compile("testAdd2I");
+        compile("testAdd2L");
+        compile("testAdd2B");
+        compile("testAddIConst");
+        compile("testAddConstI");
+    }
+
+    public static int testAdd2I(int a, int b) {
+        return a + b;
+    }
+
+    public static long testAdd2L(long a, long b) {
+        return a + b;
+    }
+
+    public static int testAdd2B(byte a, byte b) {
+        return a + b;
+    }
+
+    public static int testAddIConst(int a) {
+        return a + 32;
+    }
+
+    public static int testAddConstI(int a) {
+        return 32 + a;
+    }
+
+    @Test
+    public void testSub() {
+        compile("testSub2I");
+        compile("testSub2L");
+        compile("testSubIConst");
+        compile("testSubConstI");
+    }
+
+    public static int testSub2I(int a, int b) {
+        return a - b;
+    }
+
+    public static long testSub2L(long a, long b) {
+        return a - b;
+    }
+
+    public static int testSubIConst(int a) {
+        return a - 32;
+    }
+
+    public static int testSubConstI(int a) {
+        return 32 - a;
+    }
+
+    @Test
+    public void testMul() {
+        compile("testMul2I");
+        compile("testMul2L");
+        compile("testMulIConst");
+        compile("testMulConstI");
+    }
+
+    public static int testMul2I(int a, int b) {
+        return a * b;
+    }
+
+    public static long testMul2L(long a, long b) {
+        return a * b;
+    }
+
+    public static int testMulIConst(int a) {
+        return a * 32;
+    }
+
+    public static int testMulConstI(int a) {
+        return 32 * a;
+    }
+
+    @Test
+    public void testDiv() {
+        compile("testDiv2I");
+        compile("testDiv2L");
+        compile("testDivIConst");
+    }
+
+    public static int testDiv2I(int a, int b) {
+        return a / b;
+    }
+
+    public static long testDiv2L(long a, long b) {
+        return a / b;
+    }
+
+    public static int testDivIConst(int a) {
+        return a / 32;
+    }
+
+    @Ignore
+    public void testRem() {
+        compile("testRem2I");
+        compile("testRem2L");
+    }
+
+    public static int testRem2I(int a, int b) {
+        return a % b;
+    }
+
+    public static long testRem2L(long a, long b) {
+        return a % b;
+    }
+
+    @Test
+    public void testIntConversion() {
+        compile("testI2L");
+        compile("testI2C");
+        compile("testI2B");
+        compile("testI2F");
+        compile("testI2D");
+    }
+
+    public static long testI2L(int a) {
+        return a;
+    }
+
+    public static char testI2C(int a) {
+        return (char) a;
+    }
+
+    public static byte testI2B(int a) {
+        return (byte) a;
+    }
+
+    public static float testI2F(int a) {
+        return a;
+    }
+
+    public static double testI2D(int a) {
+        return a;
+    }
+
+    public static void main(String[] args) {
+        IntegerSPARCTest test = new IntegerSPARCTest();
+        for (Method m : IntegerSPARCTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/LogicSPARCTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.sparc.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+public class LogicSPARCTest extends SPARCTestBase {
+
+    @Test
+    public void testAnd() {
+        compile("testAnd2I");
+        compile("testAnd2L");
+    }
+
+    public static int testAnd2I(int a, int b) {
+        return a & b;
+    }
+
+    public static long testAnd2L(long a, long b) {
+        return a & b;
+    }
+
+    @Test
+    public void testOr() {
+        compile("testOr2I");
+        compile("testOr2L");
+    }
+
+    public static int testOr2I(int a, int b) {
+        return a | b;
+    }
+
+    public static long testOr2L(long a, long b) {
+        return a | b;
+    }
+
+    @Test
+    public void testXor() {
+        compile("testXor2I");
+        compile("testXor2L");
+    }
+
+    public static int testXor2I(int a, int b) {
+        return a ^ b;
+    }
+
+    public static long testXor2L(long a, long b) {
+        return a ^ b;
+    }
+
+    @Test
+    public void testNot() {
+        compile("testNot1I");
+        compile("testNot1L");
+    }
+
+    public static int testNot1I(int a) {
+        return ~a;
+    }
+
+    public static long testNot1L(long a) {
+        return ~a;
+    }
+
+    @Test
+    public void testShiftLeft() {
+        compile("testShiftLeft2I");
+        compile("testShiftLeft2L");
+    }
+
+    public static int testShiftLeft2I(int a, int b) {
+        return a << b;
+    }
+
+    public static long testShiftLeft2L(long a, int b) {
+        return a << b;
+    }
+
+    @Test
+    public void testShiftRight() {
+        compile("testShiftRight2I");
+        compile("testShiftRight2L");
+        compile("testUnsignedShiftRight2I");
+        compile("testUnsignedShiftRight2L");
+    }
+
+    public static int testShiftRight2I(int a, int b) {
+        return a >> b;
+    }
+
+    public static long testShiftRight2L(long a, int b) {
+        return a >> b;
+    }
+
+    public static int testUnsignedShiftRight2I(int a, int b) {
+        return a >>> b;
+    }
+
+    public static long testUnsignedShiftRight2L(long a, long b) {
+        return a >>> b;
+    }
+
+    public static void main(String[] args) {
+        LogicSPARCTest test = new LogicSPARCTest();
+        for (Method m : LogicSPARCTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCTestBase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.sparc.test;
+
+import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.*;
+import com.oracle.graal.api.runtime.Graal;
+import com.oracle.graal.compiler.GraalCompiler;
+import com.oracle.graal.compiler.sparc.SPARCBackend;
+import com.oracle.graal.compiler.test.GraalCompilerTest;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.java.GraphBuilderConfiguration;
+import com.oracle.graal.java.GraphBuilderPhase;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.spi.GraalCodeCacheProvider;
+import com.oracle.graal.phases.OptimisticOptimizations;
+import com.oracle.graal.phases.PhasePlan;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.sparc.SPARC;
+
+public abstract class SPARCTestBase extends GraalCompilerTest {
+
+    private StructuredGraph sg;
+
+    protected CompilationResult compile(String test) {
+        StructuredGraph graph = parse(test);
+        sg = graph;
+        Debug.dump(graph, "Graph");
+        TargetDescription target = new TargetDescription(new SPARC(), true, 1, 0, true);
+        SPARCBackend sparcBackend = new SPARCBackend(Graal.getRequiredCapability(GraalCodeCacheProvider.class), target);
+        PhasePlan phasePlan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, graalRuntime().getReplacements(),
+                                                              sparcBackend, target, null, phasePlan, OptimisticOptimizations.NONE,
+                                                              new SpeculationLog());
+        return result;
+    }
+
+    protected StructuredGraph getStructuredGraph() {
+        return sg;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCBackend.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.sparc;
+
+import com.oracle.graal.api.code.CallingConvention;
+import com.oracle.graal.api.code.CodeCacheProvider;
+import com.oracle.graal.api.code.CompilationResult;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.meta.ResolvedJavaMethod;
+import com.oracle.graal.asm.AbstractAssembler;
+import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.compiler.gen.LIRGenerator;
+import com.oracle.graal.compiler.target.Backend;
+import com.oracle.graal.lir.FrameMap;
+import com.oracle.graal.lir.LIR;
+import com.oracle.graal.lir.asm.FrameContext;
+import com.oracle.graal.lir.asm.TargetMethodAssembler;
+import com.oracle.graal.nodes.StructuredGraph;
+
+public class SPARCBackend extends Backend {
+
+    public SPARCBackend(CodeCacheProvider runtime, TargetDescription target) {
+        super(runtime, target);
+    }
+
+    @Override
+    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        return new SPARCLIRGenerator(graph, runtime(), target, frameMap, cc, lir);
+    }
+
+    @Override
+    protected AbstractAssembler createAssembler(FrameMap frameMap) {
+        return new SPARCAssembler(target, frameMap.registerConfig);
+    }
+
+    class HotSpotFrameContext implements FrameContext {
+
+        @Override
+        public void enter(TargetMethodAssembler tasm) {
+        }
+
+        @Override
+        public void leave(TargetMethodAssembler tasm) {
+        }
+    }
+    @Override
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
+        FrameMap frameMap = lirGen.frameMap;
+        AbstractAssembler masm = createAssembler(frameMap);
+        HotSpotFrameContext frameContext = new HotSpotFrameContext();
+        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult);
+        tasm.setFrameSize(frameMap.frameSize());
+        return tasm;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) {
+
+        // Emit code for the LIR
+        lirGen.lir.emitCode(tasm);
+
+    }
+
+
+}
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Jun 07 14:15:38 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -23,355 +23,823 @@
 
 package com.oracle.graal.compiler.sparc;
 
-import com.oracle.graal.api.code.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
+import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.*;
+import static com.oracle.graal.lir.sparc.SPARCMathIntrinsicOp.IntrinsicOpcode.*;
+import static com.oracle.graal.lir.sparc.SPARCArithmetic.*;
+import static com.oracle.graal.lir.sparc.SPARCCompare.*;
+
+import com.oracle.graal.api.code.CallingConvention;
+import com.oracle.graal.api.code.CodeCacheProvider;
+import com.oracle.graal.api.code.DeoptimizationAction;
+import com.oracle.graal.api.code.ForeignCallLinkage;
+import com.oracle.graal.api.code.StackSlot;
+import com.oracle.graal.api.code.TargetDescription;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.asm.NumUtil;
+import com.oracle.graal.compiler.gen.LIRGenerator;
+import com.oracle.graal.compiler.target.LIRGenLowerable;
+import com.oracle.graal.graph.GraalInternalError;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.nodes.*;
+import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.sparc.SPARCAddressValue;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegConst;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.Op1Stack;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Stack;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Reg;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.ShiftOp;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary1Op;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary2Op;
+import com.oracle.graal.lir.sparc.SPARCBitManipulationOp;
+import com.oracle.graal.lir.sparc.SPARCBreakpointOp;
+import com.oracle.graal.lir.sparc.SPARCByteSwapOp;
+import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.CondMoveOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.FloatCondMoveOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.SequentialSwitchOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.SwitchRangesOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp;
+import com.oracle.graal.lir.sparc.SPARCMathIntrinsicOp;
+import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
+import com.oracle.graal.lir.sparc.SPARCMove.MembarOp;
+import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp;
+import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp;
+import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
+import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp;
+import com.oracle.graal.lir.sparc.SPARCMove.StoreOp;
+import com.oracle.graal.lir.sparc.SPARCTestOp;
+import com.oracle.graal.nodes.BreakpointNode;
+import com.oracle.graal.nodes.DeoptimizingNode;
+import com.oracle.graal.nodes.DirectCallTargetNode;
+import com.oracle.graal.nodes.IndirectCallTargetNode;
+import com.oracle.graal.nodes.InfopointNode;
+import com.oracle.graal.nodes.SafepointNode;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.ConvertNode.Op;
-import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.CompareAndSwapNode;
 
 /**
  * This class implements the SPARC specific portion of the LIR generator.
  */
 public class SPARCLIRGenerator extends LIRGenerator {
 
+    public static class SPARCSpillMoveFactory implements LIR.SpillMoveFactory {
+
+        @Override
+        public LIRInstruction createMove(AllocatableValue result, Value input) {
+            throw new InternalError("NYI");
+        }
+    }
+
     public SPARCLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
         super(graph, runtime, target, frameMap, cc, lir);
-        // SPARC: Implement lir generator.
+        lir.spillMoveFactory = new SPARCSpillMoveFactory();
+    }
+
+    @Override
+    protected void emitNode(ValueNode node) {
+        if (node instanceof LIRGenLowerable) {
+            ((LIRGenLowerable) node).generate(this);
+        } else {
+            super.emitNode(node);
+        }
     }
 
     @Override
     public Variable emitMove(Value input) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(input.getKind());
+        emitMove(result, input);
+        return result;
+    }
+
+    @Override
+    public void emitMove(AllocatableValue dst, Value src) {
+        if (isRegister(src) || isStackSlot(dst)) {
+            append(new MoveFromRegOp(dst, src));
+        } else {
+            append(new MoveToRegOp(dst, src));
+        }
     }
 
     @Override
     protected boolean peephole(ValueNode valueNode) {
-        // SPARC: Auto-generated method stub
+        // No peephole optimizations for now
         return false;
     }
 
     @Override
     protected void emitReturn(Value input) {
-        // SPARC: Auto-generated method stub
-
+        append(new ReturnOp(input));
     }
 
     @Override
     public void emitJump(LabelRef label) {
-        @SuppressWarnings("unused")
-        SPARCLIRInstruction instruction = null;
-        // SPARC: Auto-generated method stub
-
+        append(new JumpOp(label));
     }
 
     @Override
     public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
-        // SPARC: Auto-generated method stub
-
+        switch (left.getKind().getStackKind()) {
+            case Int:
+                append(new CompareOp(ICMP, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Long:
+                append(new CompareOp(LCMP, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Float:
+                append(new CompareOp(FCMP, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Double:
+                append(new CompareOp(DCMP, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Object:
+                append(new CompareOp(ACMP, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
+        }
     }
 
     @Override
     public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
-        // SPARC: Auto-generated method stub
-
+        // append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, label));
+        throw GraalInternalError.shouldNotReachHere("emitOverflowCheckBranch: unimp");
     }
 
     @Override
     public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
-        // SPARC: Auto-generated method stub
+        emitIntegerTest(left, right);
+        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label));
+    }
+
+    private void emitIntegerTest(Value a, Value b) {
+        assert a.getKind().getStackKind() == Kind.Int || a.getKind() == Kind.Long;
+        if (LIRValueUtil.isVariable(b)) {
+            append(new SPARCTestOp(load(b), loadNonConst(a)));
+        } else {
+            append(new SPARCTestOp(load(a), loadNonConst(b)));
+        }
+    }
 
+    @Override
+    public Variable load(Value value) {
+        if (!isVariable(value)) {
+            return emitMove(value);
+        }
+        return (Variable) value;
+    }
+
+    @Override
+    public Value loadNonConst(Value value) {
+        if (isConstant(value) && !canInlineConstant((Constant) value)) {
+            return emitMove(value);
+        }
+        return value;
     }
 
     @Override
-    public Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
-        // SPARC: Auto-generated method stub
-        return null;
+    public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
+        boolean mirrored = emitCompare(left, right);
+        Condition finalCondition = mirrored ? cond.mirror() : cond;
+
+        Variable result = newVariable(trueValue.getKind());
+        switch (left.getKind().getStackKind()) {
+            case Int:
+            case Long:
+            case Object:
+                append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
+                break;
+            case Float:
+            case Double:
+                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
+        }
+        return result;
+    }
+
+    /**
+     * This method emits the compare instruction, and may reorder the operands. It returns true if
+     * it did so.
+     * 
+     * @param a the left operand of the comparison
+     * @param b the right operand of the comparison
+     * @return true if the left and right operands were switched, false otherwise
+     */
+    private boolean emitCompare(Value a, Value b) {
+        Variable left;
+        Value right;
+        boolean mirrored;
+        if (LIRValueUtil.isVariable(b)) {
+            left = load(b);
+            right = loadNonConst(a);
+            mirrored = true;
+        } else {
+            left = load(a);
+            right = loadNonConst(b);
+            mirrored = false;
+        }
+        switch (left.getKind().getStackKind()) {
+            case Int:
+                append(new CompareOp(ICMP, left, right));
+                break;
+            case Long:
+                append(new CompareOp(LCMP, left, right));
+                break;
+            case Object:
+                append(new CompareOp(ACMP, left, right));
+                break;
+            case Float:
+                append(new CompareOp(FCMP, left, right));
+                break;
+            case Double:
+                append(new CompareOp(DCMP, left, right));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return mirrored;
     }
 
     @Override
-    public Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue) {
-        // SPARC: Auto-generated method stub
-        return null;
+    public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
+        emitIntegerTest(left, right);
+        Variable result = newVariable(trueValue.getKind());
+        append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue)));
+        return result;
     }
 
     @Override
     protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        // SPARC: Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        // SPARC: Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
     protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
-        // SPARC: Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
-        // SPARC: Auto-generated method stub
-
+        // Making a copy of the switch value is necessary because jump table destroys the input
+        // value
+        if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) {
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL));
+        } else {
+            assert key.getKind() == Kind.Object : key.getKind();
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
+        }
     }
 
     @Override
     protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
-        // SPARC: Auto-generated method stub
-
+        append(new SwitchRangesOp(lowKeys, highKeys, targets, defaultTarget, key));
     }
 
     @Override
     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
-        // SPARC: Auto-generated method stub
-
+        // Making a copy of the switch value is necessary because jump table destroys the input
+        // value
+        Variable tmp = emitMove(key);
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind)));
     }
 
     @Override
     public void emitBitCount(Variable result, Value operand) {
-        // SPARC: Auto-generated method stub
-
+        if (operand.getKind().getStackKind() == Kind.Int) {
+            append(new SPARCBitManipulationOp(IPOPCNT, result, asAllocatable(operand)));
+        } else {
+            append(new SPARCBitManipulationOp(LPOPCNT, result, asAllocatable(operand)));
+        }
     }
 
     @Override
     public void emitBitScanForward(Variable result, Value operand) {
-        // SPARC: Auto-generated method stub
-
+        append(new SPARCBitManipulationOp(BSF, result, asAllocatable(operand)));
     }
 
     @Override
     public void emitBitScanReverse(Variable result, Value operand) {
-        // SPARC: Auto-generated method stub
-
+        if (operand.getKind().getStackKind() == Kind.Int) {
+            append(new SPARCBitManipulationOp(IBSR, result, asAllocatable(operand)));
+        } else {
+            append(new SPARCBitManipulationOp(LBSR, result, asAllocatable(operand)));
+        }
     }
 
     @Override
     public void emitMathAbs(Variable result, Variable input) {
-        // SPARC: Auto-generated method stub
-
+        append(new BinaryRegConst(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL))));
     }
 
     @Override
     public void emitMathSqrt(Variable result, Variable input) {
-        // SPARC: Auto-generated method stub
-
+        append(new SPARCMathIntrinsicOp(SQRT, result, input));
     }
 
     @Override
     public void emitMathLog(Variable result, Variable input, boolean base10) {
-        // SPARC: Auto-generated method stub
-
+        append(new SPARCMathIntrinsicOp(LOG, result, input));
     }
 
     @Override
     public void emitMathCos(Variable result, Variable input) {
-        // SPARC: Auto-generated method stub
-
+        append(new SPARCMathIntrinsicOp(COS, result, input));
     }
 
     @Override
     public void emitMathSin(Variable result, Variable input) {
-        // SPARC: Auto-generated method stub
-
+        append(new SPARCMathIntrinsicOp(SIN, result, input));
     }
 
     @Override
     public void emitMathTan(Variable result, Variable input) {
-        // SPARC: Auto-generated method stub
-
+        append(new SPARCMathIntrinsicOp(TAN, result, input));
     }
 
     @Override
-    public void emitByteSwap(Variable result, Value operand) {
-        // SPARC: Auto-generated method stub
-
+    public void emitByteSwap(Variable result, Value input) {
+        append(new SPARCByteSwapOp(result, input));
     }
 
     @Override
     public boolean canInlineConstant(Constant c) {
-        // SPARC: Auto-generated method stub
-        return false;
+        switch (c.getKind()) {
+            case Long:
+                return NumUtil.isInt(c.asLong()) && !runtime.needsDataPatch(c);
+            case Object:
+                return c.isNull();
+            default:
+                return true;
+        }
     }
 
     @Override
     public boolean canStoreConstant(Constant c) {
-        // SPARC: Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void emitMove(AllocatableValue dst, Value src) {
-        // SPARC: Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
-    public Value emitAddress(Value base, long displacement, Value index, int scale) {
-        // SPARC: Auto-generated method stub
-        return null;
+    public SPARCAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
+        AllocatableValue baseRegister;
+        long finalDisp = displacement;
+        if (isConstant(base)) {
+            if (asConstant(base).isNull()) {
+                baseRegister = Value.ILLEGAL;
+            } else if (asConstant(base).getKind() != Kind.Object) {
+                finalDisp += asConstant(base).asLong();
+                baseRegister = Value.ILLEGAL;
+            } else {
+                baseRegister = load(base);
+            }
+        } else {
+            baseRegister = asAllocatable(base);
+        }
+
+        if (index != Value.ILLEGAL && scale != 0) {
+            if (isConstant(index)) {
+                finalDisp += asConstant(index).asLong() * scale;
+            } else {
+                Value indexRegister;
+                if (scale != 1) {
+                    indexRegister = emitMul(index, Constant.forInt(scale));
+                } else {
+                    indexRegister = index;
+                }
+
+                if (baseRegister == Value.ILLEGAL) {
+                    baseRegister = asAllocatable(indexRegister);
+                } else {
+                    Variable newBase = newVariable(Kind.Int);
+                    emitMove(newBase, baseRegister);
+                    baseRegister = newBase;
+                    baseRegister = emitAdd(baseRegister, indexRegister);
+                }
+            }
+        }
+
+        return new SPARCAddressValue(target().wordKind, baseRegister, (int) finalDisp);
+    }
+
+    private SPARCAddressValue asAddress(Value address) {
+        if (address instanceof SPARCAddressValue) {
+            return (SPARCAddressValue) address;
+        } else {
+            return emitAddress(address, 0, Value.ILLEGAL, 0);
+        }
     }
 
     @Override
-    public Value emitLoad(Kind kind, Value address, DeoptimizingNode canTrap) {
-        // SPARC: Auto-generated method stub
-        return null;
+    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) {
+        SPARCAddressValue loadAddress = asAddress(address);
+        Variable result = newVariable(kind);
+        append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
+        return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value address, Value input, DeoptimizingNode canTrap) {
-        // SPARC: Auto-generated method stub
-
+    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
+        SPARCAddressValue storeAddress = asAddress(address);
+        Variable input = load(inputVal);
+        append(new StoreOp(kind, storeAddress, input, deopting != null ? state(deopting) : null));
     }
 
     @Override
     public Value emitAddress(StackSlot address) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(target().wordKind);
+        append(new StackLoadAddressOp(result, address));
+        return result;
     }
 
     @Override
     public Value emitNegate(Value input) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(input.getKind());
+        switch (input.getKind()) {
+            case Int:
+                append(new Op1Stack(INEG, result, input));
+                break;
+            case Float:
+                append(new Op1Stack(FNEG, result, input));
+                break;
+            case Double:
+                append(new Op1Stack(DNEG, result, input));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
-    public Value emitAdd(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+    public Variable emitAdd(Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(IADD, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Stack(LADD, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FADD, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DADD, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind() + " prim: " + a.getKind().isPrimitive());
+        }
+        return result;
     }
 
     @Override
     public Value emitSub(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Stack(LSUB, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FSUB, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DSUB, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
     }
 
     @Override
     public Value emitMul(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Reg(LMUL, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FMUL, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DMUL, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
     }
 
     @Override
     public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Reg(LDIV, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DDIV, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
     }
 
     @Override
     public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Reg(IREM, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Reg(LREM, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
     }
 
     @Override
     public Value emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
-        // SPARC: Auto-generated method stub
-        return null;
+        @SuppressWarnings("unused")
+        LIRFrameState state = state(deopting);
+        switch (a.getKind()) {
+            case Int:
+                // emitDivRem(IUDIV, a, b, state);
+                // return emitMove(RAX_I);
+            case Long:
+                // emitDivRem(LUDIV, a, b, state);
+                // return emitMove(RAX_L);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
     }
 
     @Override
     public Value emitURem(Value a, Value b, DeoptimizingNode deopting) {
-        // SPARC: Auto-generated method stub
-        return null;
+        @SuppressWarnings("unused")
+        LIRFrameState state = state(deopting);
+        switch (a.getKind()) {
+            case Int:
+                // emitDivRem(IUREM, a, b, state);
+                // return emitMove(RDX_I);
+            case Long:
+                // emitDivRem(LUREM, a, b, state);
+                // return emitMove(RDX_L);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
     }
 
     @Override
     public Value emitAnd(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(IAND, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Stack(LAND, result, a, loadNonConst(b)));
+                break;
+
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
     }
 
     @Override
     public Value emitOr(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(IOR, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Stack(LOR, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
     }
 
     @Override
     public Value emitXor(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Stack(LXOR, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
     public Value emitShl(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op1Stack(LSHL, result, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
     public Value emitShr(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op1Stack(LSHR, result, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
     public Value emitUShr(Value a, Value b) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new ShiftOp(IUSHR, result, a, b));
+                break;
+            case Long:
+                append(new ShiftOp(LUSHR, result, a, b));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
     public Value emitConvert(Op opcode, Value inputVal) {
-        // SPARC: Auto-generated method stub
-        return null;
+        Variable input = load(inputVal);
+        Variable result = newVariable(opcode.to);
+        switch (opcode) {
+            case I2L:
+                append(new Unary2Op(I2L, result, input));
+                break;
+            case L2I:
+                append(new Unary1Op(L2I, result, input));
+                break;
+            case I2B:
+                append(new Unary2Op(I2B, result, input));
+                break;
+            case I2C:
+                append(new Unary1Op(I2C, result, input));
+                break;
+            case I2S:
+                append(new Unary2Op(I2S, result, input));
+                break;
+            case F2D:
+                append(new Unary2Op(F2D, result, input));
+                break;
+            case D2F:
+                append(new Unary2Op(D2F, result, input));
+                break;
+            case I2F:
+                append(new Unary2Op(I2F, result, input));
+                break;
+            case I2D:
+                append(new Unary2Op(I2D, result, input));
+                break;
+            case F2I:
+                append(new Unary2Op(F2I, result, input));
+                break;
+            case D2I:
+                append(new Unary2Op(D2I, result, input));
+                break;
+            case L2F:
+                append(new Unary2Op(L2F, result, input));
+                break;
+            case L2D:
+                append(new Unary2Op(L2D, result, input));
+                break;
+            case F2L:
+                append(new Unary2Op(F2L, result, input));
+                break;
+            case D2L:
+                append(new Unary2Op(D2L, result, input));
+                break;
+            case MOV_I2F:
+                append(new Unary2Op(MOV_I2F, result, input));
+                break;
+            case MOV_L2D:
+                append(new Unary2Op(MOV_L2D, result, input));
+                break;
+            case MOV_F2I:
+                append(new Unary2Op(MOV_F2I, result, input));
+                break;
+            case MOV_D2L:
+                append(new Unary2Op(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(result, input);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
     public void emitMembar(int barriers) {
-        // SPARC: Auto-generated method stub
-
+        int necessaryBarriers = target.arch.requiredBarriers(barriers);
+        if (target.isMP && necessaryBarriers != 0) {
+            append(new MembarOp(necessaryBarriers));
+        }
     }
 
     @Override
     public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
-        // SPARC: Auto-generated method stub
-
+        append(new ReturnOp(Value.ILLEGAL));
     }
 
     @Override
     public void visitCompareAndSwap(CompareAndSwapNode i) {
-        // SPARC: Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
-        // SPARC: Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
-    public void visitBreakpointNode(BreakpointNode i) {
-        // SPARC: Auto-generated method stub
+    public void visitBreakpointNode(BreakpointNode node) {
+        JavaType[] sig = new JavaType[node.arguments().size()];
+        for (int i = 0; i < sig.length; i++) {
+            sig[i] = node.arguments().get(i).stamp().javaType(runtime);
+        }
 
+        Value[] parameters = visitInvokeArguments(frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false), node.arguments());
+        append(new SPARCBreakpointOp(parameters));
     }
 
     @Override
     public void emitUnwind(Value operand) {
-        // SPARC: Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
-        // SPARC: Auto-generated method stub
-
+        assert v.kind() == Kind.Object;
+        append(new NullCheckOp(load(operand(v)), state(deopting)));
     }
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        // SPARC: Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -309,7 +309,7 @@
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+        new PartialEscapeAnalysisPhase(false, false, new CanonicalizerPhase(true)).apply(graph, context);
         new CullFrameStatesPhase().apply(graph);
     }
 
@@ -326,22 +326,23 @@
 
                 Assumptions assumptions = new Assumptions(false);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
+                CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 if (loopPeeling) {
                     new LoopTransformHighPhase().apply(graph);
                 }
                 new DeadCodeEliminationPhase().apply(graph);
-                new CanonicalizerPhase().apply(graph, context);
-                new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+                canonicalizer.apply(graph, context);
+                new PartialEscapeAnalysisPhase(false, false, canonicalizer).apply(graph, context);
 
                 new CullFrameStatesPhase().apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
-                new CanonicalizerPhase().apply(graph, context);
+                canonicalizer.apply(graph, context);
 
                 StructuredGraph referenceGraph = parse(referenceSnippet);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(referenceGraph);
                 new DeadCodeEliminationPhase().apply(referenceGraph);
-                new CanonicalizerPhase().apply(referenceGraph, context);
+                new CanonicalizerPhase(true).apply(referenceGraph, context);
 
                 assertEquals(referenceGraph, graph, excludeVirtual);
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -35,7 +35,7 @@
 
     private StructuredGraph getCanonicalizedGraph(String name) {
         StructuredGraph graph = parse(name);
-        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
         return graph;
     }
 
@@ -53,7 +53,7 @@
             assertEquals(referenceGraph, graph);
         }
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
         for (int i = 1; i < 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -82,7 +82,7 @@
             public void run() {
                 StructuredGraph graph = parse(snippet);
                 new InliningPhase(runtime(), null, replacements, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
                 Debug.dump(graph, "Graph");
                 StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
                 Debug.dump(referenceGraph, "ReferenceGraph");
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -115,7 +115,7 @@
                 StructuredGraph graph = parse(snippet);
                 Debug.dump(graph, "After parsing: " + snippet);
                 Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count());
-                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
                 Assert.assertEquals(afterCanon, graph.getNodes(CheckCastNode.class).count());
                 return graph;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -68,7 +68,7 @@
         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault();
         new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         return graph;
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.test;
 
 import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -420,7 +421,7 @@
         InstalledCode installedCode = Debug.scope("Compiling", new Object[]{runtime, new DebugDumpScope(String.valueOf(id), true)}, new Callable<InstalledCode>() {
 
             public InstalledCode call() throws Exception {
-                final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
+                final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed();
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s ...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature()));
                 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -144,7 +144,7 @@
             n.replaceFirstInput(local, constant);
         }
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -66,7 +66,7 @@
         }
         Assumptions assumptions = new Assumptions(false);
         new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -77,7 +77,7 @@
 
         Assumptions assumptions = new Assumptions(false);
         new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -133,8 +133,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
         Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() {
 
             @Override
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -220,11 +220,11 @@
             public SchedulePhase call() throws Exception {
                 StructuredGraph graph = parse(snippet);
                 Assumptions assumptions = new Assumptions(false);
-                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+                HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
+                new CanonicalizerPhase(true).apply(graph, context);
                 if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 }
-                HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
                 if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -94,7 +94,7 @@
         }
         Assumptions assumptions = new Assumptions(false);
         new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -93,10 +93,11 @@
     private StructuredGraph compileTestSnippet(final String snippet) {
         StructuredGraph graph = parse(snippet);
         HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
-        new CanonicalizerPhase().apply(graph, context);
+        canonicalizer.apply(graph, context);
         new PushThroughPiPhase().apply(graph);
-        new CanonicalizerPhase().apply(graph, context);
+        canonicalizer.apply(graph, context);
 
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,6 +25,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -88,14 +89,14 @@
                 new FloatingReadPhase().apply(graph);
                 new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph);
                 new ReadEliminationPhase().apply(graph);
-                new CanonicalizerPhase().apply(graph, context);
+                new CanonicalizerPhase(true).apply(graph, context);
 
                 Debug.dump(graph, "After lowering");
 
                 for (FloatingReadNode node : graph.getNodes(LocalNode.class).first().usages().filter(FloatingReadNode.class)) {
                     // Checking that the parameter a is not directly used for the access to field
                     // x10 (because x10 must be guarded by the checkcast).
-                    Assert.assertTrue(node.location().getLocationIdentity() == LocationNode.FINAL_LOCATION);
+                    Assert.assertTrue(node.location().getLocationIdentity() == LocationIdentity.FINAL_LOCATION);
                 }
             }
         });
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -244,9 +244,9 @@
     private <T extends Node & Node.IterableNodeType> void test(String test, String ref) {
         StructuredGraph testGraph = parse(test);
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(testGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(testGraph);
         StructuredGraph refGraph = parse(ref);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(refGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(refGraph);
         assertEquals(testGraph, refGraph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -166,9 +166,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -98,7 +98,7 @@
 
     private void testZeroReturn(String methodName) {
         StructuredGraph graph = parse(methodName);
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         assertConstantReturn(graph, 0);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -89,7 +89,7 @@
         // No debug scope to reduce console noise for @Test(expected = ...) tests
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -186,13 +186,13 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         // a second canonicalizer is needed to process nested MaterializeNodes
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
         assertEquals(referenceGraph, graph);
     }
 
@@ -242,9 +242,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         Debug.dump(graph, "Graph");
         Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierAdditionTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierAdditionTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,10 +27,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
-import com.oracle.graal.nodes.spi.Lowerable.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -33,7 +33,6 @@
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.test.backend;
 
 import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 import java.util.concurrent.*;
@@ -112,7 +113,7 @@
 
     private RegisterStats getRegisterStats(final StructuredGraph graph) {
         final PhasePlan phasePlan = getDefaultPhasePlan();
-        final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions);
+        final Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
 
         final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -55,7 +55,7 @@
     public void test1() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
 
         for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -222,7 +222,7 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
-                new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false).apply(graph, context);
+                new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true)).apply(graph, context);
                 Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
                 ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
                 if (expectedConstantResult != null) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
+import static com.oracle.graal.phases.GraalOptions.*;
 import static org.junit.Assert.*;
 
 import java.util.concurrent.*;
@@ -33,6 +34,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
@@ -100,8 +102,8 @@
 
     private void processMethod(final String snippet) {
         graph = parse(snippet);
-        GraalOptions.OptEarlyReadElimination = true;
+        OptEarlyReadElimination.setValue(true);
         HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
-        new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph, context);
+        new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false, new CanonicalizerPhase(true)).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -224,6 +224,6 @@
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new PartialEscapeAnalysisPhase(false, true).apply(graph, context);
+        new PartialEscapeAnalysisPhase(false, true, new CanonicalizerPhase(true)).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -164,12 +164,13 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
-                new CanonicalizerPhase().apply(graph, context);
-                new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+                CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+                canonicalizer.apply(graph, context);
+                new PartialEscapeAnalysisPhase(false, false, canonicalizer).apply(graph, context);
 
                 new CullFrameStatesPhase().apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
-                new CanonicalizerPhase().apply(graph, context);
+                canonicalizer.apply(graph, context);
                 return graph;
             }
         });
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -161,7 +161,7 @@
                 Debug.dump(graph, "Graph");
                 new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 Debug.dump(graph, "Graph");
-                new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 return graph;
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,11 +27,11 @@
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.phases.*;
 
 /**
- * Implements the filter specified by the {@link GraalOptions#Dump}, {@link GraalOptions#Log},
- * {@link GraalOptions#Meter} and {@link GraalOptions#Time} options.
+ * Implements the filter specified by the {@link GraalDebugConfig#Dump},
+ * {@link GraalDebugConfig#Log}, {@link GraalDebugConfig#Meter} and {@link GraalDebugConfig#Time}
+ * options.
  * <p>
  * These options enable the associated debug facility if their filter matches the
  * {@linkplain DebugScope#getQualifiedName() name} of the {@linkplain Debug#currentScope() current
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -38,6 +40,7 @@
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
@@ -52,6 +55,13 @@
  */
 public class GraalCompiler {
 
+    // @formatter:off
+    @Option(help = "")
+    public static final OptionValue<Boolean> VerifyUsageWithEquals = new OptionValue<>(true);
+    @Option(help = "Enable inlining")
+    public static final OptionValue<Boolean> Inline = new OptionValue<>(true);
+    // @formatter:on
+
     /**
      * Requests compilation of a given graph.
      * 
@@ -69,7 +79,7 @@
         Debug.scope("GraalCompiler", new Object[]{graph, runtime}, new Runnable() {
 
             public void run() {
-                final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions);
+                final Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
                     public LIR call() {
@@ -125,23 +135,27 @@
         } else {
             Debug.dump(graph, "initial state");
         }
-        new VerifyValueUsage(runtime).apply(graph);
-
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+        if (VerifyUsageWithEquals.getValue()) {
+            new VerifyUsageWithEquals(runtime, Value.class).apply(graph);
+            new VerifyUsageWithEquals(runtime, Register.class).apply(graph);
         }
 
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(OptCanonicalizeReads.getValue());
         HighTierContext highTierContext = new HighTierContext(runtime, assumptions, replacements);
 
-        if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
-            if (GraalOptions.IterativeInlining) {
-                new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph, highTierContext);
+        if (OptCanonicalizer.getValue()) {
+            canonicalizer.apply(graph, highTierContext);
+        }
+
+        if (Inline.getValue() && !plan.isPhaseDisabled(InliningPhase.class)) {
+            if (IterativeInlining.getValue()) {
+                new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, OptEarlyReadElimination.getValue(), canonicalizer).apply(graph, highTierContext);
             } else {
                 new InliningPhase(runtime, null, replacements, assumptions, cache, plan, optimisticOpts).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
 
-                if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+                if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
+                    canonicalizer.apply(graph, highTierContext);
                     new IterativeConditionalEliminationPhase().apply(graph, highTierContext);
                 }
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Fri Jun 07 14:15:38 2013 +0200
@@ -31,10 +31,43 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
+import com.oracle.graal.options.*;
 
 public class GraalDebugConfig implements DebugConfig {
 
+    // @formatter:off
+    @Option(help = "Enable scope-based debugging", name = "Debug")
+    public static final OptionValue<Boolean> DebugEnabled = new OptionValue<>(true);
+    @Option(help = "Scopes to be dumped")
+    public static final OptionValue<String> Dump = new OptionValue<>(null);
+    @Option(help = "Scopes to be metered")
+    public static final OptionValue<String> Meter = new OptionValue<>(null);
+    @Option(help = "Scopes to be timed")
+    public static final OptionValue<String> Time = new OptionValue<>(null);
+    @Option(help = "Scopes to be logged")
+    public static final OptionValue<String> Log = new OptionValue<>(null);
+    @Option(help = "Filters debug scope output by method name/pattern")
+    public static final OptionValue<String> MethodFilter = new OptionValue<>(null);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PerThreadDebugValues = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> SummarizeDebugValues = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> SummarizePerPhase = new OptionValue<>(false);
+    @Option(help = "Send Graal IR to dump handlers on error")
+    public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false);
+    @Option(help = "Enable expensive assertions")
+    public static final OptionValue<Boolean> DetailedAsserts = new StableOptionValue<Boolean>() {
+        @Override
+        protected Boolean initialValue() {
+            boolean enabled = false;
+            // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
+            assert (enabled = true) == true;
+            return enabled;
+        }
+    };
+    // @formatter:on
+
     private final DebugFilter logFilter;
     private final DebugFilter meterFilter;
     private final DebugFilter timerFilter;
@@ -170,7 +203,7 @@
         for (Object o : Debug.context()) {
             if (o instanceof Graph) {
                 Debug.log("Context obj %s", o);
-                if (GraalOptions.DumpOnError) {
+                if (DumpOnError.getValue()) {
                     Debug.dump(o, "Exception graph");
                 } else {
                     Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error");
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,10 @@
  */
 package com.oracle.graal.compiler.alloc;
 
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -29,12 +33,8 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
-import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.lir.LIRValueUtil.*;
-
 /**
  * Represents an interval in the {@linkplain LinearScan linear scan register allocator}.
  */
@@ -922,7 +922,7 @@
 
         // do not add use positions for precolored intervals because they are never used
         if (registerPriority != RegisterPriority.None && isVariable(operand)) {
-            if (GraalOptions.DetailedAsserts) {
+            if (DetailedAsserts.getValue()) {
                 for (int i = 0; i < usePosList.size(); i++) {
                     assert pos <= usePosList.usePos(i) : "already added a use-position with lower position";
                     if (i > 0) {
@@ -1026,7 +1026,7 @@
         // split list of use positions
         result.usePosList = usePosList.splitAt(splitPos);
 
-        if (GraalOptions.DetailedAsserts) {
+        if (DetailedAsserts.getValue()) {
             for (int i = 0; i < usePosList.size(); i++) {
                 assert usePosList.usePos(i) < splitPos;
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.compiler.alloc;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.graal.compiler.alloc.Interval.RegisterBindingLists;
 import com.oracle.graal.compiler.alloc.Interval.State;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.phases.*;
 
 /**
  */
@@ -208,7 +209,7 @@
             boolean isActive = currentInterval.from() <= toOpId;
             int opId = isActive ? currentInterval.from() : toOpId;
 
-            if (GraalOptions.TraceLinearScanLevel >= 2 && !TTY.isSuppressed()) {
+            if (TraceLinearScanLevel.getValue() >= 2 && !TTY.isSuppressed()) {
                 if (currentPosition < opId) {
                     TTY.println();
                     TTY.println("walkTo(%d) *", opId);
@@ -239,7 +240,7 @@
     private void intervalMoved(Interval interval, State from, State to) {
         // intervalMoved() is called whenever an interval moves from one interval list to another.
         // In the implementation of this method it is prohibited to move the interval to any list.
-        if (GraalOptions.TraceLinearScanLevel >= 4 && !TTY.isSuppressed()) {
+        if (TraceLinearScanLevel.getValue() >= 4 && !TTY.isSuppressed()) {
             TTY.print(from.toString() + " to " + to.toString());
             TTY.fillTo(23);
             TTY.out().println(interval.logString(allocator));
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Jun 07 14:15:38 2013 +0200
@@ -24,7 +24,9 @@
 
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -501,7 +503,7 @@
 
     // called once before assignment of register numbers
     void eliminateSpillMoves() {
-        if (GraalOptions.TraceLinearScanLevel >= 3) {
+        if (TraceLinearScanLevel.getValue() >= 3) {
             TTY.println(" Eliminating unnecessary spill moves");
         }
 
@@ -509,7 +511,7 @@
         // the list is sorted by Interval.spillDefinitionPos
         Interval interval;
         interval = createUnhandledLists(mustStoreAtDefinition, null).first;
-        if (GraalOptions.DetailedAsserts) {
+        if (DetailedAsserts.getValue()) {
             checkIntervals(interval);
         }
 
@@ -535,7 +537,7 @@
                     if (!isRegister(curInterval.location()) && curInterval.alwaysInMemory()) {
                         // move target is a stack slot that is always correct, so eliminate
                         // instruction
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("eliminating move from interval %d to %d", operandNumber(move.getInput()), operandNumber(move.getResult()));
                         }
                         instructions.set(j, null); // null-instructions are deleted by assignRegNum
@@ -561,7 +563,7 @@
 
                         insertionBuffer.append(j + 1, ir.spillMoveFactory.createMove(toLocation, fromLocation));
 
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             StackSlot slot = interval.spillSlot();
                             TTY.println("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, slot, opId);
                         }
@@ -593,7 +595,7 @@
             assert temp.spillDefinitionPos() >= temp.from() : "invalid order";
             assert temp.spillDefinitionPos() <= temp.from() + 2 : "only intervals defined once at their start-pos can be optimized";
 
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos());
             }
 
@@ -658,7 +660,7 @@
         assert index == numInstructions : "must match";
         assert (index << 1) == opId : "must match: " + (index << 1);
 
-        if (GraalOptions.DetailedAsserts) {
+        if (DetailedAsserts.getValue()) {
             for (int i = 0; i < variables.size(); i++) {
                 assert variables.get(i) != null && variables.get(i).index == i;
             }
@@ -696,7 +698,7 @@
                             int operandNum = operandNumber(operand);
                             if (!liveKill.get(operandNum)) {
                                 liveGen.set(operandNum);
-                                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                if (TraceLinearScanLevel.getValue() >= 4) {
                                     TTY.println("  Setting liveGen for operand %d at instruction %d", operandNum, op.id());
                                 }
                             }
@@ -705,7 +707,7 @@
                             }
                         }
 
-                        if (GraalOptions.DetailedAsserts) {
+                        if (DetailedAsserts.getValue()) {
                             verifyInput(block, liveKill, operand);
                         }
                         return operand;
@@ -718,7 +720,7 @@
                         int operandNum = operandNumber(operand);
                         if (!liveKill.get(operandNum)) {
                             liveGen.set(operandNum);
-                            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            if (TraceLinearScanLevel.getValue() >= 4) {
                                 TTY.println("  Setting liveGen for LIR opId %d, operand %d because of state for %s", op.id(), operandNum, op);
                             }
                         }
@@ -737,7 +739,7 @@
                             }
                         }
 
-                        if (GraalOptions.DetailedAsserts) {
+                        if (DetailedAsserts.getValue()) {
                             // fixed intervals are never live at block boundaries, so
                             // they need not be processed in live sets
                             // process them only in debug mode so that this can be checked
@@ -761,7 +763,7 @@
             blockData.get(block).liveIn = new BitSet(liveSize);
             blockData.get(block).liveOut = new BitSet(liveSize);
 
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("liveGen  B%d %s", block.getId(), blockData.get(block).liveGen);
                 TTY.println("liveKill B%d %s", block.getId(), blockData.get(block).liveKill);
             }
@@ -850,7 +852,7 @@
                     liveIn.or(blockData.get(block).liveGen);
                 }
 
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     traceLiveness(changeOccurredInBlock, iterationCount, block);
                 }
             }
@@ -861,7 +863,7 @@
             }
         } while (changeOccurred);
 
-        if (GraalOptions.DetailedAsserts) {
+        if (DetailedAsserts.getValue()) {
             verifyLiveness();
         }
 
@@ -869,7 +871,7 @@
         Block startBlock = ir.cfg.getStartBlock();
         BitSet liveInArgs = new BitSet(blockData.get(startBlock).liveIn.size());
         if (!blockData.get(startBlock).liveIn.equals(liveInArgs)) {
-            if (GraalOptions.DetailedAsserts) {
+            if (DetailedAsserts.getValue()) {
                 reportFailure(numBlocks);
             }
 
@@ -970,7 +972,7 @@
         if (!isProcessed(operand)) {
             return;
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2 && kind == null) {
+        if (TraceLinearScanLevel.getValue() >= 2 && kind == null) {
             TTY.println(" use %s from %d to %d (%s)", operand, from, to, registerPriority.name());
         }
 
@@ -989,7 +991,7 @@
         if (!isProcessed(operand)) {
             return;
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" temp %s tempPos %d (%s)", operand, tempPos, RegisterPriority.MustHaveRegister.name());
         }
 
@@ -1010,7 +1012,7 @@
         if (!isProcessed(operand)) {
             return;
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" def %s defPos %d (%s)", operand, defPos, registerPriority.name());
         }
 
@@ -1031,7 +1033,7 @@
             // also add register priority for dead intervals
             interval.addRange(defPos, defPos + 1);
             interval.addUsePos(defPos, registerPriority);
-            if (GraalOptions.TraceLinearScanLevel >= 2) {
+            if (TraceLinearScanLevel.getValue() >= 2) {
                 TTY.println("Warning: def of operand %s at %d occurs without use", operand, defPos);
             }
         }
@@ -1087,12 +1089,12 @@
             MoveOp move = (MoveOp) op;
             if (optimizeMethodArgument(move.getInput())) {
                 StackSlot slot = asStackSlot(move.getInput());
-                if (GraalOptions.DetailedAsserts) {
+                if (DetailedAsserts.getValue()) {
                     assert op.id() > 0 : "invalid id";
                     assert blockForId(op.id()).getPredecessorCount() == 0 : "move from stack must be in first block";
                     assert isVariable(move.getResult()) : "result of move must be a variable";
 
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("found move from stack slot %s to %s", slot, move.getResult());
                     }
                 }
@@ -1122,7 +1124,7 @@
                             from.setLocationHint(to);
                         }
 
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber);
                         }
                         return registerHint;
@@ -1155,7 +1157,7 @@
             for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) {
                 assert live.get(operandNum) : "should not stop here otherwise";
                 AllocatableValue operand = operandFor(operandNum);
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                if (TraceLinearScanLevel.getValue() >= 2) {
                     TTY.println("live in %s to %d", operand, blockTo + 2);
                 }
 
@@ -1185,7 +1187,7 @@
                             addTemp(r.asValue(), opId, RegisterPriority.None, Kind.Illegal);
                         }
                     }
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("operation destroys all caller-save registers");
                     }
                 }
@@ -1436,7 +1438,7 @@
         Interval result = interval.getSplitChildAtOpId(opId, mode, this);
 
         if (result != null) {
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("Split child at pos " + opId + " of interval " + interval.toString() + " is " + result.toString());
             }
             return result;
@@ -1490,7 +1492,7 @@
 
     void resolveFindInsertPos(Block fromBlock, Block toBlock, MoveResolver moveResolver) {
         if (fromBlock.getSuccessorCount() <= 1) {
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("inserting moves at end of fromBlock B%d", fromBlock.getId());
             }
 
@@ -1504,11 +1506,11 @@
             }
 
         } else {
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("inserting moves at beginning of toBlock B%d", toBlock.getId());
             }
 
-            if (GraalOptions.DetailedAsserts) {
+            if (DetailedAsserts.getValue()) {
                 assert ir.lir(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label";
 
                 // because the number of predecessor edges matches the number of
@@ -1549,7 +1551,7 @@
 
                     // prevent optimization of two consecutive blocks
                     if (!blockCompleted.get(pred.getLinearScanNumber()) && !blockCompleted.get(sux.getLinearScanNumber())) {
-                        if (GraalOptions.TraceLinearScanLevel >= 3) {
+                        if (TraceLinearScanLevel.getValue() >= 3) {
                             TTY.println(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId());
                         }
                         blockCompleted.set(block.getLinearScanNumber());
@@ -1576,7 +1578,7 @@
                     // check for duplicate edges between the same blocks (can happen with switch
                     // blocks)
                     if (!alreadyResolved.get(toBlock.getLinearScanNumber())) {
-                        if (GraalOptions.TraceLinearScanLevel >= 3) {
+                        if (GraalOptions.TraceLinearScanLevel.getValue() >= 3) {
                             TTY.println(" processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId());
                         }
                         alreadyResolved.set(toBlock.getLinearScanNumber());
@@ -1614,7 +1616,7 @@
         assert interval != null : "interval must exist";
 
         if (opId != -1) {
-            if (GraalOptions.DetailedAsserts) {
+            if (DetailedAsserts.getValue()) {
                 Block block = blockForId(opId);
                 if (block.getSuccessorCount() <= 1 && opId == getLastLirInstructionId(block)) {
                     // check if spill moves could have been appended at the end of this block, but
@@ -1655,7 +1657,7 @@
     }
 
     void computeOopMap(IntervalWalker iw, LIRInstruction op, BitSet registerRefMap, BitSet frameRefMap) {
-        if (GraalOptions.TraceLinearScanLevel >= 3) {
+        if (TraceLinearScanLevel.getValue() >= 3) {
             TTY.println("creating oop map at opId %d", op.id());
         }
 
@@ -1839,14 +1841,14 @@
 
                 sortIntervalsAfterAllocation();
 
-                if (GraalOptions.DetailedAsserts) {
+                if (DetailedAsserts.getValue()) {
                     verify();
                 }
 
                 eliminateSpillMoves();
                 assignLocations();
 
-                if (GraalOptions.DetailedAsserts) {
+                if (DetailedAsserts.getValue()) {
                     verifyIntervals();
                 }
             }
@@ -1864,7 +1866,7 @@
     }
 
     void printIntervals(String label) {
-        if (GraalOptions.TraceLinearScanLevel >= 1) {
+        if (TraceLinearScanLevel.getValue() >= 1) {
             int i;
             TTY.println();
             TTY.println(label);
@@ -1894,27 +1896,27 @@
 
     boolean verify() {
         // (check that all intervals have a correct register and that no registers are overwritten)
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" verifying intervals *");
         }
         verifyIntervals();
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" verifying that no oops are in fixed intervals *");
         }
         // verifyNoOopsInFixedIntervals();
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" verifying that unpinned constants are not alive across block boundaries");
         }
         verifyConstants();
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" verifying register allocation *");
         }
         verifyRegisters();
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" no errors found *");
         }
 
@@ -1986,7 +1988,7 @@
                 Value l1 = i1.location();
                 Value l2 = i2.location();
                 if (i1.intersects(i2) && (l1.equals(l2))) {
-                    if (GraalOptions.DetailedAsserts) {
+                    if (DetailedAsserts.getValue()) {
                         TTY.println("Intervals %d and %d overlap and have the same register assigned", i1.operandNumber, i2.operandNumber);
                         TTY.println(i1.logString(this));
                         TTY.println(i2.logString(this));
@@ -2066,7 +2068,7 @@
 
             // visit all operands where the liveAtEdge bit is set
             for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("checking interval %d of block B%d", operandNum, block.getId());
                 }
                 Value operand = operandFor(operandNum);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -38,7 +39,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -297,7 +297,7 @@
         int optimalSplitPos = -1;
         if (minSplitPos == maxSplitPos) {
             // trivial case, no optimization of split position possible
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      min-pos and max-pos are equal, no optimization possible");
             }
             optimalSplitPos = minSplitPos;
@@ -321,7 +321,7 @@
             assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order";
             if (minBlock == maxBlock) {
                 // split position cannot be moved to block boundary : so split as late as possible
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("      cannot move split pos to block boundary because minPos and maxPos are in same block");
                 }
                 optimalSplitPos = maxSplitPos;
@@ -333,14 +333,14 @@
                     // as mustHaveRegister) with a hole before each definition. When the register is
                     // needed
                     // for the second definition : an earlier reloading is unnecessary.
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("      interval has hole just before maxSplitPos, so splitting at maxSplitPos");
                     }
                     optimalSplitPos = maxSplitPos;
 
                 } else {
                     // seach optimal block boundary between minSplitPos and maxSplitPos
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("      moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId());
                     }
 
@@ -349,7 +349,7 @@
                         // max-position :
                         // then split before this loop
                         int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, allocator.getLastLirInstructionId(minBlock) + 2);
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("      loop optimization: loop end found at pos %d", loopEndPos);
                         }
 
@@ -364,7 +364,7 @@
                             // of the interval (normally, only mustHaveRegister causes a reloading)
                             Block loopBlock = allocator.blockForId(loopEndPos);
 
-                            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            if (TraceLinearScanLevel.getValue() >= 4) {
                                 TTY.println("      interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(),
                                                 loopBlock.getId());
                             }
@@ -373,11 +373,11 @@
                             optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, allocator.getLastLirInstructionId(loopBlock) + 2);
                             if (optimalSplitPos == allocator.getLastLirInstructionId(loopBlock) + 2) {
                                 optimalSplitPos = -1;
-                                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                if (TraceLinearScanLevel.getValue() >= 4) {
                                     TTY.println("      loop optimization not necessary");
                                 }
                             } else {
-                                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                if (TraceLinearScanLevel.getValue() >= 4) {
                                     TTY.println("      loop optimization successful");
                                 }
                             }
@@ -391,7 +391,7 @@
                 }
             }
         }
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      optimal split position: %d", optimalSplitPos);
         }
 
@@ -403,13 +403,13 @@
     // 1) the left part has already a location assigned
     // 2) the right part is sorted into to the unhandled-list
     void splitBeforeUsage(Interval interval, int minSplitPos, int maxSplitPos) {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("----- splitting interval: ");
         }
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println(interval.logString(allocator));
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("      between %d and %d", minSplitPos, maxSplitPos);
         }
 
@@ -427,7 +427,7 @@
         if (optimalSplitPos == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) {
             // the split position would be just before the end of the interval
             // . no split at all necessary
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      no split necessary because optimal split position is at end of interval");
             }
             return;
@@ -442,7 +442,7 @@
             optimalSplitPos = (optimalSplitPos - 1) | 1;
         }
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      splitting at position %d", optimalSplitPos);
         }
         assert allocator.isBlockBegin(optimalSplitPos) || (optimalSplitPos % 2 == 1) : "split pos must be odd when not on block boundary";
@@ -455,10 +455,10 @@
         assert splitPart.from() >= currentInterval.currentFrom() : "cannot append new interval before current walk position";
         unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Any, splitPart);
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("      split interval in two parts (insertMoveWhenActivated: %b)", moveNecessary);
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.print("      ");
             TTY.println(interval.logString(allocator));
             TTY.print("      ");
@@ -476,7 +476,7 @@
         int maxSplitPos = currentPosition;
         int minSplitPos = Math.max(interval.previousUsage(RegisterPriority.ShouldHaveRegister, maxSplitPos) + 1, interval.from());
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.print("----- splitting and spilling interval: ");
             TTY.println(interval.logString(allocator));
             TTY.println("      between %d and %d", minSplitPos, maxSplitPos);
@@ -490,7 +490,7 @@
 
         if (minSplitPos == interval.from()) {
             // the whole interval is never used, so spill it entirely to memory
-            if (GraalOptions.TraceLinearScanLevel >= 2) {
+            if (TraceLinearScanLevel.getValue() >= 2) {
                 TTY.println("      spilling entire interval because split pos is at beginning of interval");
                 TTY.println("      use positions: " + interval.usePosList().size());
             }
@@ -509,7 +509,7 @@
                 if (isRegister(parent.location())) {
                     if (parent.firstUsage(RegisterPriority.ShouldHaveRegister) == Integer.MAX_VALUE) {
                         // parent is never used, so kick it out of its assigned register
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("      kicking out interval %d out of its register because it is never used", parent.operandNumber);
                         }
                         allocator.assignSpillSlot(parent);
@@ -534,7 +534,7 @@
                 optimalSplitPos = (optimalSplitPos - 1) | 1;
             }
 
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      splitting at position %d", optimalSplitPos);
             }
             assert allocator.isBlockBegin(optimalSplitPos) || (optimalSplitPos % 2 == 1) : "split pos must be odd when not on block boundary";
@@ -545,7 +545,7 @@
             allocator.changeSpillState(spilledPart, optimalSplitPos);
 
             if (!allocator.isBlockBegin(optimalSplitPos)) {
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("      inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber);
                 }
                 insertMove(optimalSplitPos, interval, spilledPart);
@@ -555,7 +555,7 @@
             assert spilledPart.currentSplitChild() == interval : "overwriting wrong currentSplitChild";
             spilledPart.makeCurrentSplitChild();
 
-            if (GraalOptions.TraceLinearScanLevel >= 2) {
+            if (TraceLinearScanLevel.getValue() >= 2) {
                 TTY.println("      split interval in two parts");
                 TTY.print("      ");
                 TTY.println(interval.logString(allocator));
@@ -604,7 +604,7 @@
     }
 
     boolean allocFreeRegister(Interval interval) {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("trying to find free register for " + interval.logString(allocator));
         }
 
@@ -620,7 +620,7 @@
         // (either as a fixed register or a normal allocated register in the past)
         // only intervals overlapping with cur are processed, non-overlapping invervals can be
         // ignored safely
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      state of registers:");
             for (Register register : availableRegs) {
                 int i = register.number;
@@ -632,7 +632,7 @@
         Interval locationHint = interval.locationHint(true);
         if (locationHint != null && locationHint.location() != null && isRegister(locationHint.location())) {
             hint = asRegister(locationHint.location());
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      hint register %d from interval %s", hint.number, locationHint.logString(allocator));
             }
         }
@@ -654,12 +654,12 @@
             int number = availableReg.number;
             if (usePos[number] >= intervalTo) {
                 // this register is free for the full interval
-                if (minFullReg == null || availableReg == hint || (usePos[number] < usePos[minFullReg.number] && minFullReg != hint)) {
+                if (minFullReg == null || availableReg.equals(hint) || (usePos[number] < usePos[minFullReg.number] && !minFullReg.equals(hint))) {
                     minFullReg = availableReg;
                 }
             } else if (usePos[number] > regNeededUntil) {
                 // this register is at least free until regNeededUntil
-                if (maxPartialReg == null || availableReg == hint || (usePos[number] > usePos[maxPartialReg.number] && maxPartialReg != hint)) {
+                if (maxPartialReg == null || availableReg.equals(hint) || (usePos[number] > usePos[maxPartialReg.number] && !maxPartialReg.equals(hint))) {
                     maxPartialReg = availableReg;
                 }
             }
@@ -676,7 +676,7 @@
 
         splitPos = usePos[reg.number];
         interval.assignLocation(reg.asValue(interval.kind()));
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("selected register %d", reg.number);
         }
 
@@ -702,7 +702,7 @@
 
     // Split an Interval and spill it to memory so that cur can be placed in a register
     void allocLockedRegister(Interval interval) {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("need to split and spill to get register for " + interval.logString(allocator));
         }
 
@@ -715,7 +715,7 @@
         spillCollectActiveAny();
         spillCollectInactiveAny(interval);
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      state of registers:");
             for (Register reg : availableRegs) {
                 int i = reg.number;
@@ -748,7 +748,7 @@
 
         if (reg == null || usePos[reg.number] <= firstUsage) {
             // the first use of cur is later than the spilling position -> spill cur
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, reg == null ? 0 : usePos[reg.number]);
             }
 
@@ -767,7 +767,7 @@
 
         int splitPos = blockPos[reg.number];
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("decided to use register %d", reg.number);
         }
         assert splitPos > 0 : "invalid splitPos";
@@ -796,7 +796,7 @@
             if (isOdd(pos)) {
                 // the current instruction is a call that blocks all registers
                 if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) {
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("      free register cannot be available because all registers blocked by following call");
                     }
 
@@ -888,11 +888,11 @@
         Interval interval = currentInterval;
         boolean result = true;
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("+++++ activating interval " + interval.logString(allocator));
         }
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      splitParent: %s, insertMoveWhenActivated: %b", interval.splitParent().operandNumber, interval.insertMoveWhenActivated());
         }
 
@@ -901,7 +901,7 @@
             // activating an interval that has a stack slot assigned . split it at first use
             // position
             // used for method parameters
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      interval has spill slot assigned (method parameter) . split it before first use");
             }
             splitStackInterval(interval);
@@ -911,7 +911,7 @@
             if (interval.location() == null) {
                 // interval has not assigned register . normal allocation
                 // (this is the normal case for most intervals)
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("      normal allocation of register");
                 }
 
@@ -937,7 +937,7 @@
             assert interval.isSplitChild();
             assert interval.currentSplitChild() != null;
             assert !interval.currentSplitChild().operand.equals(operand) : "cannot insert move between same interval";
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber);
             }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.alloc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -30,7 +31,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.phases.*;
 
 /**
  */
@@ -201,7 +201,7 @@
 
         insertionBuffer.append(insertIdx, allocator.ir.spillMoveFactory.createMove(toOpr, fromOpr));
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("MoveResolver: inserted move from %d (%s) to %d (%s)", fromInterval.operandNumber, fromInterval.location(), toInterval.operandNumber, toInterval.location());
         }
     }
@@ -213,7 +213,7 @@
         AllocatableValue toOpr = toInterval.operand;
         insertionBuffer.append(insertIdx, allocator.ir.spillMoveFactory.createMove(toOpr, fromOpr));
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.print("MoveResolver: inserted move from constant %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location());
         }
     }
@@ -285,7 +285,7 @@
                 }
                 spillInterval.assignLocation(spillSlot);
 
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("created new Interval %s for spilling", spillInterval.operand);
                 }
 
@@ -327,7 +327,7 @@
     }
 
     void addMapping(Interval fromInterval, Interval toInterval) {
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("MoveResolver: adding mapping from interval %d (%s) to interval %d (%s)", fromInterval.operandNumber, fromInterval.location(), toInterval.operandNumber, toInterval.location());
         }
 
@@ -339,7 +339,7 @@
     }
 
     void addMapping(Value fromOpr, Interval toInterval) {
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("MoveResolver: adding mapping from %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location());
         }
         assert isConstant(fromOpr) : "only for constants";
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.alloc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -33,7 +34,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.*;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -92,7 +92,7 @@
     }
 
     private void processBlock(Block block) {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println();
             TTY.println("processBlock B%d", block.getId());
         }
@@ -100,7 +100,7 @@
         // must copy state because it is modified
         Interval[] inputState = copy(stateForBlock(block));
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("Input-State of intervals:");
             TTY.print("    ");
             for (int i = 0; i < stateSize(); i++) {
@@ -142,7 +142,7 @@
                         savedStateCorrect = false;
                         savedState[i] = null;
 
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("processSuccessor B%d: invalidating slot %d", block.getId(), i);
                         }
                     }
@@ -151,12 +151,12 @@
 
             if (savedStateCorrect) {
                 // already processed block with correct inputState
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                if (TraceLinearScanLevel.getValue() >= 2) {
                     TTY.println("processSuccessor B%d: previous visit already correct", block.getId());
                 }
             } else {
                 // must re-visit this block
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                if (TraceLinearScanLevel.getValue() >= 2) {
                     TTY.println("processSuccessor B%d: must re-visit because input state changed", block.getId());
                 }
                 addToWorkList(block);
@@ -164,7 +164,7 @@
 
         } else {
             // block was not processed before, so set initial inputState
-            if (GraalOptions.TraceLinearScanLevel >= 2) {
+            if (TraceLinearScanLevel.getValue() >= 2) {
                 TTY.println("processSuccessor B%d: initial visit", block.getId());
             }
 
@@ -182,11 +182,11 @@
             Register reg = asRegister(location);
             int regNum = reg.number;
             if (interval != null) {
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("        %s = %s", reg, interval.operand);
                 }
             } else if (inputState[regNum] != null) {
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("        %s = null", reg);
                 }
             }
@@ -209,7 +209,7 @@
         for (int i = 0; i < ops.size(); i++) {
             final LIRInstruction op = ops.get(i);
 
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println(op.toStringWithIdPrefix());
             }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,6 +26,7 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 import java.util.Map.Entry;
@@ -46,7 +47,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -203,7 +203,7 @@
         return value;
     }
 
-    protected LabelRef getLIRBlock(FixedNode b) {
+    public LabelRef getLIRBlock(FixedNode b) {
         Block result = lir.cfg.blockFor(b);
         int suxIndex = currentBlock.getSuccessors().indexOf(result);
         assert suxIndex != -1 : "Block not in successor list of current block";
@@ -259,8 +259,7 @@
     }
 
     public void append(LIRInstruction op) {
-        assert LIRVerifier.verify(op);
-        if (GraalOptions.PrintIRWithLIR && !TTY.isSuppressed()) {
+        if (PrintIRWithLIR.getValue() && !TTY.isSuppressed()) {
             if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
                 lastInstructionPrinted = currentInstruction;
                 InstructionPrinter ip = new InstructionPrinter(TTY.out());
@@ -269,11 +268,12 @@
             TTY.println(op.toStringWithIdPrefix());
             TTY.println();
         }
+        assert LIRVerifier.verify(op);
         lir.lir(currentBlock).add(op);
     }
 
     public void doBlock(Block block) {
-        if (GraalOptions.PrintIRWithLIR) {
+        if (PrintIRWithLIR.getValue()) {
             TTY.print(block.toString());
         }
 
@@ -284,7 +284,7 @@
 
         append(new LabelOp(new Label(), block.isAligned()));
 
-        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+        if (TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("BEGIN Generating LIR for block B" + block.getId());
         }
 
@@ -315,12 +315,12 @@
                     }
                 }
             }
-            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+            if (TraceLIRGeneratorLevel.getValue() >= 2) {
                 if (fs == null) {
                     TTY.println("STATE RESET");
                 } else {
                     TTY.println("STATE CHANGE (singlePred)");
-                    if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+                    if (TraceLIRGeneratorLevel.getValue() >= 3) {
                         TTY.println(fs.toString(Node.Verbosity.Debugger));
                     }
                 }
@@ -331,7 +331,7 @@
         List<ScheduledNode> nodes = lir.nodesFor(block);
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
-            if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+            if (TraceLIRGeneratorLevel.getValue() >= 3) {
                 TTY.println("LIRGen for " + instr);
             }
             FrameState stateAfter = null;
@@ -358,9 +358,9 @@
             if (stateAfter != null) {
                 lastState = stateAfter;
                 assert checkStateReady(lastState);
-                if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+                if (TraceLIRGeneratorLevel.getValue() >= 2) {
                     TTY.println("STATE CHANGE");
-                    if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+                    if (TraceLIRGeneratorLevel.getValue() >= 3) {
                         TTY.println(stateAfter.toString(Node.Verbosity.Debugger));
                     }
                 }
@@ -373,7 +373,7 @@
             emitJump(getLIRBlock((FixedNode) successors.first()));
         }
 
-        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+        if (TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("END Generating LIR for block B" + block.getId());
         }
 
@@ -384,7 +384,7 @@
         blockLastState.put(block, lastState);
         currentBlock = null;
 
-        if (GraalOptions.PrintIRWithLIR) {
+        if (PrintIRWithLIR.getValue()) {
             TTY.println();
         }
     }
@@ -414,7 +414,7 @@
     }
 
     private void doRoot(ValueNode instr) {
-        if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+        if (TraceLIRGeneratorLevel.getValue() >= 2) {
             TTY.println("Emitting LIR for instruction " + instr);
         }
         currentInstruction = instr;
@@ -484,7 +484,7 @@
     }
 
     private void moveToPhi(MergeNode merge, AbstractEndNode pred) {
-        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+        if (TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("MOVE TO PHI from " + pred + " to " + merge);
         }
         PhiResolver resolver = new PhiResolver(this);
@@ -660,7 +660,7 @@
 
     @Override
     public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
-        LIRFrameState state = info != null ? state(info) : null;
+        LIRFrameState state = !linkage.canDeoptimize() ? null : stateFor(info.getDeoptimizationState(), info.getDeoptimizationReason());
 
         // move the arguments into the correct location
         CallingConvention linkageCc = linkage.getCallingConvention();
@@ -707,7 +707,7 @@
                 int switchRangeCount = switchRangeCount(x);
                 if (switchRangeCount == 0) {
                     emitJump(getLIRBlock(x.defaultSuccessor()));
-                } else if (switchRangeCount >= GraalOptions.MinimumJumpTableSize && keyCount / (double) valueRange >= GraalOptions.MinTableSwitchDensity) {
+                } else if (switchRangeCount >= MinimumJumpTableSize.getValue() && keyCount / (double) valueRange >= MinTableSwitchDensity.getValue()) {
                     int minValue = x.keyAt(0).asInt();
                     assert valueRange < Integer.MAX_VALUE;
                     LabelRef[] targets = new LabelRef[(int) valueRange];
@@ -718,7 +718,7 @@
                         targets[x.keyAt(i).asInt() - minValue] = getLIRBlock(x.keySuccessor(i));
                     }
                     emitTableSwitch(minValue, defaultTarget, targets, value);
-                } else if (keyCount / switchRangeCount >= GraalOptions.RangeTestsSwitchDensity) {
+                } else if (keyCount / switchRangeCount >= RangeTestsSwitchDensity.getValue()) {
                     emitSwitchRanges(x, switchRangeCount, value, defaultTarget);
                 } else {
                     emitSequentialSwitch(x, value, defaultTarget);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
@@ -32,39 +34,40 @@
 public class HighTier extends PhaseSuite<HighTierContext> {
 
     public HighTier() {
-        if (GraalOptions.FullUnroll) {
-            addPhase(new LoopFullUnrollPhase());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(OptCanonicalizeReads.getValue());
+
+        if (FullUnroll.getValue()) {
+            addPhase(new LoopFullUnrollPhase(OptCanonicalizeReads.getValue()));
         }
 
-        if (GraalOptions.OptTailDuplication) {
+        if (OptTailDuplication.getValue()) {
             addPhase(new TailDuplicationPhase());
         }
 
-        if (GraalOptions.PartialEscapeAnalysis) {
-            addPhase(new PartialEscapeAnalysisPhase(true, GraalOptions.OptEarlyReadElimination));
+        if (PartialEscapeAnalysis.getValue()) {
+            addPhase(new PartialEscapeAnalysisPhase(true, OptEarlyReadElimination.getValue(), canonicalizer));
         }
 
-        if (GraalOptions.OptConvertDeoptsToGuards) {
+        if (OptConvertDeoptsToGuards.getValue()) {
             addPhase(new ConvertDeoptimizeToGuardPhase());
         }
 
         addPhase(new LockEliminationPhase());
 
-        if (GraalOptions.OptLoopTransform) {
+        if (OptLoopTransform.getValue()) {
             addPhase(new LoopTransformHighPhase());
             addPhase(new LoopTransformLowPhase());
         }
         addPhase(new RemoveValueProxyPhase());
 
-        if (GraalOptions.CullFrameStates) {
+        if (CullFrameStates.getValue()) {
             addPhase(new CullFrameStatesPhase());
         }
 
-        if (GraalOptions.OptCanonicalizer) {
-            addPhase(new CanonicalizerPhase());
+        if (OptCanonicalizer.getValue()) {
+            addPhase(canonicalizer);
         }
 
         addPhase(new LoweringPhase(LoweringType.BEFORE_GUARDS));
     }
-
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -30,41 +32,43 @@
 public class MidTier extends PhaseSuite<MidTierContext> {
 
     public MidTier() {
-        if (GraalOptions.OptPushThroughPi) {
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(OptCanonicalizeReads.getValue());
+
+        if (OptPushThroughPi.getValue()) {
             addPhase(new PushThroughPiPhase());
-            if (GraalOptions.OptCanonicalizer) {
-                addPhase(new CanonicalizerPhase());
+            if (OptCanonicalizer.getValue()) {
+                addPhase(canonicalizer);
             }
         }
 
-        if (GraalOptions.OptFloatingReads) {
-            IncrementalCanonicalizerPhase<MidTierContext> canonicalizer = new IncrementalCanonicalizerPhase<>();
-            canonicalizer.addPhase(new FloatingReadPhase());
-            addPhase(canonicalizer);
-            if (GraalOptions.OptReadElimination) {
+        if (OptFloatingReads.getValue()) {
+            IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>();
+            incCanonicalizer.addPhase(new FloatingReadPhase());
+            addPhase(incCanonicalizer);
+            if (OptReadElimination.getValue()) {
                 addPhase(new ReadEliminationPhase());
             }
         }
         addPhase(new RemoveValueProxyPhase());
 
-        if (GraalOptions.OptCanonicalizer) {
-            addPhase(new CanonicalizerPhase());
+        if (OptCanonicalizer.getValue()) {
+            addPhase(canonicalizer);
         }
 
-        if (GraalOptions.OptEliminatePartiallyRedundantGuards) {
+        if (OptEliminatePartiallyRedundantGuards.getValue()) {
             addPhase(new EliminatePartiallyRedundantGuardsPhase(false, true));
         }
 
-        if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
+        if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
             addPhase(new IterativeConditionalEliminationPhase());
         }
 
-        if (GraalOptions.OptEliminatePartiallyRedundantGuards) {
+        if (OptEliminatePartiallyRedundantGuards.getValue()) {
             addPhase(new EliminatePartiallyRedundantGuardsPhase(true, true));
         }
 
-        if (GraalOptions.OptCanonicalizer) {
-            addPhase(new CanonicalizerPhase());
+        if (OptCanonicalizer.getValue()) {
+            addPhase(canonicalizer);
         }
 
         addPhase(new LoopSafepointEliminationPhase());
@@ -73,8 +77,8 @@
 
         addPhase(new GuardLoweringPhase());
 
-        if (GraalOptions.OptCanonicalizer) {
-            addPhase(new CanonicalizerPhase());
+        if (OptCanonicalizer.getValue()) {
+            addPhase(canonicalizer);
         }
     }
 }
--- a/graal/com.oracle.graal.graph/.checkstyle_checks.xml	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.graph/.checkstyle_checks.xml	Fri Jun 07 14:15:38 2013 +0200
@@ -203,6 +203,12 @@
     <property name="checkFormat" value="RegexpSingleline"/>
     <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable System.(out|err).print checks"/>
   </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+    <property name="checkFormat" value=".*Header"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+  </module>
   <module name="RegexpSingleline">
     <property name="format" value="System\.(out|err)\.print"/>
     <property name="fileExtensions" value="java"/>
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Jun 07 14:15:38 2013 +0200
@@ -199,13 +199,13 @@
             if (field.isAnnotationPresent(Node.Input.class)) {
                 assert !field.isAnnotationPresent(Node.Successor.class) : "field cannot be both input and successor";
                 if (INPUT_LIST_CLASS.isAssignableFrom(type)) {
-                    assert Modifier.isFinal(field.getModifiers()) : "NodeInputList input field " + field + " should be final";
-                    assert !Modifier.isPublic(field.getModifiers()) : "NodeInputList input field " + field + " should not be public";
+                    GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeInputList input field %s should be final", field);
+                    GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeInputList input field %s should not be public", field);
                     inputListOffsets.add(offset);
                 } else {
-                    assert NODE_CLASS.isAssignableFrom(type) || type.isInterface() : "invalid input type: " + type;
-                    assert !Modifier.isFinal(field.getModifiers()) : "Node input field " + field + " should not be final";
-                    assert Modifier.isPrivate(field.getModifiers()) : "Node input field " + field + " should be private";
+                    GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type) || type.isInterface(), "invalid input type: %s", type);
+                    GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node input field %s should not be final", field);
+                    GraalInternalError.guarantee(Modifier.isPrivate(field.getModifiers()), "Node input field %s should be private", field);
                     inputOffsets.add(offset);
                 }
                 if (field.getAnnotation(Node.Input.class).notDataflow()) {
@@ -213,19 +213,19 @@
                 }
             } else if (field.isAnnotationPresent(Node.Successor.class)) {
                 if (SUCCESSOR_LIST_CLASS.isAssignableFrom(type)) {
-                    assert Modifier.isFinal(field.getModifiers()) : "NodeSuccessorList successor field " + field + " should be final";
-                    assert !Modifier.isPublic(field.getModifiers()) : "NodeSuccessorList successor field " + field + " should not be public";
+                    GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeSuccessorList successor field % should be final", field);
+                    GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeSuccessorList successor field %s should not be public", field);
                     successorListOffsets.add(offset);
                 } else {
-                    assert NODE_CLASS.isAssignableFrom(type) : "invalid successor type: " + type;
-                    assert !Modifier.isFinal(field.getModifiers()) : "Node successor field " + field + " should not be final";
-                    assert Modifier.isPrivate(field.getModifiers()) : "Node successor field " + field + " should be private";
+                    GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type), "invalid successor type: %s", type);
+                    GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node successor field %s should not be final", field);
+                    GraalInternalError.guarantee(Modifier.isPrivate(field.getModifiers()), "Node successor field %s should be private", field);
                     successorOffsets.add(offset);
                 }
             } else {
-                assert !NODE_CLASS.isAssignableFrom(type) || field.getName().equals("Null") : "suspicious node field: " + field;
-                assert !INPUT_LIST_CLASS.isAssignableFrom(type) : "suspicious node input list field: " + field;
-                assert !SUCCESSOR_LIST_CLASS.isAssignableFrom(type) : "suspicious node successor list field: " + field;
+                GraalInternalError.guarantee(!NODE_CLASS.isAssignableFrom(type) || field.getName().equals("Null"), "suspicious node field: %s", field);
+                GraalInternalError.guarantee(!INPUT_LIST_CLASS.isAssignableFrom(type), "suspicious node input list field: %s", field);
+                GraalInternalError.guarantee(!SUCCESSOR_LIST_CLASS.isAssignableFrom(type), "suspicious node successor list field: %s", field);
                 dataOffsets.add(offset);
             }
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Jun 07 14:15:38 2013 +0200
@@ -50,7 +50,6 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.*;
 
 /**
  * HotSpot AMD64 specific backend.
@@ -75,7 +74,7 @@
      *            the current frame
      */
     protected static void emitStackOverflowCheck(TargetMethodAssembler tasm, boolean afterFrameInit) {
-        if (GraalOptions.StackShadowPages > 0) {
+        if (StackShadowPages.getValue() > 0) {
 
             AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
             int frameSize = tasm.frameMap.frameSize();
@@ -83,7 +82,7 @@
                 int lastFramePage = frameSize / unsafe.pageSize();
                 // emit multiple stack bangs for methods with frames larger than a page
                 for (int i = 0; i <= lastFramePage; i++) {
-                    int disp = (i + GraalOptions.StackShadowPages) * unsafe.pageSize();
+                    int disp = (i + StackShadowPages.getValue()) * unsafe.pageSize();
                     if (afterFrameInit) {
                         disp -= frameSize;
                     }
@@ -112,7 +111,7 @@
                 emitStackOverflowCheck(tasm, false);
             }
             asm.decrementq(rsp, frameSize);
-            if (GraalOptions.ZapStackOnMethodEntry) {
+            if (ZapStackOnMethodEntry.getValue()) {
                 final int intSize = 4;
                 for (int i = 0; i < frameSize / intSize; ++i) {
                     asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1);
@@ -158,7 +157,7 @@
         AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
         FrameMap frameMap = gen.frameMap;
         LIR lir = gen.lir;
-        boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
+        boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
 
         Stub stub = gen.getStub();
         AbstractAssembler masm = createAssembler(frameMap);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,11 +27,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
-@Opcode("CRUNTIME_CALL_PROLOGUE")
+@Opcode
 final class AMD64HotSpotCRuntimeCallPrologueOp extends AMD64LIRInstruction {
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -53,7 +53,7 @@
             masm.movq(rbp, (AMD64Address) tasm.asAddress(savedRbp));
         } else {
             Register framePointer = asRegister(savedRbp);
-            if (framePointer != rbp) {
+            if (!framePointer.equals(rbp)) {
                 masm.movq(rbp, framePointer);
             }
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Jun 07 14:15:38 2013 +0200
@@ -45,9 +45,18 @@
 import com.oracle.graal.lir.StandardOp.ParametersOp;
 import com.oracle.graal.lir.StandardOp.PlaceholderOp;
 import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapCompressedOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadCompressedOop;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreCompressedOop;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
@@ -211,8 +220,7 @@
     @Override
     public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
         Stub stub = getStub();
-        HotSpotForeignCallLinkage hsLinkage = (HotSpotForeignCallLinkage) linkage;
-        boolean destroysRegisters = hsLinkage.destroysRegisters();
+        boolean destroysRegisters = linkage.destroysRegisters();
 
         AMD64SaveRegistersOp save = null;
         StackSlot[] savedRegisterLocations = null;
@@ -234,7 +242,7 @@
 
         Variable result;
 
-        if (!hsLinkage.isLeaf()) {
+        if (linkage.canDeoptimize()) {
             assert info != null;
             append(new AMD64HotSpotCRuntimeCallPrologueOp());
             result = super.emitForeignCall(linkage, info, args);
@@ -391,4 +399,78 @@
             op.savedRbp = savedRbp;
         }
     }
+
+    private static boolean isCompressCandidate(DeoptimizingNode access) {
+        return access != null && ((HeapAccess) access).compress();
+    }
+
+    @Override
+    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode access) {
+        AMD64AddressValue loadAddress = asAddressValue(address);
+        Variable result = newVariable(kind);
+        assert access == null || access instanceof HeapAccess;
+        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
+            assert kind == Kind.Object;
+            Variable scratch = newVariable(Kind.Long);
+            append(new LoadCompressedOop(kind, result, scratch, loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase, runtime().config.narrowOopShift,
+                            runtime().config.logMinObjAlignment));
+        } else {
+            append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
+        }
+        return result;
+    }
+
+    @Override
+    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode access) {
+        AMD64AddressValue storeAddress = asAddressValue(address);
+        LIRFrameState state = access != null ? state(access) : null;
+        if (isConstant(inputVal)) {
+            Constant c = asConstant(inputVal);
+            if (canStoreConstant(c)) {
+                append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
+                return;
+            }
+        }
+        Variable input = load(inputVal);
+        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
+            assert kind == Kind.Object;
+            Variable scratch = newVariable(Kind.Long);
+            append(new StoreCompressedOop(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+        } else {
+            append(new StoreOp(kind, storeAddress, input, state));
+        }
+    }
+
+    @Override
+    public void visitCompareAndSwap(CompareAndSwapNode node) {
+        Kind kind = node.newValue().kind();
+        assert kind == node.expected().kind();
+
+        Value expected = loadNonConst(operand(node.expected()));
+        Variable newValue = load(operand(node.newValue()));
+
+        AMD64AddressValue address;
+        int displacement = node.displacement();
+        Value index = operand(node.offset());
+        if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) {
+            assert !runtime.needsDataPatch(asConstant(index));
+            displacement += (int) asConstant(index).asLong();
+            address = new AMD64AddressValue(kind, load(operand(node.object())), displacement);
+        } else {
+            address = new AMD64AddressValue(kind, load(operand(node.object())), load(index), Scale.Times1, displacement);
+        }
+
+        RegisterValue raxRes = AMD64.rax.asValue(kind);
+        emitMove(raxRes, expected);
+        if (runtime().config.useCompressedOops && node.compress()) {
+            assert kind == Kind.Object;
+            Variable scratch = newVariable(Kind.Long);
+            append(new CompareAndSwapCompressedOp(raxRes, address, raxRes, newValue, scratch, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+        } else {
+            append(new CompareAndSwapOp(raxRes, address, raxRes, newValue));
+        }
+        Variable result = newVariable(node.kind());
+        append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE));
+        setResult(node, result);
+    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPatchReturnAddressOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPatchReturnAddressOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -28,7 +28,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -32,13 +33,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.phases.*;
 
 public class AMD64HotSpotRegisterConfig implements RegisterConfig {
 
     private final Architecture architecture;
 
-    private final Register[] allocatable = initAllocatable();
+    private final Register[] allocatable;
 
     private final HashMap<PlatformKind, Register[]> categorized = new HashMap<>();
 
@@ -86,25 +86,34 @@
         throw new IllegalArgumentException("register " + name + " is not allocatable");
     }
 
-    private static Register[] initAllocatable() {
+    private static Register[] initAllocatable(boolean reserveForHeapBase) {
+        Register[] registers = null;
         // @formatter:off
-        Register[] allocatable = {
+        if (reserveForHeapBase) {
+            registers = new Register[] {
+                        rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, /*r12,*/ r13, r14, /*r15, */
+                        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+                        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+                      };
+        } else {
+            registers = new Register[] {
                         rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, r12, r13, r14, /*r15, */
                         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
                         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
-                    };
-        // @formatter:on
+                      };
+        }
+       // @formatter:on
 
-        if (GraalOptions.RegisterPressure != null) {
-            String[] names = GraalOptions.RegisterPressure.split(",");
+        if (RegisterPressure.getValue() != null) {
+            String[] names = RegisterPressure.getValue().split(",");
             Register[] regs = new Register[names.length];
             for (int i = 0; i < names.length; i++) {
-                regs[i] = findRegister(names[i], allocatable);
+                regs[i] = findRegister(names[i], registers);
             }
             return regs;
         }
 
-        return allocatable;
+        return registers;
     }
 
     public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
@@ -119,6 +128,7 @@
         }
 
         csl = null;
+        allocatable = initAllocatable(config.useCompressedOops);
         attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Jun 07 14:15:38 2013 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.*;
@@ -60,14 +61,14 @@
         RegisterValue exception = rax.asValue(Kind.Object);
         RegisterValue exceptionPc = rdx.asValue(word);
         CallingConvention exceptionCc = new CallingConvention(0, ILLEGAL, exception, exceptionPc);
-        register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc));
-        register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc));
+        register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
+        register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
 
         // The x86 crypto stubs do callee saving
-        registerForeignCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF);
+        registerForeignCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
 
         convertSnippets = new AMD64ConvertSnippets.Templates(this, replacements, graalRuntime.getTarget());
         super.registerReplacements(replacements);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.stubs.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,7 +27,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
 import com.oracle.graal.lir.asm.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
 import com.oracle.graal.lir.asm.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -31,7 +31,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp;
 import com.oracle.graal.lir.asm.*;
@@ -61,13 +60,13 @@
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         tasm.recordMark(Marks.MARK_INLINE_INVOKE);
         Register callReg = asRegister(targetAddress);
-        assert callReg != METHOD;
+        assert !callReg.equals(METHOD);
         AMD64Call.indirectCall(tasm, masm, callReg, callTarget, state);
     }
 
     @Override
     protected void verify() {
         super.verify();
-        assert asRegister(metaspaceMethod) == METHOD;
+        assert asRegister(metaspaceMethod).equals(METHOD);
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.spi.*;
@@ -59,7 +58,7 @@
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) {
         int pos = asm.codeBuffer.position();
-        int offset = SafepointPollOffset % unsafe.pageSize();
+        int offset = SafepointPollOffset.getValue() % unsafe.pageSize();
         RegisterValue scratch = (RegisterValue) temp;
         if (config.isPollingPageFar) {
             asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Jun 07 14:15:38 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,14 +24,17 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.sparc.*;
+import com.oracle.graal.asm.AbstractAssembler;
+import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.compiler.gen.LIRGenerator;
+import com.oracle.graal.compiler.sparc.SPARCLIRGenerator;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.Stub;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 /**
  * HotSpot SPARC specific backend.
@@ -49,14 +52,44 @@
 
     @Override
     protected AbstractAssembler createAssembler(FrameMap frameMap) {
-        // SPARC: Create assembler.
-        return null;
+        return new SPARCAssembler(target, frameMap.registerConfig);
+    }
+
+    class HotSpotFrameContext implements FrameContext {
+
+        final boolean isStub;
+
+        HotSpotFrameContext(boolean isStub) {
+            this.isStub = isStub;
+        }
+
+        @Override
+        public void enter(TargetMethodAssembler tasm) {
+        }
+
+        @Override
+        public void leave(TargetMethodAssembler tasm) {
+        }
     }
 
     @Override
     public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
-        // SPARC: Create assembler.
-        return null;
+        SPARCHotSpotLIRGenerator gen = (SPARCHotSpotLIRGenerator) lirGen;
+        FrameMap frameMap = gen.frameMap;
+        LIR lir = gen.lir;
+        boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
+
+        Stub stub = gen.getStub();
+        AbstractAssembler masm = createAssembler(frameMap);
+        HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(stub != null);
+        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult);
+        tasm.setFrameSize(frameMap.frameSize());
+        StackSlot deoptimizationRescueSlot = gen.deoptimizationRescueSlot;
+        if (deoptimizationRescueSlot != null && stub == null) {
+            tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
+        }
+
+        return tasm;
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Fri Jun 07 14:15:38 2013 +0200
@@ -47,7 +47,7 @@
     @Override
     protected TargetDescription createTarget() {
         // SPARC: Create target description.
-        return null;
+        throw new InternalError("NYI");
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import com.oracle.graal.api.code.CallingConvention;
+import com.oracle.graal.api.code.CodeCacheProvider;
+import com.oracle.graal.api.code.DeoptimizationAction;
+import com.oracle.graal.api.code.StackSlot;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.meta.DeoptimizationReason;
+import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.compiler.sparc.SPARCLIRGenerator;
+import com.oracle.graal.hotspot.HotSpotLIRGenerator;
+import com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode;
+import com.oracle.graal.hotspot.stubs.Stub;
+import com.oracle.graal.lir.FrameMap;
+import com.oracle.graal.lir.LIR;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.ValueNode;
+
+public class SPARCHotSpotLIRGenerator  extends SPARCLIRGenerator implements HotSpotLIRGenerator {
+
+    public StackSlot deoptimizationRescueSlot;
+
+    public SPARCHotSpotLIRGenerator(StructuredGraph graph,
+            CodeCacheProvider runtime, TargetDescription target,
+            FrameMap frameMap, CallingConvention cc, LIR lir) {
+        super(graph, runtime, target, frameMap, cc, lir);
+        // TODO Auto-generated constructor stub
+    }
+
+    @Override
+    public void emitTailcall(Value[] args, Value address) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void emitDeoptimizeCaller(DeoptimizationAction action,
+            DeoptimizationReason reason) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void emitPatchReturnAddress(ValueNode address) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc,
+            ValueNode exception, ValueNode exceptionPc) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public StackSlot getLockSlot(int lockDepth) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Stub getStub() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import static com.oracle.graal.api.code.CodeUtil.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+
+/**
+ * use
+ * 
+ * <pre>
+ * mx unittest AheadOfTimeCompilationTest @-XX:CompileCommand='print,*AheadOfTimeCompilationTest.*'
+ * </pre>
+ * 
+ * to print disassembly.
+ */
+public class AheadOfTimeCompilationTest extends GraalCompilerTest {
+
+    public static final Object STATICFINALOBJECT = new Object();
+
+    public static Object getStaticFinalObject() {
+        return AheadOfTimeCompilationTest.STATICFINALOBJECT;
+    }
+
+    @Test
+    @Ignore
+    public void testStaticFinalObject1() {
+        StructuredGraph result2 = compile("getStaticFinalObject", true);
+        assert result2.getNodes().filter(ConstantNode.class).count() == 1;
+        assert result2.getNodes(FloatingReadNode.class).count() == 1;
+    }
+
+    @Test
+    public void testStaticFinalObject2() {
+        StructuredGraph result1 = compile("getStaticFinalObject", false);
+        assert result1.getNodes().filter(ConstantNode.class).count() == 1;
+        assert result1.getNodes(FloatingReadNode.class).count() == 0;
+    }
+
+    private StructuredGraph compile(String test, boolean compileAOT) {
+        StructuredGraph graph = parse(test);
+        ResolvedJavaMethod method = graph.method();
+
+        boolean originalSetting = GraalOptions.OptCanonicalizeReads.getValue();
+        GraalOptions.OptCanonicalizeReads.setValue(!compileAOT);
+        PhasePlan phasePlan = new PhasePlan();
+        final StructuredGraph graphCopy = graph.copy();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
+        editPhasePlan(method, graph, phasePlan);
+        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
+                        new SpeculationLog());
+        addMethod(method, compResult, graphCopy);
+
+        GraalOptions.OptCanonicalizeReads.setValue(originalSetting);
+
+        return graph;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Tests {@link CompileTheWorld} functionality.
@@ -34,9 +35,11 @@
 
     @Test
     public void testRtJar() throws Throwable {
+        boolean originalSetting = GraalOptions.ExitVMOnException.getValue();
         // Compile a couple classes in rt.jar
         String file = System.getProperty("java.home") + "/lib/rt.jar";
         new CompileTheWorld(file, 1, 5).compile();
+        GraalOptions.ExitVMOnException.setValue(originalSetting);
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.hotspot.test;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.meta.*;
+
+/**
+ * The following tests perform object/array equality and assignments in various ways. The selected
+ * cases have been the problematic ones while implementing the Compressed Oops support.
+ */
+
+public class CompressedOopTest extends GraalCompilerTest {
+
+    private final MetaAccessProvider metaAccessProvider;
+    Object[] argsToBind;
+
+    public CompressedOopTest() {
+        this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class);
+    }
+
+    @Test
+    public void test() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("fieldTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        final Method benchmarkMethod = CompressedOopTest.class.getMethod("benchmark", HotSpotInstalledCode.class, Object.class, Object.class, Object.class);
+        final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod);
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod));
+        Container c1 = new Container();
+        Assert.assertEquals(c1.b, installedBenchmarkCode.executeVarargs(argsToBind[0], c1, c1, c1));
+    }
+
+    @Test
+    public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("arrayTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        final Method benchmarkMethod = CompressedOopTest.class.getMethod("benchmark", HotSpotInstalledCode.class, Object.class, Object.class, Object.class);
+        final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod);
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod));
+        ArrayContainer ac = new ArrayContainer();
+        Assert.assertEquals(ac.a[9], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 0, 9));
+        Assert.assertEquals(ac.a[8], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 1, 8));
+        Assert.assertEquals(ac.a[7], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 2, 7));
+        Assert.assertEquals(ac.a[6], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 3, 6));
+        Assert.assertEquals(ac.a[5], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 4, 5));
+        Assert.assertEquals(ac.a[4], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 5, 4));
+        Assert.assertEquals(ac.a[3], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 6, 3));
+        Assert.assertEquals(ac.a[2], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 7, 2));
+        Assert.assertEquals(ac.a[1], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 8, 1));
+        Assert.assertEquals(ac.a[0], installedBenchmarkCode.executeVarargs(argsToBind[0], ac.a, 9, 0));
+    }
+
+    @Test
+    public void test2() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("arrayCopyTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        ArrayContainer source = new ArrayContainer();
+        ArrayContainer destination = new ArrayContainer();
+        Assert.assertEquals(source.a.length, destination.a.length);
+        Assert.assertFalse(Arrays.equals(source.a, destination.a));
+        fooCode.execute(source.a, destination.a, source.a);
+        Assert.assertArrayEquals(source.a, destination.a);
+    }
+
+    @Test
+    public void test3() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("compareAndSwapTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        Object initial = new Object();
+        Object replacement = new Object();
+        AtomicReference<Object> cas = new AtomicReference<>();
+        Assert.assertEquals(cas.get(), null);
+        fooCode.execute(cas, null, initial);
+        Assert.assertEquals(cas.get(), initial);
+        fooCode.execute(cas, initial, replacement);
+        Assert.assertEquals(cas.get(), replacement);
+    }
+
+    @Test
+    public void test4() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("charArrayCopyTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        StringContainer1 source1 = new StringContainer1();
+        StringContainer2 source2 = new StringContainer2();
+        char[] result = new char[source1.value.length + source2.value.length];
+        fooCode.execute(source1.value, source2.value, result);
+        Assert.assertArrayEquals(new char[]{'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'}, result);
+    }
+
+    @Test
+    public void test5() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("charContainerArrayCopyTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        StringContainer1 source1 = new StringContainer1();
+        StringContainer2 source2 = new StringContainer2();
+        char[] result = new char[source1.value.length + source2.value.length];
+        fooCode.execute(source1, source2, result);
+        Assert.assertArrayEquals(new char[]{'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'}, result);
+    }
+
+    @Test
+    public void test6() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("stringCopyTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        String a = new String("Test ");
+        String b = new String("String");
+        String c = (String) fooCode.execute(a, b, null);
+        Assert.assertTrue(c.equals("Test String"));
+    }
+
+    @Test
+    public void test7() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("queueTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        ArrayDeque<Object> q = new ArrayDeque<>();
+        Object[] objects = new Object[512];
+        for (int i = 0; i < objects.length; i++) {
+            objects[i] = new Object();
+        }
+
+        int j = 0;
+        while (j < objects.length) {
+            fooCode.execute(q, objects[j], null);
+            j++;
+        }
+
+        System.gc();
+        Assert.assertTrue(q.size() == objects.length);
+        Assert.assertTrue(!q.isEmpty());
+
+        j = 0;
+        while (j < objects.length) {
+            Assert.assertTrue(objects[j] == q.remove());
+            j++;
+        }
+
+        Assert.assertTrue(q.size() == 0);
+        Assert.assertTrue(q.isEmpty());
+    }
+
+    @Test
+    public void test8() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("unmodListTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        List<Object> list = new ArrayList<>();
+        for (int i = 0; i < 512; i++) {
+            list.add(new Object());
+        }
+
+        Object[] array = (Object[]) fooCode.execute(list, null, null);
+        Assert.assertTrue(list.size() == array.length);
+        int i = 0;
+        for (Object obj : list) {
+            Assert.assertTrue(obj == array[i]);
+            i++;
+        }
+    }
+
+    @Test
+    public void test9() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("unmodListTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        List<Object> list = new ArrayList<>();
+        Object[] array = (Object[]) fooCode.execute(list, null, null);
+        Assert.assertTrue(list.size() == array.length);
+    }
+
+    public void test10() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("constantTest", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        Container c = new Container();
+        Assert.assertFalse((boolean) fooCode.execute(c, null, null));
+    }
+
+    @Test
+    public void test11() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("stringEqualsTest", String.class, String.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        String s1 = new String("Test");
+        String s2 = new String("Test");
+        boolean result = ((Boolean) (fooCode.execute(s1, s2, null))).booleanValue();
+        Assert.assertTrue(result);
+    }
+
+    @Test
+    public void test12() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = CompressedOopTest.class.getMethod("stringConstantEqualsTest", String.class, String.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
+        String s1 = new String("Test");
+        boolean result = ((Boolean) (fooCode.execute(s1, null, null))).booleanValue();
+        Assert.assertTrue(result);
+    }
+
+    public static Object benchmark(HotSpotInstalledCode code, Object o1, Object o2, Object o3) throws InvalidInstalledCodeException {
+        return code.execute(o1, o2, o3);
+    }
+
+    public static Object fieldTest(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        ((Container) c1).a = ((Container) c1).b;
+        return ((Container) c1).a;
+    }
+
+    public static Object arrayTest(Object c1, Object c2, Object c3) {
+        Object[] array = (Object[]) c1;
+        int initialIndex = ((Integer) c2).intValue();
+        int replacingIndex = ((Integer) c3).intValue();
+        array[initialIndex] = array[replacingIndex];
+        return array[initialIndex];
+    }
+
+    public static void arrayCopyTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        Object[] source = (Object[]) c1;
+        Object[] destination = (Object[]) c2;
+        System.arraycopy(source, 0, destination, 0, source.length);
+    }
+
+    public static String stringCopyTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        String source = (String) c1;
+        String destination = (String) c2;
+        return source + destination;
+    }
+
+    public static char[] charArrayCopyTest(Object c1, Object c2, Object c3) {
+        char[] source1 = (char[]) c1;
+        char[] source2 = (char[]) c2;
+        char[] result = (char[]) c3;
+
+        for (int i = 0; i < source1.length; i++) {
+            result[i] = source1[i];
+        }
+
+        for (int i = 0; i < source2.length; i++) {
+            result[source1.length + i] = source2[i];
+        }
+        return result;
+    }
+
+    public static char[] charContainerArrayCopyTest(Object c1, Object c2, Object c3) {
+        char[] source1 = ((StringContainer1) c1).value;
+        char[] source2 = ((StringContainer2) c2).value;
+        char[] result = (char[]) c3;
+
+        for (int i = 0; i < source1.length; i++) {
+            result[i] = source1[i];
+        }
+
+        for (int i = 0; i < source2.length; i++) {
+            result[source1.length + i] = source2[i];
+        }
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void compareAndSwapTest(Object c1, Object c2, Object c3) throws ClassCastException {
+        AtomicReference<Object> cas = (AtomicReference<Object>) c1;
+        cas.compareAndSet(c2, c3);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static HashMap<Object, Object> hashMapCloneTest(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        HashMap<Object, Object> map = (HashMap<Object, Object>) c1;
+        return (HashMap<Object, Object>) map.clone();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void hashMapCopyTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        HashMap<Object, Object> map = (HashMap<Object, Object>) c1;
+        HashMap<Object, Object> map1 = (HashMap<Object, Object>) c2;
+        map.clear();
+        map.putAll(map1);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void queueTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        ArrayDeque<Object> queue = (ArrayDeque<Object>) c1;
+        queue.add(c2);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Object[] unmodListTest(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        List<Object> queue = (ArrayList<Object>) c1;
+        Object[] result = Collections.unmodifiableCollection(queue).toArray(new Object[queue.size()]);
+        return result;
+    }
+
+    public static Boolean constantTest(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        ConstantContainer container = (ConstantContainer) c1;
+        return container.a.equals(container.b);
+    }
+
+    public static Boolean stringEqualsTest(String c1, String c2, @SuppressWarnings("unused") Object c3) {
+        return c1.equals(c2);
+    }
+
+    public static Boolean stringConstantEqualsTest(String c1, @SuppressWarnings("unused") String c2, @SuppressWarnings("unused") Object c3) {
+        return "Test".equals(c1);
+    }
+
+}
+
+class Container {
+
+    public Object a = new Object();
+    public Object b = new Object();
+}
+
+class ArrayContainer {
+
+    public Object[] a = new Object[10];
+
+    public ArrayContainer() {
+        for (int i = 0; i < 10; i++) {
+            a[i] = new Object();
+        }
+    }
+}
+
+class HashMapContainer {
+
+    public HashMap<Object, Object> a = new HashMap<>();
+
+    public HashMapContainer() {
+        for (int i = 0; i < 10; i++) {
+            a.put(new Object(), new Object());
+        }
+    }
+}
+
+class StringContainer1 {
+
+    public char[] value = new char[5];
+
+    public StringContainer1() {
+        value[0] = 'T';
+        value[1] = 'e';
+        value[2] = 's';
+        value[3] = 't';
+        value[4] = ' ';
+
+    }
+}
+
+class StringContainer2 {
+
+    public char[] value = new char[6];
+
+    public StringContainer2() {
+        value[0] = 'S';
+        value[1] = 't';
+        value[2] = 'r';
+        value[3] = 'i';
+        value[4] = 'n';
+        value[5] = 'g';
+    }
+}
+
+class ConstantContainer {
+
+    public final Object a = new Object();
+    public final Object b = new Object();
+
+    public ConstantContainer() {
+
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri Jun 07 14:15:38 2013 +0200
@@ -24,17 +24,18 @@
 
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
-import java.lang.reflect.Modifier;
+import java.lang.reflect.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CallingConvention.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -62,6 +63,8 @@
     private final int id;
     private final int priority;
 
+    private StructuredGraph graph;
+
     public static CompilationTask create(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id, int priority) {
         return new CompilationTask(graalRuntime, plan, optimisticOpts, method, entryBCI, id, priority);
     }
@@ -107,8 +110,8 @@
                 return;
             }
             inProgress = true;
-            if (GraalOptions.DynamicCompilePriority) {
-                int threadPriority = priority < GraalOptions.SlowQueueCutoff ? Thread.NORM_PRIORITY : Thread.MIN_PRIORITY;
+            if (DynamicCompilePriority.getValue()) {
+                int threadPriority = priority < VMToCompilerImpl.SlowQueueCutoff.getValue() ? Thread.NORM_PRIORITY : Thread.MIN_PRIORITY;
                 if (Thread.currentThread().getPriority() != threadPriority) {
                     Thread.currentThread().setPriority(threadPriority);
                 }
@@ -132,17 +135,17 @@
     public void runCompilation() {
         CompilationStatistics stats = CompilationStatistics.create(method, entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI);
         try (TimerCloseable a = CompilationTime.start()) {
-            final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
+            final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed();
             if (printCompilation) {
                 TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(),
                                 entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") "));
             }
-            if (GraalOptions.HotSpotPrintCompilation) {
+            if (HotSpotPrintCompilation.getValue()) {
                 printCompilation();
             }
 
             CompilationResult result = null;
-            TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
+            TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
             long start = System.currentTimeMillis();
             try {
                 result = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true), new Callable<CompilationResult>() {
@@ -151,7 +154,7 @@
                     public CompilationResult call() throws Exception {
                         graalRuntime.evictDeoptedGraphs();
                         Replacements replacements = graalRuntime.getReplacements();
-                        StructuredGraph graph = replacements.getMethodSubstitution(method);
+                        graph = replacements.getMethodSubstitution(method);
                         if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) {
                             graph = new StructuredGraph(method, entryBCI);
                         } else {
@@ -172,20 +175,22 @@
                 }
             }
 
-            installMethod(result, null);
+            installMethod(result);
         } catch (BailoutException bailout) {
             Debug.metric("Bailouts").increment();
-            if (GraalOptions.ExitVMOnBailout) {
+            if (ExitVMOnBailout.getValue()) {
                 TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method));
                 bailout.printStackTrace(TTY.cachedOut);
                 System.exit(-1);
-            } else if (GraalOptions.PrintBailout) {
+            } else if (PrintBailout.getValue()) {
                 TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method));
                 bailout.printStackTrace(TTY.cachedOut);
             }
         } catch (Throwable t) {
-            if (GraalOptions.ExitVMOnException) {
+            if (PrintStackTraceOnException.getValue() || ExitVMOnException.getValue()) {
                 t.printStackTrace(TTY.cachedOut);
+            }
+            if (ExitVMOnException.getValue()) {
                 System.exit(-1);
             }
         }
@@ -202,7 +207,7 @@
                         MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize()));
     }
 
-    private void installMethod(final CompilationResult compResult, final Graph graph) {
+    private void installMethod(final CompilationResult compResult) {
         Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() {
 
             @Override
@@ -211,6 +216,9 @@
                 if (Debug.isDumpEnabled()) {
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
+                if (Debug.isLogEnabled()) {
+                    Debug.log("%s", graalRuntime.getRuntime().disassemble(installedCode));
+                }
             }
 
         });
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot;
 
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.File;
 import java.lang.reflect.Constructor;
@@ -75,7 +76,7 @@
      * {@link GraalOptions#CompileTheWorldStopAt}.
      */
     public CompileTheWorld() {
-        this(GraalOptions.CompileTheWorld, GraalOptions.CompileTheWorldStartAt, GraalOptions.CompileTheWorldStopAt);
+        this(CompileTheWorld.getValue(), CompileTheWorldStartAt.getValue(), CompileTheWorldStopAt.getValue());
     }
 
     /**
@@ -91,7 +92,7 @@
         this.stopAt = stopAt;
 
         // We don't want the VM to exit when a method fails to compile.
-        GraalOptions.ExitVMOnException = false;
+        ExitVMOnException.setValue(false);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.io.*;
@@ -29,7 +30,6 @@
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.printer.*;
 
 public final class CompilerThread extends Thread {
@@ -60,7 +60,7 @@
     @Override
     public void run() {
         GraalDebugConfig hotspotDebugConfig = null;
-        if (GraalOptions.Debug) {
+        if (DebugEnabled.getValue()) {
             PrintStream log = graalRuntime().getVMToCompiler().log();
             DebugEnvironment.initialize(log);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,9 +25,9 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.ExceptionHandler;
-import com.oracle.graal.api.code.CompilationResult.Mark;
-import com.oracle.graal.api.code.CompilationResult.Site;
+import com.oracle.graal.api.code.CompilationResult.CodeComment;
+import com.oracle.graal.api.code.CompilationResult.JumpTable;
+import com.oracle.graal.api.code.CompilationResult.*;
 
 /**
  * A {@link CompilationResult} with additional HotSpot-specific information required for installing
@@ -40,6 +40,18 @@
 
     public final Site[] sites;
     public final ExceptionHandler[] exceptionHandlers;
+    public final Comment[] comments;
+
+    public static class Comment {
+
+        public final String text;
+        public final int pcOffset;
+
+        public Comment(int pcOffset, String text) {
+            this.text = text;
+            this.pcOffset = pcOffset;
+        }
+    }
 
     public HotSpotCompiledCode(CompilationResult compResult) {
         this.comp = compResult;
@@ -49,6 +61,24 @@
         } else {
             exceptionHandlers = compResult.getExceptionHandlers().toArray(new ExceptionHandler[compResult.getExceptionHandlers().size()]);
         }
+        List<CodeAnnotation> annotations = compResult.getAnnotations();
+        comments = new Comment[annotations.size()];
+        if (!annotations.isEmpty()) {
+            for (int i = 0; i < comments.length; i++) {
+                CodeAnnotation annotation = annotations.get(i);
+                String text;
+                if (annotation instanceof CodeComment) {
+                    CodeComment codeComment = (CodeComment) annotation;
+                    text = codeComment.value;
+                } else if (annotation instanceof JumpTable) {
+                    JumpTable jumpTable = (JumpTable) annotation;
+                    text = "JumpTable [" + jumpTable.low + " .. " + jumpTable.high + "]";
+                } else {
+                    text = annotation.toString();
+                }
+                comments[i] = new Comment(annotation.position, text);
+            }
+        }
     }
 
     static class SiteComparator implements Comparator<Site> {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Fri Jun 07 14:15:38 2013 +0200
@@ -88,11 +88,18 @@
     private final Transition transition;
 
     /**
-     * The locations defined/killed by the call.
+     * The registers and stack slots defined/killed by the call.
      */
     private Value[] temporaries = AllocatableValue.NONE;
 
     /**
+     * The memory locations killed by the call.
+     */
+    private final LocationIdentity[] killedLocations;
+
+    private final boolean reexecutable;
+
+    /**
      * Creates a {@link HotSpotForeignCallLinkage}.
      * 
      * @param descriptor the descriptor of the call
@@ -100,11 +107,16 @@
      * @param effect specifies if the call destroys or preserves all registers (apart from
      *            temporaries which are always destroyed)
      * @param ccType calling convention type
-     * @param transition specifies if this is a {@linkplain #isLeaf() leaf} call
+     * @param transition specifies if this is a {@linkplain #canDeoptimize() leaf} call
+     * @param reexecutable specifies if the call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a call that cannot be
+     *            re-executed.
+     * @param killedLocations the memory locations killed by the call
      */
-    public static HotSpotForeignCallLinkage create(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type ccType, Transition transition) {
+    public static HotSpotForeignCallLinkage create(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type ccType, Transition transition, boolean reexecutable,
+                    LocationIdentity... killedLocations) {
         CallingConvention targetCc = createCallingConvention(descriptor, ccType);
-        return new HotSpotForeignCallLinkage(descriptor, address, effect, transition, targetCc);
+        return new HotSpotForeignCallLinkage(descriptor, address, effect, transition, targetCc, reexecutable, killedLocations);
     }
 
     /**
@@ -130,12 +142,15 @@
         }
     }
 
-    public HotSpotForeignCallLinkage(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Transition transition, CallingConvention cc) {
+    public HotSpotForeignCallLinkage(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Transition transition, CallingConvention cc, boolean reexecutable,
+                    LocationIdentity... killedLocations) {
         this.address = address;
         this.effect = effect;
         this.transition = transition;
         this.descriptor = descriptor;
         this.cc = cc;
+        this.reexecutable = reexecutable;
+        this.killedLocations = killedLocations;
     }
 
     @Override
@@ -153,6 +168,14 @@
         return sb.toString();
     }
 
+    public boolean isReexecutable() {
+        return reexecutable;
+    }
+
+    public LocationIdentity[] getKilledLocations() {
+        return killedLocations;
+    }
+
     public CallingConvention getCallingConvention() {
         return cc;
     }
@@ -212,11 +235,8 @@
         return effect == DESTROYS_REGISTERS;
     }
 
-    /**
-     * Determines if this is call to a function that does not lock, GC or throw exceptions. That is,
-     * the thread's execution state during the call is never inspected by another thread.
-     */
-    public boolean isLeaf() {
-        return transition == Transition.LEAF;
+    @Override
+    public boolean canDeoptimize() {
+        return transition != Transition.LEAF;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Fri Jun 07 14:15:38 2013 +0200
@@ -35,8 +35,11 @@
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 
+//import static com.oracle.graal.phases.GraalOptions.*;
+
 /**
  * Singleton class holding the instance of the {@link GraalRuntime}.
  * 
@@ -84,9 +87,14 @@
         runtime.compilerToVm = toVM;
     }
 
+    // @formatter:off
+    @Option(help = "The runtime configuration to use")
+    private static final OptionValue<String> GraalRuntime = new OptionValue<>("basic");
+    // @formatter:on
+
     protected static HotSpotGraalRuntimeFactory findFactory(String architecture) {
         for (HotSpotGraalRuntimeFactory factory : ServiceLoader.loadInstalled(HotSpotGraalRuntimeFactory.class)) {
-            if (factory.getArchitecture().equals(architecture) && factory.getName().equals(GraalOptions.GraalRuntime)) {
+            if (factory.getArchitecture().equals(architecture) && factory.getName().equals(GraalRuntime.getValue())) {
                 return factory;
             }
         }
@@ -123,9 +131,9 @@
         return unsafe.getInt(object, offset);
     }
 
-    protected/* final */CompilerToVM  compilerToVm;
+    protected/* final */CompilerToVM compilerToVm;
     protected/* final */CompilerToGPU compilerToGpu;
-    protected/* final */VMToCompiler  vmToCompiler;
+    protected/* final */VMToCompiler vmToCompiler;
 
     protected final HotSpotRuntime runtime;
     protected final TargetDescription target;
@@ -138,13 +146,13 @@
     private final HotSpotBackend backend;
 
     protected HotSpotGraalRuntime() {
-        CompilerToVM  toVM  = new CompilerToVMImpl();
+        CompilerToVM toVM = new CompilerToVMImpl();
         CompilerToGPU toGPU = new CompilerToGPUImpl();
 
         // initialize VmToCompiler
         VMToCompiler toCompiler = new VMToCompilerImpl(this);
 
-        compilerToVm  = toVM;
+        compilerToVm = toVM;
         compilerToGpu = toGPU;
         vmToCompiler = toCompiler;
         config = new HotSpotVMConfig();
@@ -153,16 +161,16 @@
 
         // Set some global options:
         if (config.compileTheWorld) {
-            GraalOptions.CompileTheWorld = CompileTheWorld.SUN_BOOT_CLASS_PATH;
+            GraalOptions.CompileTheWorld.setValue(CompileTheWorld.SUN_BOOT_CLASS_PATH);
         }
         if (config.compileTheWorldStartAt != 1) {
-            GraalOptions.CompileTheWorldStartAt = config.compileTheWorldStartAt;
+            GraalOptions.CompileTheWorldStartAt.setValue(config.compileTheWorldStartAt);
         }
         if (config.compileTheWorldStopAt != Integer.MAX_VALUE) {
-            GraalOptions.CompileTheWorldStopAt = config.compileTheWorldStopAt;
+            GraalOptions.CompileTheWorldStopAt.setValue(config.compileTheWorldStopAt);
         }
-        GraalOptions.HotSpotPrintCompilation = config.printCompilation;
-        GraalOptions.HotSpotPrintInlining = config.printInlining;
+        GraalOptions.HotSpotPrintCompilation.setValue(config.printCompilation);
+        GraalOptions.HotSpotPrintInlining.setValue(config.printInlining);
 
         if (Boolean.valueOf(System.getProperty("graal.printconfig"))) {
             printConfig(config);
@@ -180,8 +188,8 @@
         replacements = new HotSpotReplacementsImpl(runtime, assumptions, runtime.getGraalRuntime().getTarget());
 
         backend = createBackend();
-        GraalOptions.StackShadowPages = config.stackShadowPages;
-        if (GraalOptions.CacheGraphs) {
+        GraalOptions.StackShadowPages.setValue(config.stackShadowPages);
+        if (GraalOptions.CacheGraphs.getValue()) {
             cache = new HotSpotGraphCache();
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,14 +23,28 @@
 
 package com.oracle.graal.hotspot;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.hotspot.logging.*;
-import com.oracle.graal.phases.*;
+import com.oracle.graal.options.*;
 
 public class HotSpotOptions {
 
+    private static final Map<String, OptionDescriptor> options = new HashMap<>();
+
+    static {
+        ServiceLoader<Options> sl = ServiceLoader.loadInstalled(Options.class);
+        for (Options opts : sl) {
+            for (OptionDescriptor desc : opts) {
+                if (desc.getClass().getName().startsWith("com.oracle.graal")) {
+                    String name = desc.getName();
+                    OptionDescriptor existing = options.put(name, desc);
+                    assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
+                }
+            }
+        }
+    }
+
     // Called from VM code
     public static boolean setOption(String option) {
         if (option.length() == 0) {
@@ -38,7 +52,7 @@
         }
 
         Object value = null;
-        String fieldName = null;
+        String optionName = null;
         String valueString = null;
 
         if (option.equals("+PrintFlags")) {
@@ -48,70 +62,60 @@
 
         char first = option.charAt(0);
         if (first == '+' || first == '-') {
-            fieldName = option.substring(1);
+            optionName = option.substring(1);
             value = (first == '+');
         } else {
             int index = option.indexOf('=');
             if (index == -1) {
-                fieldName = option;
+                optionName = option;
                 valueString = null;
             } else {
-                fieldName = option.substring(0, index);
+                optionName = option.substring(0, index);
                 valueString = option.substring(index + 1);
             }
         }
 
-        Field f;
-        try {
-            f = GraalOptions.class.getDeclaredField(fieldName);
-            Class<?> fType = f.getType();
+        OptionDescriptor desc = options.get(optionName);
+        if (desc == null) {
+            Logger.info("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)");
+            return false;
+        }
 
-            if (value == null) {
-                if (fType == Boolean.TYPE) {
-                    Logger.info("Value for boolean option '" + fieldName + "' must use '-G:+" + fieldName + "' or '-G:-" + fieldName + "' format");
-                    return false;
-                }
+        Class<?> optionType = desc.getType();
 
-                if (valueString == null) {
-                    Logger.info("Value for option '" + fieldName + "' must use '-G:" + fieldName + "=<value>' format");
-                    return false;
-                }
+        if (value == null) {
+            if (optionType == Boolean.TYPE || optionType == Boolean.class) {
+                Logger.info("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format");
+                return false;
+            }
 
-                if (fType == Float.TYPE) {
-                    value = Float.parseFloat(valueString);
-                } else if (fType == Double.TYPE) {
-                    value = Double.parseDouble(valueString);
-                } else if (fType == Integer.TYPE) {
-                    value = Integer.parseInt(valueString);
-                } else if (fType == String.class) {
-                    value = valueString;
-                }
-            } else {
-                if (fType != Boolean.TYPE) {
-                    Logger.info("Value for option '" + fieldName + "' must use '-G:" + fieldName + "=<value>' format");
-                    return false;
-                }
+            if (valueString == null) {
+                Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
+                return false;
             }
 
-            if (value != null) {
-                f.setAccessible(true);
-                f.set(null, value);
-                // Logger.info("Set option " + fieldName + " to " + value);
-            } else {
-                Logger.info("Wrong value \"" + valueString + "\" for option " + fieldName);
+            if (optionType == Float.class) {
+                value = Float.parseFloat(valueString);
+            } else if (optionType == Double.class) {
+                value = Double.parseDouble(valueString);
+            } else if (optionType == Integer.class) {
+                value = Integer.parseInt(valueString);
+            } else if (optionType == String.class) {
+                value = valueString;
+            }
+        } else {
+            if (optionType != Boolean.class) {
+                Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
                 return false;
             }
-        } catch (SecurityException e) {
-            Logger.info("Security exception when setting option " + option);
-            return false;
-        } catch (NoSuchFieldException e) {
-            Logger.info("Could not find option " + fieldName + " (use -G:+PrintFlags to see Graal options)");
-            return false;
-        } catch (IllegalArgumentException e) {
-            Logger.info("Illegal value for option " + option);
-            return false;
-        } catch (IllegalAccessException e) {
-            Logger.info("Illegal access exception when setting option " + option);
+        }
+
+        if (value != null) {
+            OptionValue<?> optionValue = desc.getOptionValue();
+            optionValue.setValue(value);
+            // Logger.info("Set option " + fieldName + " to " + value);
+        } else {
+            Logger.info("Wrong value \"" + valueString + "\" for option " + optionName);
             return false;
         }
 
@@ -120,23 +124,14 @@
 
     private static void printFlags() {
         Logger.info("[Graal flags]");
-        Field[] flags = GraalOptions.class.getDeclaredFields();
-        Arrays.sort(flags, new Comparator<Field>() {
+        SortedMap<String, OptionDescriptor> sortedOptions = new TreeMap<>(options);
+        for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
+            e.getKey();
+            OptionDescriptor desc = e.getValue();
+            Object value = desc.getOptionValue().getValue();
+            Logger.info(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, desc.getHelp()));
+        }
 
-            public int compare(Field o1, Field o2) {
-                return o1.getName().compareTo(o2.getName());
-            }
-        });
-        for (Field f : flags) {
-            if (Modifier.isPublic(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) {
-                f.setAccessible(true);
-                try {
-                    Object value = f.get(null);
-                    Logger.info(String.format("%9s %-40s = %s", f.getType().getSimpleName(), f.getName(), value));
-                } catch (Exception e) {
-                }
-            }
-        }
         System.exit(0);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Jun 07 14:15:38 2013 +0200
@@ -50,6 +50,13 @@
     public boolean useAESIntrinsics;
     public boolean useG1GC;
 
+    // Compressed Oops related values.
+    public boolean useCompressedOops;
+    public boolean useCompressedKlassPointers;
+    public long narrowOopBase;
+    public int narrowOopShift;
+    public int logMinObjAlignment;
+
     // CPU capabilities
     public int useSSE;
     public int useAVX;
@@ -411,6 +418,7 @@
     public long arithmeticSinAddress;
     public long arithmeticCosAddress;
     public long arithmeticTanAddress;
+    public long loadAndClearExceptionAddress;
 
     public int deoptReasonNone;
     public int deoptReasonNullCheck;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Jun 07 14:15:38 2013 +0200
@@ -129,8 +129,9 @@
     @Override
     public native long getMaxCallTargetOffset(long address);
 
+    // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage
     @Override
-    public native String disassembleCodeBlob(long codeBlob);
+    public synchronized native String disassembleCodeBlob(long codeBlob);
 
     @Override
     public native byte[] getCode(long codeBlob);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,10 +23,12 @@
 
 package com.oracle.graal.hotspot.bridge;
 
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.CompilationTask.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.java.GraphBuilderPhase.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -46,6 +48,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
@@ -57,6 +60,41 @@
  */
 public class VMToCompilerImpl implements VMToCompiler {
 
+    //@formatter:off
+    @Option(help = "File to which compiler logging is sent")
+    private static final OptionValue<String> LogFile = new OptionValue<>(null);
+
+    @Option(help = "Use low priority compilation threads")
+    private static final OptionValue<Boolean> SlowCompileThreads = new OptionValue<>(false);
+
+    @Option(help = "Use priority-based compilation queue")
+    private static final OptionValue<Boolean> PriorityCompileQueue = new OptionValue<>(true);
+
+    @Option(help = "Print compilation queue activity periodically")
+    private static final OptionValue<Boolean> PrintQueue = new OptionValue<>(false);
+
+    @Option(help = "")
+    public static final OptionValue<Integer> SlowQueueCutoff = new OptionValue<>(100000);
+
+    @Option(help = "Time limit in milliseconds for bootstrap (-1 for no limit)")
+    private static final OptionValue<Integer> TimedBootstrap = new OptionValue<>(-1);
+
+    @Option(help = "Number of compilation threads to use")
+    private static final StableOptionValue<Integer> Threads = new StableOptionValue<Integer>() {
+
+        @Override
+        public Integer initialValue() {
+            return Runtime.getRuntime().availableProcessors();
+        }
+    };
+
+    @Option(help = "")
+    private static final OptionValue<Boolean> GenericDynamicCounters = new OptionValue<>(false);
+
+    @Option(help = "")
+    private static final OptionValue<String> BenchmarkDynamicCounters = new OptionValue<>(null);
+    //@formatter:on
+
     private final HotSpotGraalRuntime graalRuntime;
 
     public final HotSpotResolvedPrimitiveType typeBoolean;
@@ -117,41 +155,38 @@
         initMirror(typeLong, offset);
         initMirror(typeVoid, offset);
 
-        if (GraalOptions.LogFile != null) {
+        if (LogFile.getValue() != null) {
             try {
                 final boolean enableAutoflush = true;
-                log = new PrintStream(new FileOutputStream(GraalOptions.LogFile), enableAutoflush);
+                log = new PrintStream(new FileOutputStream(LogFile.getValue()), enableAutoflush);
             } catch (FileNotFoundException e) {
-                throw new RuntimeException("couldn't open log file: " + GraalOptions.LogFile, e);
+                throw new RuntimeException("couldn't open log file: " + LogFile.getValue(), e);
             }
         }
 
         TTY.initialize(log);
 
-        if (GraalOptions.Log == null && GraalOptions.Meter == null && GraalOptions.Time == null && GraalOptions.Dump == null) {
-            if (GraalOptions.MethodFilter != null) {
+        if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null) {
+            if (MethodFilter.getValue() != null) {
                 TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time and Dump options are all null");
             }
         }
 
         if (config.ciTime) {
-            quietMeterAndTime = (GraalOptions.Meter == null && GraalOptions.Time == null);
-            GraalOptions.Debug = true;
-            GraalOptions.Meter = "";
-            GraalOptions.Time = "";
+            quietMeterAndTime = (Meter.getValue() == null && Time.getValue() == null);
+            DebugEnabled.setValue(true);
+            Meter.setValue("");
+            Time.setValue("");
         }
 
-        if (GraalOptions.Debug) {
-            Debug.enable();
-            if (GraalOptions.DebugReplacements) {
-                DebugEnvironment.initialize(log);
-            }
+        if (DebugEnabled.getValue()) {
+            DebugEnvironment.initialize(log);
         }
 
         // Install intrinsics.
         final HotSpotRuntime runtime = graalRuntime.getCapability(HotSpotRuntime.class);
         final Replacements replacements = graalRuntime.getCapability(Replacements.class);
-        if (GraalOptions.Intrinsify) {
+        if (Intrinsify.getValue()) {
             Debug.scope("RegisterReplacements", new Object[]{new DebugDumpScope("RegisterReplacements")}, new Runnable() {
 
                 @Override
@@ -161,7 +196,7 @@
                         provider.registerReplacements(runtime, replacements, runtime.getTarget());
                     }
                     runtime.registerReplacements(replacements);
-                    if (GraalOptions.BootstrapReplacements) {
+                    if (BootstrapReplacements.getValue()) {
                         for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
                             replacements.getMacroSubstitution(method);
                             replacements.getMethodSubstitution(method);
@@ -173,21 +208,17 @@
 
         }
 
-        if (GraalOptions.DebugReplacements) {
-            phaseTransition("replacements");
-        }
+        // Create compilation queue.
+        BlockingQueue<Runnable> queue = PriorityCompileQueue.getValue() ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>();
+        compileQueue = new ThreadPoolExecutor(Threads.getValue(), Threads.getValue(), 0L, TimeUnit.MILLISECONDS, queue, CompilerThread.FACTORY);
 
-        // Create compilation queue.
-        BlockingQueue<Runnable> queue = GraalOptions.PriorityCompileQueue ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>();
-        compileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, queue, CompilerThread.FACTORY);
-
-        if (GraalOptions.SlowCompileThreads) {
-            BlockingQueue<Runnable> slowQueue = GraalOptions.PriorityCompileQueue ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>();
-            slowCompileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, slowQueue, CompilerThread.LOW_PRIORITY_FACTORY);
+        if (SlowCompileThreads.getValue()) {
+            BlockingQueue<Runnable> slowQueue = PriorityCompileQueue.getValue() ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>();
+            slowCompileQueue = new ThreadPoolExecutor(Threads.getValue(), Threads.getValue(), 0L, TimeUnit.MILLISECONDS, slowQueue, CompilerThread.LOW_PRIORITY_FACTORY);
         }
 
         // Create queue status printing thread.
-        if (GraalOptions.PrintQueue) {
+        if (PrintQueue.getValue()) {
             Thread t = new Thread() {
 
                 @Override
@@ -209,8 +240,8 @@
             t.start();
         }
 
-        if (GraalOptions.BenchmarkDynamicCounters != null) {
-            String[] arguments = GraalOptions.BenchmarkDynamicCounters.split(",");
+        if (BenchmarkDynamicCounters.getValue() != null) {
+            String[] arguments = BenchmarkDynamicCounters.getValue().split(",");
             if (arguments.length == 0 || (arguments.length % 3) != 0) {
                 throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)");
             }
@@ -228,7 +259,7 @@
             DynamicCounterNode.excludedClassPrefix = "Lcom/oracle/graal/";
             DynamicCounterNode.enabled = true;
         }
-        if (GraalOptions.GenericDynamicCounters) {
+        if (GenericDynamicCounters.getValue()) {
             DynamicCounterNode.enabled = true;
         }
         compilerStartTime = System.nanoTime();
@@ -382,7 +413,7 @@
                     TTY.flush();
                 }
             }
-        } while ((System.currentTimeMillis() - startTime) <= GraalOptions.TimedBootstrap);
+        } while ((System.currentTimeMillis() - startTime) <= TimedBootstrap.getValue());
 
         phaseTransition("bootstrap");
 
@@ -395,7 +426,7 @@
         System.gc();
         phaseTransition("bootstrap2");
 
-        if (GraalOptions.CompileTheWorld != null) {
+        if (CompileTheWorld.getValue() != null) {
             new CompileTheWorld().compile();
             System.exit(0);
         }
@@ -413,7 +444,7 @@
     private static void shutdownCompileQueue(ThreadPoolExecutor queue) throws InterruptedException {
         if (queue != null) {
             queue.shutdown();
-            if (Debug.isEnabled() && GraalOptions.Dump != null) {
+            if (Debug.isEnabled() && Dump.getValue() != null) {
                 // Wait 2 seconds to flush out all graph dumps that may be of interest
                 queue.awaitTermination(2, TimeUnit.SECONDS);
             }
@@ -437,9 +468,9 @@
                 ArrayList<DebugValue> sortedValues = new ArrayList<>(debugValues);
                 Collections.sort(sortedValues);
 
-                if (GraalOptions.SummarizeDebugValues) {
+                if (SummarizeDebugValues.getValue()) {
                     printSummary(topLevelMaps, sortedValues);
-                } else if (GraalOptions.PerThreadDebugValues) {
+                } else if (PerThreadDebugValues.getValue()) {
                     for (DebugValueMap map : topLevelMaps) {
                         TTY.println("Showing the results for thread: " + map.getName());
                         map.group();
@@ -449,13 +480,13 @@
                 } else {
                     DebugValueMap globalMap = new DebugValueMap("Global");
                     for (DebugValueMap map : topLevelMaps) {
-                        if (GraalOptions.SummarizePerPhase) {
+                        if (SummarizePerPhase.getValue()) {
                             flattenChildren(map, globalMap);
                         } else {
                             globalMap.addChild(map);
                         }
                     }
-                    if (!GraalOptions.SummarizePerPhase) {
+                    if (!SummarizePerPhase.getValue()) {
                         globalMap.group();
                     }
                     globalMap.normalize();
@@ -471,7 +502,7 @@
         }
 
         SnippetCounter.printGroups(TTY.out().out());
-        if (GraalOptions.GenericDynamicCounters) {
+        if (GenericDynamicCounters.getValue()) {
             DynamicCounterNode.dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d);
         }
     }
@@ -581,7 +612,7 @@
                         return true;
                     }
                 } else {
-                    if (GraalOptions.PriorityCompileQueue) {
+                    if (PriorityCompileQueue.getValue()) {
                         // normally compilation tasks will only be re-queued when they get a
                         // priority boost, so cancel the old task and add a new one
                         current.cancel();
@@ -604,7 +635,7 @@
             } else {
                 try {
                     method.setCurrentTask(task);
-                    if (GraalOptions.SlowCompileThreads && priority > GraalOptions.SlowQueueCutoff) {
+                    if (SlowCompileThreads.getValue() && priority > SlowQueueCutoff.getValue()) {
                         slowCompileQueue.execute(task);
                     } else {
                         compileQueue.execute(task);
@@ -742,7 +773,7 @@
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase());
         }
         phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
-        if (GraalOptions.VerifyPhases) {
+        if (VerifyPhases.getValue()) {
             phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierVerificationPhase());
 
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.io.*;
 import java.lang.ref.*;
 import java.util.*;
@@ -30,7 +32,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 
 /**
  * This class implements the graph caching system for the HotSpot platform.
@@ -73,12 +74,12 @@
         private static final long serialVersionUID = -3973307040793397840L;
 
         public LRUCache() {
-            super(GraalOptions.GraphCacheSize * 2, 0.75f, false);
+            super(GraphCacheSize.getValue() * 2, 0.75f, false);
         }
 
         @Override
         protected boolean removeEldestEntry(Entry<Long, WeakReference<ResolvedJavaMethod>> eldest) {
-            if (size() > GraalOptions.GraphCacheSize) {
+            if (size() > GraphCacheSize.getValue()) {
                 ResolvedJavaMethod method = eldest.getValue().get();
                 if (method != null) {
                     StructuredGraph cachedGraph = (StructuredGraph) method.getCompilerStorage().get(HotSpotGraphCache.this);
@@ -96,7 +97,7 @@
     private final Map<Long, WeakReference<ResolvedJavaMethod>> cachedGraphIds = Collections.synchronizedMap(new LRUCache());
 
     public HotSpotGraphCache() {
-        if (GraalOptions.PrintGraphCache) {
+        if (PrintGraphCache.getValue()) {
             Runtime.getRuntime().addShutdownHook(new Thread() {
 
                 @Override
@@ -115,7 +116,7 @@
     public StructuredGraph get(ResolvedJavaMethod method) {
         StructuredGraph result = (StructuredGraph) method.getCompilerStorage().get(this);
 
-        if (GraalOptions.PrintGraphCache) {
+        if (PrintGraphCache.getValue()) {
             if (result == null) {
                 missCounter++;
             } else {
@@ -131,7 +132,7 @@
         cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method()));
         graph.method().getCompilerStorage().put(this, graph);
 
-        if (GraalOptions.PrintGraphCache) {
+        if (PrintGraphCache.getValue()) {
             putCounter++;
         }
     }
@@ -161,12 +162,12 @@
                 StructuredGraph cachedGraph = (StructuredGraph) method.getCompilerStorage().get(this);
                 if (cachedGraph != null && cachedGraph.graphId() == graphId) {
                     method.getCompilerStorage().remove(this);
-                    if (GraalOptions.PrintGraphCache) {
+                    if (PrintGraphCache.getValue()) {
                         removeHitCounter++;
                     }
                 }
             }
-            if (GraalOptions.PrintGraphCache) {
+            if (PrintGraphCache.getValue()) {
                 removeCounter++;
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Fri Jun 07 14:15:38 2013 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -32,7 +33,6 @@
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.phases.*;
 
 /**
  * Access to a HotSpot MethodData structure (defined in methodData.hpp).
@@ -376,7 +376,7 @@
         protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
 
         private static JavaTypeProfile createTypeProfile(TriState nullSeen, ResolvedJavaType[] types, long[] counts, long totalCount, int entries) {
-            if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) {
+            if (entries <= 0 || totalCount < MatureExecutionsTypeProfile.getValue()) {
                 return null;
             }
 
@@ -484,7 +484,7 @@
         }
 
         private static JavaMethodProfile createMethodProfile(ResolvedJavaMethod[] methods, long[] counts, long totalCount, int entries) {
-            if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) {
+            if (entries <= 0 || totalCount < MatureExecutionsTypeProfile.getValue()) {
                 return null;
             }
 
@@ -540,7 +540,7 @@
             long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
             long total = takenCount + notTakenCount;
 
-            if (total < GraalOptions.MatureExecutionsBranch) {
+            if (total < MatureExecutionsBranch.getValue()) {
                 return -1;
             } else {
                 return takenCount / (double) total;
@@ -607,7 +607,7 @@
                 result[i - 1] = count;
             }
 
-            if (totalCount < GraalOptions.MatureExecutionsPerSwitchCase * length) {
+            if (totalCount < MatureExecutionsPerSwitchCase.getValue() * length) {
                 return null;
             } else {
                 for (int i = 0; i < length; i++) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Fri Jun 07 14:15:38 2013 +0200
@@ -31,8 +31,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
-import com.oracle.graal.phases.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.replacements.*;
 
 /**
@@ -84,7 +83,7 @@
             assert Modifier.isStatic(flags);
             if (constant == null) {
                 if (holder.isInitialized() && !holder.getName().equals(SystemClassName)) {
-                    if (Modifier.isFinal(getModifiers()) || assumeStaticFieldsFinal(holder.mirror())) {
+                    if (Modifier.isFinal(getModifiers())) {
                         constant = readValue(receiver);
                     }
                 }
@@ -96,11 +95,18 @@
              * have a non-default value.
              */
             assert !Modifier.isStatic(flags);
+            Object object = receiver.asObject();
             if (Modifier.isFinal(getModifiers())) {
                 Constant value = readValue(receiver);
-                if (assumeNonStaticFinalFieldsAsFinal(receiver.asObject().getClass()) || !value.isDefaultForKind()) {
+                if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) {
                     return value;
                 }
+            } else {
+                Class<?> clazz = object.getClass();
+                if (StableOptionValue.class.isAssignableFrom(clazz)) {
+                    StableOptionValue<?> option = (StableOptionValue<?>) object;
+                    return Constant.forObject(option.getValue());
+                }
             }
         }
         return null;
@@ -120,10 +126,6 @@
         }
     }
 
-    private static boolean assumeStaticFieldsFinal(Class<?> clazz) {
-        return clazz == GraalOptions.class;
-    }
-
     private static boolean assumeNonStaticFinalFieldsAsFinal(Class<?> clazz) {
         return clazz == SnippetCounter.class;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -37,7 +38,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
-import com.oracle.graal.phases.*;
 
 /**
  * Implementation of {@link JavaMethod} for resolved HotSpot methods.
@@ -276,7 +276,7 @@
     public ProfilingInfo getProfilingInfo() {
         ProfilingInfo info;
 
-        if (GraalOptions.UseProfilingInformation && methodData == null) {
+        if (UseProfilingInformation.getValue() && methodData == null) {
             long metaspaceMethodData = unsafeReadWord(metaspaceMethod + graalRuntime().getConfig().methodDataOffset);
             if (metaspaceMethodData != 0) {
                 methodData = new HotSpotMethodData(metaspaceMethodData);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Fri Jun 07 14:15:38 2013 +0200
@@ -313,6 +313,7 @@
 
     @Override
     public boolean isAssignableFrom(ResolvedJavaType other) {
+        assert other != null;
         if (other instanceof HotSpotResolvedObjectType) {
             HotSpotResolvedObjectType otherType = (HotSpotResolvedObjectType) other;
             return javaMirror.isAssignableFrom(otherType.javaMirror);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Fri Jun 07 14:15:38 2013 +0200
@@ -129,6 +129,7 @@
 
     @Override
     public boolean isAssignableFrom(ResolvedJavaType other) {
+        assert other != null;
         return other == this;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,6 +26,7 @@
 import static com.oracle.graal.api.code.DeoptimizationAction.*;
 import static com.oracle.graal.api.code.MemoryBarriers.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
@@ -38,6 +39,7 @@
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
 import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*;
 import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
 import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*;
@@ -48,6 +50,7 @@
 import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
 import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.Log.*;
 import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
 
@@ -74,15 +77,15 @@
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.printer.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
@@ -95,6 +98,7 @@
     public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class);
     public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class);
     public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class);
+    public static final ForeignCallDescriptor LOAD_AND_CLEAR_EXCEPTION = new ForeignCallDescriptor("load_and_clear_exception", Object.class, Word.class);
 
     public final HotSpotVMConfig config;
 
@@ -190,18 +194,29 @@
 
     /**
      * Creates and registers the details for linking a foreign call to a {@link Stub}.
+     * 
+     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a stub call that cannot
+     *            be re-executed.
+     * @param killedLocations the memory locations killed by the stub call
      */
-    protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor) {
-        return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF));
+    protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, LocationIdentity... killedLocations) {
+        return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations));
     }
 
     /**
      * Creates and registers the linkage for a foreign call.
+     * 
+     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a stub call that cannot
+     *            be re-executed.
+     * @param killedLocations the memory locations killed by the stub call
      */
-    protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type ccType, RegisterEffect effect, Transition transition) {
+    protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type ccType, RegisterEffect effect, Transition transition,
+                    boolean reexecutable, LocationIdentity... killedLocations) {
         Class<?> resultType = descriptor.getResultType();
-        assert resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "foreign calls must return objects in thread local storage: " + descriptor;
-        return register(HotSpotForeignCallLinkage.create(descriptor, address, effect, ccType, transition));
+        assert transition == LEAF || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor;
+        return register(HotSpotForeignCallLinkage.create(descriptor, address, effect, ccType, transition, reexecutable, killedLocations));
     }
 
     private static void link(Stub stub) {
@@ -215,9 +230,13 @@
      * @param address the address of the code to call
      * @param prependThread true if the JavaThread value for the current thread is to be prepended
      *            to the arguments for the call to {@code address}
+     * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
+     *            side effects. Deoptimization will not return to a point before a foreign call that
+     *            cannot be re-executed.
+     * @param killedLocations the memory locations killed by the foreign call
      */
-    private void linkForeignCall(ForeignCallDescriptor descriptor, long address, boolean prependThread, Replacements replacements) {
-        ForeignCallStub stub = new ForeignCallStub(address, descriptor, prependThread, this, replacements);
+    private void linkForeignCall(Replacements replacements, ForeignCallDescriptor descriptor, long address, boolean prependThread, boolean reexecutable, LocationIdentity... killedLocations) {
+        ForeignCallStub stub = new ForeignCallStub(this, replacements, address, descriptor, prependThread, reexecutable, killedLocations);
         HotSpotForeignCallLinkage linkage = stub.getLinkage();
         HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage();
         linkage.setCompiledStub(stub);
@@ -225,78 +244,87 @@
         register(targetLinkage);
     }
 
-    public void registerReplacements(Replacements replacements) {
+    public static final boolean PREPEND_THREAD = true;
+    public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD;
+
+    public static final boolean REEXECUTABLE = true;
+    public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE;
+
+    public static final LocationIdentity[] NO_LOCATIONS = {};
+
+    public void registerReplacements(Replacements r) {
         HotSpotVMConfig c = config;
         TargetDescription target = getTarget();
 
-        registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF);
-        registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF);
+        registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
 
-        registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
-        registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
-        registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
-        registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
-        registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF);
+        registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
 
-        registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
-        registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
-        registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
-        registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
-        registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF);
+        registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
 
-        link(new NewInstanceStub(this, replacements, target, registerStubCall(NEW_INSTANCE)));
-        link(new NewArrayStub(this, replacements, target, registerStubCall(NEW_ARRAY)));
-        link(new ExceptionHandlerStub(this, replacements, target, foreignCalls.get(EXCEPTION_HANDLER)));
-        link(new UnwindExceptionToCallerStub(this, replacements, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER)));
-        link(new VerifyOopStub(this, replacements, target, registerStubCall(VERIFY_OOP)));
+        link(new NewInstanceStub(this, r, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, ANY_LOCATION)));
+        link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, ANY_LOCATION)));
+        link(new ExceptionHandlerStub(this, r, target, foreignCalls.get(EXCEPTION_HANDLER)));
+        link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, ANY_LOCATION)));
+        link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, NO_LOCATIONS)));
 
-        linkForeignCall(IDENTITY_HASHCODE, c.identityHashCodeAddress, true, replacements);
-        linkForeignCall(REGISTER_FINALIZER, c.registerFinalizerAddress, true, replacements);
-        linkForeignCall(CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, true, replacements);
-        linkForeignCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, true, replacements);
-        linkForeignCall(MONITORENTER, c.monitorenterAddress, true, replacements);
-        linkForeignCall(MONITOREXIT, c.monitorexitAddress, true, replacements);
-        linkForeignCall(WRITE_BARRIER_PRE, c.writeBarrierPreAddress, true, replacements);
-        linkForeignCall(WRITE_BARRIER_POST, c.writeBarrierPostAddress, true, replacements);
-        linkForeignCall(NEW_MULTI_ARRAY, c.newMultiArrayAddress, true, replacements);
-        linkForeignCall(LOG_PRINTF, c.logPrintfAddress, true, replacements);
-        linkForeignCall(LOG_OBJECT, c.logObjectAddress, true, replacements);
-        linkForeignCall(LOG_PRIMITIVE, c.logPrimitiveAddress, true, replacements);
-        linkForeignCall(THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, true, replacements);
-        linkForeignCall(VM_ERROR, c.vmErrorAddress, true, replacements);
-        linkForeignCall(OSR_MIGRATION_END, c.osrMigrationEndAddress, false, replacements);
+        linkForeignCall(r, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_REEXECUTABLE, MARK_WORD_LOCATION);
+        linkForeignCall(r, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, WRITE_BARRIER_PRE, c.writeBarrierPreAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, WRITE_BARRIER_POST, c.writeBarrierPostAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, NOT_REEXECUTABLE, NO_LOCATIONS);
 
-        if (GraalOptions.IntrinsifyObjectMethods) {
-            replacements.registerSubstitutions(ObjectSubstitutions.class);
+        if (IntrinsifyObjectMethods.getValue()) {
+            r.registerSubstitutions(ObjectSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifySystemMethods) {
-            replacements.registerSubstitutions(SystemSubstitutions.class);
+        if (IntrinsifySystemMethods.getValue()) {
+            r.registerSubstitutions(SystemSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyThreadMethods) {
-            replacements.registerSubstitutions(ThreadSubstitutions.class);
+        if (IntrinsifyThreadMethods.getValue()) {
+            r.registerSubstitutions(ThreadSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyUnsafeMethods) {
-            replacements.registerSubstitutions(UnsafeSubstitutions.class);
+        if (IntrinsifyUnsafeMethods.getValue()) {
+            r.registerSubstitutions(UnsafeSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyClassMethods) {
-            replacements.registerSubstitutions(ClassSubstitutions.class);
+        if (IntrinsifyClassMethods.getValue()) {
+            r.registerSubstitutions(ClassSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyAESMethods) {
-            replacements.registerSubstitutions(AESCryptSubstitutions.class);
-            replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class);
+        if (IntrinsifyAESMethods.getValue()) {
+            r.registerSubstitutions(AESCryptSubstitutions.class);
+            r.registerSubstitutions(CipherBlockChainingSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyReflectionMethods) {
-            replacements.registerSubstitutions(ReflectionSubstitutions.class);
+        if (IntrinsifyReflectionMethods.getValue()) {
+            r.registerSubstitutions(ReflectionSubstitutions.class);
         }
 
-        checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        newObjectSnippets = new NewObjectSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        monitorSnippets = new MonitorSnippets.Templates(this, replacements, graalRuntime.getTarget(), c.useFastLocking);
-        writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget());
-        exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget());
+        checkcastSnippets = new CheckCastSnippets.Templates(this, r, graalRuntime.getTarget());
+        instanceofSnippets = new InstanceOfSnippets.Templates(this, r, graalRuntime.getTarget());
+        newObjectSnippets = new NewObjectSnippets.Templates(this, r, graalRuntime.getTarget());
+        monitorSnippets = new MonitorSnippets.Templates(this, r, graalRuntime.getTarget(), c.useFastLocking);
+        writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, r, graalRuntime.getTarget());
+        boxingSnippets = new BoxingSnippets.Templates(this, r, graalRuntime.getTarget());
+        exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, r, graalRuntime.getTarget());
     }
 
     public HotSpotGraalRuntime getGraalRuntime() {
@@ -449,7 +477,8 @@
         if (n instanceof ArrayLengthNode) {
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
             ValueNode array = arrayLengthNode.array();
-            ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt()));
+            ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(),
+                            WriteBarrierType.NONE, false));
             tool.createNullCheckGuard(arrayLengthRead, array);
             graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
         } else if (n instanceof Invoke) {
@@ -464,7 +493,7 @@
                 JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
 
                 LoweredCallTargetNode loweredCallTarget = null;
-                if (callTarget.invokeKind() == InvokeKind.Virtual && GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || invoke.isPolymorphic())) {
+                if (callTarget.invokeKind() == InvokeKind.Virtual && InlineVTableStubs.getValue() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) {
 
                     HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
                     if (!hsMethod.getDeclaringClass().isInterface()) {
@@ -476,8 +505,8 @@
                             // We use LocationNode.ANY_LOCATION for the reads that access the
                             // compiled code entry as HotSpot does not guarantee they are final
                             // values.
-                            ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
-                                            StampFactory.forKind(wordKind())));
+                            ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
+                                            StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false));
 
                             loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
                                             CallingConvention.Type.JavaCall));
@@ -500,7 +529,8 @@
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
             ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object();
             assert loadField.kind() != Kind.Illegal;
-            ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp()));
+            ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp(), WriteBarrierType.NONE,
+                            (loadField.kind() == Kind.Object && !field.getName().equals("classMirrorOffset"))));
             tool.createNullCheckGuard(memoryRead, object);
 
             graph.replaceFixedWithFixed(loadField, memoryRead);
@@ -516,7 +546,7 @@
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
             ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object();
             WriteBarrierType barrierType = getFieldStoreBarrierType(storeField);
-            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field), barrierType));
+            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field), barrierType, storeField.field().getKind() == Kind.Object));
             tool.createNullCheckGuard(memoryWrite, object);
             memoryWrite.setStateAfter(storeField.stateAfter());
             graph.replaceFixedWithFixed(storeField, memoryWrite);
@@ -532,15 +562,18 @@
         } else if (n instanceof CompareAndSwapNode) {
             // Separate out GC barrier semantics
             CompareAndSwapNode cas = (CompareAndSwapNode) n;
-            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
+            LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
             cas.setLocation(location);
             cas.setWriteBarrierType(getCompareAndSwapBarrier(cas));
+            if (cas.expected().kind() == Kind.Object) {
+                cas.setCompress();
+            }
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
             GuardingNode boundsCheck = createBoundsCheck(loadIndexed, tool);
             Kind elementKind = loadIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index());
-            ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp()));
+            ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), WriteBarrierType.NONE, elementKind == Kind.Object));
             memoryRead.setGuard(boundsCheck);
             graph.replaceFixedWithFixed(loadIndexed, memoryRead);
         } else if (n instanceof StoreIndexedNode) {
@@ -562,7 +595,7 @@
                     }
                 } else {
                     LoadHubNode arrayClass = graph.add(new LoadHubNode(array, wordKind));
-                    LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph);
+                    LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph);
                     FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind())));
                     CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true));
                     graph.addBeforeFixed(storeIndexed, checkcast);
@@ -571,7 +604,7 @@
                 }
             }
             WriteBarrierType barrierType = getArrayStoreBarrierType(storeIndexed);
-            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType));
+            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object));
             memoryWrite.setGuard(boundsCheck);
             memoryWrite.setStateAfter(storeIndexed.stateAfter());
             graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
@@ -579,18 +612,18 @@
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != Kind.Illegal;
-            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
-            ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp()));
+            IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
+            ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), WriteBarrierType.NONE, (!load.object().isNullConstant() && load.accessKind() == Kind.Object)));
             // An unsafe read must not floating outside its block as may float above an explicit
             // null check on its object.
             memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
             graph.replaceFixedWithFixed(load, memoryRead);
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
-            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
+            IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
             ValueNode object = store.object();
             WriteBarrierType barrierType = getUnsafeStoreBarrierType(store);
-            WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType));
+            WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object));
             write.setStateAfter(store.stateAfter());
             graph.replaceFixedWithFixed(store, write);
         } else if (n instanceof LoadHubNode) {
@@ -606,103 +639,115 @@
             graph.replaceFixed(loadMethodNode, metaspaceMethod);
         } else if (n instanceof FixedGuardNode) {
             FixedGuardNode node = (FixedGuardNode) n;
-            ValueAnchorNode newAnchor = graph.add(new ValueAnchorNode(tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated()).asNode()));
+            GuardingNode guard = tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated());
+            ValueAnchorNode newAnchor = graph.add(new ValueAnchorNode(guard.asNode()));
+            node.replaceAtUsages(guard.asNode());
             graph.replaceFixedWithFixed(node, newAnchor);
         } else if (n instanceof CommitAllocationNode) {
-            CommitAllocationNode commit = (CommitAllocationNode) n;
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                CommitAllocationNode commit = (CommitAllocationNode) n;
 
-            ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
-                int entryCount = virtual.entryCount();
+                ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
+                    int entryCount = virtual.entryCount();
 
-                FixedWithNextNode newObject;
-                if (virtual instanceof VirtualInstanceNode) {
-                    newObject = graph.add(new NewInstanceNode(virtual.type(), true));
-                } else {
-                    ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType();
-                    newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true));
+                    FixedWithNextNode newObject;
+                    if (virtual instanceof VirtualInstanceNode) {
+                        newObject = graph.add(new NewInstanceNode(virtual.type(), true));
+                    } else {
+                        ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType();
+                        newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true));
+                    }
+                    graph.addBeforeFixed(commit, newObject);
+                    allocations[objIndex] = newObject;
                 }
-                graph.addBeforeFixed(commit, newObject);
-                allocations[objIndex] = newObject;
-            }
-            int valuePos = 0;
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
-                int entryCount = virtual.entryCount();
+                int valuePos = 0;
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
+                    int entryCount = virtual.entryCount();
 
-                ValueNode newObject = allocations[objIndex];
-                if (virtual instanceof VirtualInstanceNode) {
-                    VirtualInstanceNode instance = (VirtualInstanceNode) virtual;
-                    for (int i = 0; i < entryCount; i++) {
-                        ValueNode value = commit.getValues().get(valuePos++);
-                        if (value instanceof VirtualObjectNode) {
-                            value = allocations[commit.getVirtualObjects().indexOf(value)];
-                        }
-                        if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                            graph.addBeforeFixed(commit, graph.add(new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) instance.field(i)), WriteBarrierType.NONE)));
+                    ValueNode newObject = allocations[objIndex];
+                    if (virtual instanceof VirtualInstanceNode) {
+                        VirtualInstanceNode instance = (VirtualInstanceNode) virtual;
+                        for (int i = 0; i < entryCount; i++) {
+                            ValueNode value = commit.getValues().get(valuePos++);
+                            if (value instanceof VirtualObjectNode) {
+                                value = allocations[commit.getVirtualObjects().indexOf(value)];
+                            }
+                            if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
+                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) instance.field(i)), WriteBarrierType.NONE,
+                                                instance.field(i).getKind() == Kind.Object);
+
+                                graph.addBeforeFixed(commit, graph.add(write));
+                            }
                         }
-                    }
-                } else {
-                    VirtualArrayNode array = (VirtualArrayNode) virtual;
-                    ResolvedJavaType element = array.componentType();
-                    for (int i = 0; i < entryCount; i++) {
-                        ValueNode value = commit.getValues().get(valuePos++);
-                        if (value instanceof VirtualObjectNode) {
-                            int indexOf = commit.getVirtualObjects().indexOf(value);
-                            assert indexOf != -1 : commit + " " + value;
-                            value = allocations[indexOf];
-                        }
-                        if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                            graph.addBeforeFixed(commit,
-                                            graph.add(new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE)));
+
+                    } else {
+                        VirtualArrayNode array = (VirtualArrayNode) virtual;
+                        ResolvedJavaType element = array.componentType();
+                        for (int i = 0; i < entryCount; i++) {
+                            ValueNode value = commit.getValues().get(valuePos++);
+                            if (value instanceof VirtualObjectNode) {
+                                int indexOf = commit.getVirtualObjects().indexOf(value);
+                                assert indexOf != -1 : commit + " " + value;
+                                value = allocations[indexOf];
+                            }
+                            if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
+                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE,
+                                                value.kind() == Kind.Object);
+                                graph.addBeforeFixed(commit, graph.add(write));
+                            }
                         }
                     }
                 }
-            }
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
-                allocations[objIndex] = anchor;
-                graph.addBeforeFixed(commit, anchor);
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
+                    allocations[objIndex] = anchor;
+                    graph.addBeforeFixed(commit, anchor);
+                }
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    for (int lockDepth : commit.getLocks().get(objIndex)) {
+                        MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth));
+                        graph.addBeforeFixed(commit, enter);
+                    }
+                }
+                for (Node usage : commit.usages().snapshot()) {
+                    AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
+                    int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
+                    graph.replaceFloating(addObject, allocations[index]);
+                }
+                graph.removeFixed(commit);
             }
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                for (int lockDepth : commit.getLocks().get(objIndex)) {
-                    MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth));
-                    graph.addBeforeFixed(commit, enter);
-                }
-            }
-            for (Node usage : commit.usages().snapshot()) {
-                AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
-                int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
-                graph.replaceFloating(addObject, allocations[index]);
-            }
-            graph.removeFixed(commit);
         } else if (n instanceof CheckCastNode) {
             checkcastSnippets.lower((CheckCastNode) n, tool);
         } else if (n instanceof OSRStartNode) {
-            OSRStartNode osrStart = (OSRStartNode) n;
-            StartNode newStart = graph.add(new StartNode());
-            LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
-            ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(OSR_MIGRATION_END, buffer));
-            newStart.setStateAfter(osrStart.stateAfter());
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                OSRStartNode osrStart = (OSRStartNode) n;
+                StartNode newStart = graph.add(new StartNode());
+                LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
+                ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(this, OSR_MIGRATION_END, buffer));
+                migrationEnd.setStateAfter(osrStart.stateAfter());
 
-            newStart.setNext(migrationEnd);
-            FixedNode next = osrStart.next();
-            osrStart.setNext(null);
-            migrationEnd.setNext(next);
-            graph.setStart(newStart);
+                newStart.setNext(migrationEnd);
+                FixedNode next = osrStart.next();
+                osrStart.setNext(null);
+                migrationEnd.setNext(next);
+                graph.setStart(newStart);
 
-            // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
-            int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
-            for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
-                int size = FrameStateBuilder.stackSlots(osrLocal.kind());
-                int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
-                UnsafeLoadNode load = graph.add(new UnsafeLoadNode(buffer, offset, ConstantNode.forInt(0, graph), osrLocal.kind()));
-                osrLocal.replaceAndDelete(load);
-                graph.addBeforeFixed(migrationEnd, load);
+                // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
+                int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
+                for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
+                    int size = FrameStateBuilder.stackSlots(osrLocal.kind());
+                    int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
+                    IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1);
+                    ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), WriteBarrierType.NONE, false));
+                    osrLocal.replaceAndDelete(load);
+                    graph.addBeforeFixed(migrationEnd, load);
+                }
+                osrStart.replaceAtUsages(newStart);
+                osrStart.safeDelete();
             }
-            osrStart.replaceAtUsages(newStart);
-            osrStart.safeDelete();
         } else if (n instanceof CheckCastDynamicNode) {
             checkcastSnippets.lower((CheckCastDynamicNode) n);
         } else if (n instanceof InstanceOfNode) {
@@ -710,19 +755,29 @@
         } else if (n instanceof InstanceOfDynamicNode) {
             instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
         } else if (n instanceof NewInstanceNode) {
-            newObjectSnippets.lower((NewInstanceNode) n);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                newObjectSnippets.lower((NewInstanceNode) n);
+            }
         } else if (n instanceof NewArrayNode) {
-            newObjectSnippets.lower((NewArrayNode) n);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                newObjectSnippets.lower((NewArrayNode) n);
+            }
         } else if (n instanceof MonitorEnterNode) {
-            monitorSnippets.lower((MonitorEnterNode) n, tool);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                monitorSnippets.lower((MonitorEnterNode) n, tool);
+            }
         } else if (n instanceof MonitorExitNode) {
-            monitorSnippets.lower((MonitorExitNode) n, tool);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                monitorSnippets.lower((MonitorExitNode) n, tool);
+            }
         } else if (n instanceof SerialWriteBarrier) {
             writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
         } else if (n instanceof SerialArrayRangeWriteBarrier) {
             writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
         } else if (n instanceof NewMultiArrayNode) {
-            newObjectSnippets.lower((NewMultiArrayNode) n);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                newObjectSnippets.lower((NewMultiArrayNode) n);
+            }
         } else if (n instanceof LoadExceptionObjectNode) {
             exceptionObjectSnippets.lower((LoadExceptionObjectNode) n);
         } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
@@ -749,14 +804,15 @@
         assert vtableEntryOffset > 0;
         // We use LocationNode.ANY_LOCATION for the reads that access the vtable
         // entry as HotSpot does not guarantee that this is a final value.
-        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind())));
+        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()), WriteBarrierType.NONE,
+                        false));
         return metaspaceMethod;
     }
 
     private ReadNode createReadHub(LoweringTool tool, StructuredGraph graph, Kind wordKind, ValueNode object) {
-        LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph);
+        LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind())));
+        ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false));
         tool.createNullCheckGuard(hub, object);
         return hub;
     }
@@ -807,9 +863,17 @@
         return ConstantLocationNode.create(field, field.getKind(), field.offset(), graph);
     }
 
+    public int getScalingFactor(Kind kind) {
+        if (config.useCompressedOops && kind == Kind.Object) {
+            return this.graalRuntime.getTarget().arch.getSizeInBytes(Kind.Int);
+        } else {
+            return this.graalRuntime.getTarget().arch.getSizeInBytes(kind);
+        }
+    }
+
     protected IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) {
-        int scale = this.graalRuntime.getTarget().arch.getSizeInBytes(elementKind);
-        return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
+        int scale = getScalingFactor(elementKind);
+        return IndexedLocationNode.create(NamedLocationIdentity.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
     }
 
     private static GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
@@ -967,12 +1031,16 @@
     }
 
     @Override
-    public boolean hasSideEffect(ForeignCallDescriptor descriptor) {
-        // Only these two foreign calls are expected to be made with
-        // a node that implements StateSplit. They need to be a state
-        // split so that the stack trace they produce is accurate.
-        assert descriptor == CREATE_NULL_POINTER_EXCEPTION || descriptor == CREATE_OUT_OF_BOUNDS_EXCEPTION : descriptor;
-        return false;
+    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
+        return foreignCalls.get(descriptor).isReexecutable();
+    }
+
+    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
+        return foreignCalls.get(descriptor).canDeoptimize();
+    }
+
+    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
+        return foreignCalls.get(descriptor).getKilledLocations();
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
@@ -29,7 +31,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
@@ -55,7 +56,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.word.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,11 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+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.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -46,7 +48,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -49,7 +48,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{LocationIdentity.ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Fri Jun 07 14:15:38 2013 +0200
@@ -43,8 +43,8 @@
 
     public static final ForeignCallDescriptor NEW_MULTI_ARRAY = new ForeignCallDescriptor("new_multi_array", Object.class, Word.class, int.class, Word.class);
 
-    public NewMultiArrayStubCall(ValueNode hub, int rank, ValueNode dims) {
-        super(NEW_MULTI_ARRAY, defaultStamp);
+    public NewMultiArrayStubCall(MetaAccessProvider runtime, ValueNode hub, int rank, ValueNode dims) {
+        super(runtime, NEW_MULTI_ARRAY, defaultStamp);
         this.hub = hub;
         this.rank = rank;
         this.dims = dims;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,107 @@
+/*
+ * 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.hotspot.nodes;
+
+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.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub.
+ */
+@NodeInfo(nameTemplate = "StubForeignCall#{p#descriptor/s}")
+public class StubForeignCallNode extends FixedWithNextNode implements DeoptimizingNode, LIRLowerable, MemoryCheckpoint {
+
+    @Input private final NodeInputList<ValueNode> arguments;
+    private final MetaAccessProvider runtime;
+    @Input private FrameState deoptState;
+
+    private final ForeignCallDescriptor descriptor;
+
+    public StubForeignCallNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, ValueNode... arguments) {
+        super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())));
+        this.arguments = new NodeInputList<>(this, arguments);
+        this.descriptor = descriptor;
+        this.runtime = runtime;
+    }
+
+    public ForeignCallDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    @Override
+    public LocationIdentity[] getLocationIdentities() {
+        return runtime.getKilledLocations(descriptor);
+    }
+
+    protected Value[] operands(LIRGeneratorTool gen) {
+        Value[] operands = new Value[arguments.size()];
+        for (int i = 0; i < operands.length; i++) {
+            operands[i] = gen.operand(arguments.get(i));
+        }
+        return operands;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        assert graph().start() instanceof StubStartNode;
+        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor);
+        Value[] operands = operands(gen);
+        Value result = gen.emitForeignCall(linkage, this, operands);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+    }
+
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name) {
+            return super.toString(verbosity) + "#" + descriptor;
+        }
+        return super.toString(verbosity);
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return false;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return null;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState state) {
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.hotspot.phases;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,8 +27,8 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -66,7 +66,8 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
-        Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Object kObject = UnsafeLoadNode.load(rcvr, 0, kOffset, Kind.Object);
+        Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -273,9 +273,20 @@
             ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]);
             callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType);
         }
+        graph().add(callTarget);
 
-        graph().add(callTarget);
-        InvokeNode invoke = graph().add(new InvokeNode(callTarget, getBci()));
+        // The call target can have a different return type than the invoker,
+        // e.g. the target returns an Object but the invoker void. In this case
+        // we need to use the stamp of the invoker. Note: always using the
+        // invoker's stamp would be wrong because it's a less concrete type
+        // (usually java.lang.Object).
+        InvokeNode invoke;
+        if (callTarget.returnStamp().kind() != stamp().kind()) {
+            invoke = new InvokeNode(callTarget, getBci(), stamp());
+        } else {
+            invoke = new InvokeNode(callTarget, getBci());
+        }
+        graph().add(invoke);
         invoke.setStateAfter(stateAfter());
         return invoke;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.IterableNodeType;
@@ -29,7 +31,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -83,14 +84,14 @@
         // the canonicalization before loop unrolling is needed to propagate the length into
         // additions, etc.
         HighTierContext context = new HighTierContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements());
-        new CanonicalizerPhase().apply(snippetGraph, context);
-        new LoopFullUnrollPhase().apply(snippetGraph, context);
-        new CanonicalizerPhase().apply(snippetGraph, context);
+        new CanonicalizerPhase(true).apply(snippetGraph, context);
+        new LoopFullUnrollPhase(true).apply(snippetGraph, context);
+        new CanonicalizerPhase(true).apply(snippetGraph, context);
     }
 
     @Override
     protected StructuredGraph getSnippetGraph(LoweringTool tool) {
-        if (!GraalOptions.IntrinsifyArrayCopy) {
+        if (!IntrinsifyArrayCopy.getValue()) {
             return null;
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,7 +22,9 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import java.lang.reflect.*;
@@ -313,12 +315,12 @@
         }
     }
 
-    private static final SnippetCounter.Group checkCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
+    private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
     private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess");
     private static final SnippetCounter checkNPECounter = new SnippetCounter(checkCounters, "checkNPE", "checkNPE");
     private static final SnippetCounter checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE");
 
-    private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("System.arraycopy") : null;
+    private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy") : null;
     private static final SnippetCounter byteCounter = new SnippetCounter(counters, "byte[]", "arraycopy for byte[] arrays");
     private static final SnippetCounter charCounter = new SnippetCounter(counters, "char[]", "arraycopy for char[] arrays");
     private static final SnippetCounter shortCounter = new SnippetCounter(counters, "short[]", "arraycopy for short[] arrays");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.lang.invoke.*;
 
 import com.oracle.graal.api.code.*;
@@ -29,14 +31,13 @@
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 
 @ServiceProvider(ReplacementsProvider.class)
 public class CallSiteSubstitutions implements ReplacementsProvider {
 
     @Override
     public void registerReplacements(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
-        if (GraalOptions.IntrinsifyCallSiteTarget) {
+        if (IntrinsifyCallSiteTarget.getValue()) {
             replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class);
             replacements.registerSubstitutions(MutableCallSiteSubstitutions.class);
             replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,10 +27,12 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.meta.*;
@@ -38,7 +40,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
@@ -94,7 +95,7 @@
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
-            if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) {
+            if (objectHub.readWord(superCheckOffset, LocationIdentity.FINAL_LOCATION).notEqual(hub)) {
                 displayMiss.inc();
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
             }
@@ -167,7 +168,7 @@
             StructuredGraph graph = checkcast.graph();
             ValueNode object = checkcast.object();
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type();
-            TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
+            TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), CheckcastMinHintHitProbability.getValue(), CheckcastMaxHints.getValue());
             ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph());
 
             Arguments args;
@@ -187,7 +188,7 @@
                 args = new Arguments(secondary);
                 args.add("hub", hub);
                 args.add("object", object);
-                args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints);
+                args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints);
             }
             args.addConst("checkNull", !object.stamp().nonNull());
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -62,7 +62,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, 0, embeddedCipherOffset, Kind.Object);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true);
         } else {
@@ -72,7 +72,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, 0, embeddedCipherOffset, Kind.Object);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false);
         } else {
@@ -81,8 +81,10 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
-        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Object kObject = UnsafeLoadNode.load(embeddedCipher, 0, AESCryptSubstitutions.kOffset, Kind.Object);
+        Object rObject = UnsafeLoadNode.load(rcvr, 0, rOffset, Kind.Object);
+        Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
+        Word rAddr = (Word) Word.fromObject(rObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,6 +27,7 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.word.*;
@@ -44,7 +45,7 @@
             // Class for primitive type
             return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
         } else {
-            return klass.readInt(klassModifierFlagsOffset(), FINAL_LOCATION);
+            return klass.readInt(klassModifierFlagsOffset(), LocationIdentity.FINAL_LOCATION);
         }
     }
 
@@ -54,7 +55,7 @@
         if (klass.equal(0)) {
             return false;
         } else {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION);
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), LocationIdentity.FINAL_LOCATION);
             return (accessFlags & Modifier.INTERFACE) != 0;
         }
     }
@@ -79,16 +80,16 @@
     public static Class<?> getSuperclass(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION);
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), LocationIdentity.FINAL_LOCATION);
             if ((accessFlags & Modifier.INTERFACE) == 0) {
                 if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
                     return Object.class;
                 } else {
-                    Word superKlass = klass.readWord(klassSuperKlassOffset(), FINAL_LOCATION);
+                    Word superKlass = klass.readWord(klassSuperKlassOffset(), LocationIdentity.FINAL_LOCATION);
                     if (superKlass.equal(0)) {
                         return null;
                     } else {
-                        return unsafeCast(superKlass.readObject(classMirrorOffset(), FINAL_LOCATION), Class.class, true, true);
+                        return unsafeCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
                     }
                 }
             }
@@ -101,7 +102,7 @@
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
             if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
-                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), FINAL_LOCATION), Class.class, true, true);
+                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
             }
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNmethodIntrinsics.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNmethodIntrinsics.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,18 +22,19 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 
 @ServiceProvider(ReplacementsProvider.class)
 public class HotSpotNmethodIntrinsics implements ReplacementsProvider {
 
     @Override
     public void registerReplacements(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
-        if (GraalOptions.IntrinsifyInstalledCodeMethods) {
+        if (IntrinsifyInstalledCodeMethods.getValue()) {
             replacements.registerSubstitutions(HotSpotNmethodSubstitutions.class);
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri Jun 07 14:15:38 2013 +0200
@@ -34,7 +34,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
@@ -46,9 +45,6 @@
  */
 public class HotSpotReplacementsUtil {
 
-    public static final LocationIdentity ANY_LOCATION = LocationNode.ANY_LOCATION;
-    public static final LocationIdentity FINAL_LOCATION = LocationNode.FINAL_LOCATION;
-
     public static HotSpotVMConfig config() {
         return graalRuntime().getConfig();
     }
@@ -63,7 +59,7 @@
         return config().verifyOops;
     }
 
-    public static final LocationIdentity EXCEPTION_OOP_LOCATION = LocationNode.createLocation("ExceptionOop");
+    public static final LocationIdentity EXCEPTION_OOP_LOCATION = new NamedLocationIdentity("ExceptionOop");
 
     /**
      * @see HotSpotVMConfig#threadExceptionOopOffset
@@ -73,35 +69,35 @@
         return config().threadExceptionOopOffset;
     }
 
-    public static final LocationIdentity EXCEPTION_PC_LOCATION = LocationNode.createLocation("ExceptionPc");
+    public static final LocationIdentity EXCEPTION_PC_LOCATION = new NamedLocationIdentity("ExceptionPc");
 
     @Fold
     public static int threadExceptionPcOffset() {
         return config().threadExceptionPcOffset;
     }
 
-    public static final LocationIdentity TLAB_TOP_LOCATION = LocationNode.createLocation("TlabTop");
+    public static final LocationIdentity TLAB_TOP_LOCATION = new NamedLocationIdentity("TlabTop");
 
     @Fold
     public static int threadTlabTopOffset() {
         return config().threadTlabTopOffset;
     }
 
-    public static final LocationIdentity TLAB_END_LOCATION = LocationNode.createLocation("TlabEnd");
+    public static final LocationIdentity TLAB_END_LOCATION = new NamedLocationIdentity("TlabEnd");
 
     @Fold
     private static int threadTlabEndOffset() {
         return config().threadTlabEndOffset;
     }
 
-    public static final LocationIdentity TLAB_START_LOCATION = LocationNode.createLocation("TlabStart");
+    public static final LocationIdentity TLAB_START_LOCATION = new NamedLocationIdentity("TlabStart");
 
     @Fold
     private static int threadTlabStartOffset() {
         return config().threadTlabStartOffset;
     }
 
-    public static final LocationIdentity PENDING_EXCEPTION_LOCATION = LocationNode.createLocation("PendingException");
+    public static final LocationIdentity PENDING_EXCEPTION_LOCATION = new NamedLocationIdentity("PendingException");
 
     /**
      * @see HotSpotVMConfig#pendingExceptionOffset
@@ -111,7 +107,7 @@
         return config().pendingExceptionOffset;
     }
 
-    public static final LocationIdentity OBJECT_RESULT_LOCATION = LocationNode.createLocation("ObjectResult");
+    public static final LocationIdentity OBJECT_RESULT_LOCATION = new NamedLocationIdentity("ObjectResult");
 
     @Fold
     private static int objectResultOffset() {
@@ -200,7 +196,7 @@
     }
 
     @Fold
-    public static Kind wordKind() {
+    public static Kind getWordKind() {
         return graalRuntime().getTarget().wordKind;
     }
 
@@ -224,7 +220,7 @@
         return Unsafe.getUnsafe().pageSize();
     }
 
-    public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = LocationNode.createLocation("PrototypeMarkWord");
+    public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = new NamedLocationIdentity("PrototypeMarkWord");
 
     @Fold
     public static int prototypeMarkWordOffset() {
@@ -247,7 +243,7 @@
     }
 
     public static int readLayoutHelper(Word hub) {
-        return hub.readInt(klassLayoutHelperOffset(), FINAL_LOCATION);
+        return hub.readInt(klassLayoutHelperOffset(), LocationIdentity.FINAL_LOCATION);
     }
 
     @Fold
@@ -265,14 +261,14 @@
         return config().klassSuperKlassOffset;
     }
 
-    public static final LocationIdentity MARK_WORD_LOCATION = LocationNode.createLocation("MarkWord");
+    public static final LocationIdentity MARK_WORD_LOCATION = new NamedLocationIdentity("MarkWord");
 
     @Fold
     public static int markOffset() {
         return config().markOffset;
     }
 
-    public static final LocationIdentity HUB_LOCATION = LocationNode.createLocation("Hub");
+    public static final LocationIdentity HUB_LOCATION = new NamedLocationIdentity("Hub");
 
     @Fold
     private static int hubOffset() {
@@ -399,21 +395,21 @@
         return config().superCheckOffsetOffset;
     }
 
-    public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = LocationNode.createLocation("SecondarySuperCache");
+    public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = new NamedLocationIdentity("SecondarySuperCache");
 
     @Fold
     public static int secondarySuperCacheOffset() {
         return config().secondarySuperCacheOffset;
     }
 
-    public static final LocationIdentity SECONDARY_SUPERS_LOCATION = LocationNode.createLocation("SecondarySupers");
+    public static final LocationIdentity SECONDARY_SUPERS_LOCATION = new NamedLocationIdentity("SecondarySupers");
 
     @Fold
     public static int secondarySupersOffset() {
         return config().secondarySupersOffset;
     }
 
-    public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = LocationNode.createLocation("DisplacedMarkWord");
+    public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = new NamedLocationIdentity("DisplacedMarkWord");
 
     @Fold
     public static int lockDisplacedMarkOffset() {
@@ -444,7 +440,14 @@
      * Loads the hub from a object, null checking it first.
      */
     public static Word loadHub(Object object) {
-        return loadHubIntrinsic(object, wordKind());
+        return loadHubIntrinsic(object, getWordKind());
+    }
+
+    /**
+     * Loads the hub from a object.
+     */
+    public static Word loadHubNoNullcheck(Object object) {
+        return loadWordFromObject(object, hubOffset());
     }
 
     public static Object verifyOop(Object object) {
@@ -472,7 +475,7 @@
     }
 
     public static Word loadWordFromObject(Object object, int offset) {
-        return loadWordFromObjectIntrinsic(object, 0, offset, wordKind());
+        return loadWordFromObjectIntrinsic(object, 0, offset, getWordKind());
     }
 
     @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
@@ -495,7 +498,7 @@
         return CodeUtil.log2(wordSize());
     }
 
-    public static final LocationIdentity CLASS_STATE_LOCATION = LocationNode.createLocation("ClassState");
+    public static final LocationIdentity CLASS_STATE_LOCATION = new NamedLocationIdentity("ClassState");
 
     @Fold
     public static int klassStateOffset() {
@@ -527,14 +530,14 @@
         return config().klassInstanceSizeOffset;
     }
 
-    public static final LocationIdentity HEAP_TOP_LOCATION = LocationNode.createLocation("HeapTop");
+    public static final LocationIdentity HEAP_TOP_LOCATION = new NamedLocationIdentity("HeapTop");
 
     @Fold
     public static long heapTopAddress() {
         return config().heapTopAddress;
     }
 
-    public static final LocationIdentity HEAP_END_LOCATION = LocationNode.createLocation("HeapEnd");
+    public static final LocationIdentity HEAP_END_LOCATION = new NamedLocationIdentity("HeapEnd");
 
     @Fold
     public static long heapEndAddress() {
@@ -556,42 +559,42 @@
         return config().tlabAlignmentReserve;
     }
 
-    public static final LocationIdentity TLAB_SIZE_LOCATION = LocationNode.createLocation("TlabSize");
+    public static final LocationIdentity TLAB_SIZE_LOCATION = new NamedLocationIdentity("TlabSize");
 
     @Fold
     public static int threadTlabSizeOffset() {
         return config().threadTlabSizeOffset;
     }
 
-    public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = LocationNode.createLocation("TlabThreadAllocatedBytes");
+    public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = new NamedLocationIdentity("TlabThreadAllocatedBytes");
 
     @Fold
     public static int threadAllocatedBytesOffset() {
         return config().threadAllocatedBytesOffset;
     }
 
-    public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = LocationNode.createLocation("RefillWasteLimit");
+    public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = new NamedLocationIdentity("RefillWasteLimit");
 
     @Fold
     public static int tlabRefillWasteLimitOffset() {
         return config().tlabRefillWasteLimitOffset;
     }
 
-    public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = LocationNode.createLocation("TlabNOfRefills");
+    public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = new NamedLocationIdentity("TlabNOfRefills");
 
     @Fold
     public static int tlabNumberOfRefillsOffset() {
         return config().tlabNumberOfRefillsOffset;
     }
 
-    public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = LocationNode.createLocation("TlabFastRefillWaste");
+    public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = new NamedLocationIdentity("TlabFastRefillWaste");
 
     @Fold
     public static int tlabFastRefillWasteOffset() {
         return config().tlabFastRefillWasteOffset;
     }
 
-    public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = LocationNode.createLocation("TlabSlowAllocations");
+    public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = new NamedLocationIdentity("TlabSlowAllocations");
 
     @Fold
     public static int tlabSlowAllocationsOffset() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Jun 07 14:15:38 2013 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
@@ -34,7 +35,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
@@ -81,7 +81,7 @@
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub))) {
+        if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, LocationIdentity.FINAL_LOCATION).notEqual(hub))) {
             displayMiss.inc();
             return falseValue;
         }
@@ -150,7 +150,7 @@
             if (replacer.instanceOf instanceof InstanceOfNode) {
                 InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf;
                 ValueNode object = instanceOf.object();
-                TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
+                TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), InstanceOfMinHintHitProbability.getValue(), InstanceOfMaxHints.getValue());
                 final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
                 ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph());
 
@@ -171,7 +171,7 @@
                     args = new Arguments(instanceofSecondary);
                     args.add("hub", hub);
                     args.add("object", object);
-                    args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs);
+                    args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints.hubs);
                     args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive);
                 }
                 args.add("trueValue", replacer.trueValue);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,11 +22,15 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.hotspot.meta.HotSpotRuntime.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -34,6 +38,7 @@
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -41,6 +46,11 @@
  */
 public class LoadExceptionObjectSnippets implements Snippets {
 
+    /**
+     * Alternative way to implement exception object loading.
+     */
+    private static final boolean USE_C_RUNTIME = Boolean.getBoolean("graal.loadExceptionObject.useCRuntime");
+
     @Snippet
     public static Object loadException() {
         Word thread = thread();
@@ -59,8 +69,18 @@
         }
 
         public void lower(LoadExceptionObjectNode loadExceptionObject) {
-            Arguments args = new Arguments(loadException);
-            template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args);
+            if (USE_C_RUNTIME) {
+                StructuredGraph graph = loadExceptionObject.graph();
+                HotSpotRuntime hsRuntime = (HotSpotRuntime) runtime;
+                ReadRegisterNode thread = graph.add(new ReadRegisterNode(hsRuntime.threadRegister(), true, false));
+                graph.addBeforeFixed(loadExceptionObject, thread);
+                ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(runtime, LOAD_AND_CLEAR_EXCEPTION, thread));
+                loadExceptionC.setStateAfter(loadExceptionObject.stateAfter());
+                graph.replaceFixedWithFixed(loadExceptionObject, loadExceptionC);
+            } else {
+                Arguments args = new Arguments(loadException);
+                template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args);
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Jun 07 14:15:38 2013 +0200
@@ -41,7 +41,6 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -108,7 +107,7 @@
             } else {
                 // The bias pattern is present in the object's mark word. Need to check
                 // whether the bias owner and the epoch are both still current.
-                Word hub = loadHub(object);
+                Word hub = loadHubNoNullcheck(object);
                 final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
                 final Word thread = thread();
                 final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace());
@@ -345,7 +344,7 @@
      */
     private static final boolean ENABLE_BREAKPOINT = false;
 
-    private static final LocationIdentity MONITOR_COUNTER_LOCATION = LocationNode.createLocation("MonitorCounter");
+    private static final LocationIdentity MONITOR_COUNTER_LOCATION = new NamedLocationIdentity("MonitorCounter");
 
     @NodeIntrinsic(BreakpointNode.class)
     static native void bkpt(Object object, Word mark, Word tmp, Word value);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,9 +23,11 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.api.code.UnsignedMath.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*;
@@ -39,7 +41,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
@@ -237,7 +238,7 @@
             Kind elementKind = elementType.getKind();
             ConstantNode hub = ConstantNode.forConstant(arrayType.klass(), runtime, graph);
             final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind);
-            int log2ElementSize = CodeUtil.log2(target.arch.getSizeInBytes(elementKind));
+            int log2ElementSize = CodeUtil.log2(((HotSpotRuntime) runtime).getScalingFactor(elementKind));
 
             Arguments args = new Arguments(allocateArray);
             args.add("hub", hub);
@@ -277,12 +278,12 @@
         }
     }
 
-    private static final SnippetCounter.Group countersNew = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewInstance") : null;
+    private static final SnippetCounter.Group countersNew = SnippetCounters.getValue() ? new SnippetCounter.Group("NewInstance") : null;
     private static final SnippetCounter new_seqInit = new SnippetCounter(countersNew, "tlabSeqInit", "TLAB alloc with unrolled zeroing");
     private static final SnippetCounter new_loopInit = new SnippetCounter(countersNew, "tlabLoopInit", "TLAB alloc with zeroing in a loop");
     private static final SnippetCounter new_stub = new SnippetCounter(countersNew, "stub", "alloc and zeroing via stub");
 
-    private static final SnippetCounter.Group countersNewArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewArray") : null;
+    private static final SnippetCounter.Group countersNewArray = SnippetCounters.getValue() ? new SnippetCounter.Group("NewArray") : null;
     private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop");
     private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewArray, "stub", "alloc and zeroing via stub");
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
@@ -31,7 +33,6 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class ObjectCloneNode extends MacroNode implements VirtualizableAllocation, ArrayLengthProvider {
@@ -51,7 +52,7 @@
 
     @Override
     protected StructuredGraph getSnippetGraph(LoweringTool tool) {
-        if (!GraalOptions.IntrinsifyObjectClone) {
+        if (!IntrinsifyObjectClone.getValue()) {
             return null;
         }
 
@@ -77,7 +78,7 @@
     }
 
     private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) {
-        return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type);
+        return type != null && metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type);
     }
 
     private static ResolvedJavaType getConcreteType(ObjectStamp stamp, Assumptions assumptions) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,7 +22,9 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import java.lang.reflect.*;
@@ -32,7 +34,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
 
@@ -116,12 +117,12 @@
         }
     }
 
-    private static final SnippetCounter.Group cloneCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Object.clone") : null;
+    private static final SnippetCounter.Group cloneCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("Object.clone") : null;
     private static final SnippetCounter instanceCloneCounter = new SnippetCounter(cloneCounters, "instanceClone", "clone snippet for instances");
     private static final SnippetCounter arrayCloneCounter = new SnippetCounter(cloneCounters, "arrayClone", "clone snippet for arrays");
     private static final SnippetCounter genericCloneCounter = new SnippetCounter(cloneCounters, "genericClone", "clone snippet for arrays and instances");
 
-    private static final SnippetCounter.Group genericCloneCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Object.clone generic snippet") : null;
+    private static final SnippetCounter.Group genericCloneCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("Object.clone generic snippet") : null;
     private static final SnippetCounter genericInstanceCloneCounter = new SnippetCounter(genericCloneCounters, "genericInstanceClone", "generic clone implementation took instance path");
     private static final SnippetCounter genericArrayCloneCounter = new SnippetCounter(genericCloneCounters, "genericArrayClone", "generic clone implementation took array path");
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,8 +25,8 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -40,7 +40,7 @@
     @MethodSubstitution(isStatic = false)
     public static Class<?> getClass(final Object thisObj) {
         Word hub = loadHub(thisObj);
-        return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationNode.FINAL_LOCATION), Class.class, true, true);
+        return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class ReflectionGetCallerClassNode extends MacroNode implements Canonicalizable, Lowerable {
@@ -64,7 +65,7 @@
      * @return ConstantNode of the caller class, or null
      */
     private ConstantNode getCallerClassNode(MetaAccessProvider runtime) {
-        if (!GraalOptions.IntrinsifyReflectionMethods) {
+        if (!IntrinsifyReflectionMethods.getValue()) {
             return null;
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
 import java.lang.reflect.*;
@@ -43,15 +44,15 @@
 
     @MethodSubstitution
     public static Thread currentThread() {
-        return (Thread) CurrentJavaThreadNode.get().readObject(threadObjectOffset(), FINAL_LOCATION);
+        return (Thread) CurrentJavaThreadNode.get().readObject(threadObjectOffset(), LocationIdentity.FINAL_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
     public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
         Word javaThread = CurrentJavaThreadNode.get();
-        Object thread = javaThread.readObject(threadObjectOffset(), FINAL_LOCATION);
+        Object thread = javaThread.readObject(threadObjectOffset(), LocationIdentity.FINAL_LOCATION);
         if (thisObject == thread) {
-            Word osThread = javaThread.readWord(osThreadOffset(), FINAL_LOCATION);
+            Word osThread = javaThread.readWord(osThreadOffset(), LocationIdentity.FINAL_LOCATION);
             boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), ANY_LOCATION) != 0;
             if (!interrupted || !clearInterrupted) {
                 return interrupted;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import java.util.*;
@@ -32,9 +33,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
 
@@ -45,7 +43,7 @@
  */
 public class TypeCheckSnippetUtils {
 
-    public static final LocationIdentity TYPE_DISPLAY_LOCATION = LocationNode.createLocation("TypeDisplay");
+    public static final LocationIdentity TYPE_DISPLAY_LOCATION = new NamedLocationIdentity("TypeDisplay");
 
     static boolean checkSecondarySubType(Word t, Word s) {
         // if (S.cache == T) return true
@@ -59,7 +57,7 @@
 
     static boolean checkUnknownSubType(Word t, Word s) {
         // int off = T.offset
-        int superCheckOffset = t.readInt(superCheckOffsetOffset(), FINAL_LOCATION);
+        int superCheckOffset = t.readInt(superCheckOffsetOffset(), LocationIdentity.FINAL_LOCATION);
         boolean primary = superCheckOffset != secondarySuperCacheOffset();
 
         // if (T = S[off]) return true
@@ -90,7 +88,7 @@
 
         // if (S.scan_s_s_array(T)) { S.cache = T; return true; }
         Word secondarySupers = s.readWord(secondarySupersOffset(), SECONDARY_SUPERS_LOCATION);
-        int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), FINAL_LOCATION);
+        int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), LocationIdentity.FINAL_LOCATION);
         for (int i = 0; i < length; i++) {
             if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) {
                 s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION);
@@ -144,10 +142,10 @@
     }
 
     static Word loadSecondarySupersElement(Word metaspaceArray, int index) {
-        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), FINAL_LOCATION);
+        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), LocationIdentity.FINAL_LOCATION);
     }
 
-    private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("TypeCheck") : null;
+    private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("TypeCheck") : null;
     static final SnippetCounter hintsHit = new SnippetCounter(counters, "hintsHit", "hit a hint type");
     static final SnippetCounter exactHit = new SnippetCounter(counters, "exactHit", "exact type test succeeded");
     static final SnippetCounter exactMiss = new SnippetCounter(counters, "exactMiss", "exact type test failed");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java	Fri Jun 07 14:15:38 2013 +0200
@@ -34,7 +34,7 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -127,6 +127,6 @@
 
     public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = descriptorFor(ExceptionHandlerStub.class, "exceptionHandlerForPc");
 
-    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
+    @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
     public static native Word exceptionHandlerForPc(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForPc, Word thread);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Fri Jun 07 14:15:38 2013 +0200
@@ -24,9 +24,9 @@
 
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.meta.MetaUtil.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.reflect.*;
 
@@ -40,7 +40,6 @@
 import com.oracle.graal.hotspot.replacements.*;
 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.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -80,13 +79,18 @@
      * @param descriptor the signature of the call to this stub
      * @param prependThread true if the JavaThread value for the current thread is to be prepended
      *            to the arguments for the call to {@code address}
+     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a stub call that cannot
+     *            be re-executed.
+     * @param killedLocations the memory locations killed by the stub call
      */
-    public ForeignCallStub(long address, ForeignCallDescriptor descriptor, boolean prependThread, HotSpotRuntime runtime, Replacements replacements) {
-        super(runtime, replacements, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF));
+    public ForeignCallStub(HotSpotRuntime runtime, Replacements replacements, long address, ForeignCallDescriptor descriptor, boolean prependThread, boolean reexecutable,
+                    LocationIdentity... killedLocations) {
+        super(runtime, replacements, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations));
         this.prependThread = prependThread;
         Class[] targetParameterTypes = createTargetParameters(descriptor);
         ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes);
-        target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NOT_LEAF);
+        target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NOT_LEAF, reexecutable, killedLocations);
     }
 
     /**
@@ -255,7 +259,7 @@
             if (kind == Kind.Object) {
                 stamp = StampFactory.declared(type);
             } else {
-                stamp = StampFactory.forKind(kind);
+                stamp = StampFactory.forKind(type.getKind());
             }
             LocalNode local = builder.add(new LocalNode(i, stamp));
             locals[i] = local;
@@ -278,14 +282,14 @@
         return invoke;
     }
 
-    private ForeignCallNode createTargetCall(GraphBuilder builder, LocalNode[] locals, ReadRegisterNode thread) {
+    private StubForeignCallNode createTargetCall(GraphBuilder builder, LocalNode[] locals, ReadRegisterNode thread) {
         if (prependThread) {
             ValueNode[] targetArguments = new ValueNode[1 + locals.length];
             targetArguments[0] = thread;
             System.arraycopy(locals, 0, targetArguments, 1, locals.length);
-            return builder.append(new ForeignCallNode(target.getDescriptor(), targetArguments));
+            return builder.append(new StubForeignCallNode(runtime, target.getDescriptor(), targetArguments));
         } else {
-            return builder.append(new ForeignCallNode(target.getDescriptor(), locals));
+            return builder.append(new StubForeignCallNode(runtime, target.getDescriptor(), locals));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Jun 07 14:15:38 2013 +0200
@@ -36,7 +36,6 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -89,7 +88,7 @@
      */
     @Snippet
     private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub) {
-        int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
+        int layoutHelper = hub.readInt(layoutHelperOffset(), LocationIdentity.FINAL_LOCATION);
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
         int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask();
@@ -122,6 +121,6 @@
 
     public static final ForeignCallDescriptor NEW_ARRAY_C = descriptorFor(NewArrayStub.class, "newArrayC");
 
-    @NodeIntrinsic(ForeignCallNode.class)
+    @NodeIntrinsic(StubForeignCallNode.class)
     public static native void newArrayC(@ConstantNodeParameter ForeignCallDescriptor newArrayC, Word thread, Word hub, int length);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
@@ -36,7 +37,6 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -87,7 +87,7 @@
      */
     @Snippet
     private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub) {
-        int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION);
+        int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), LocationIdentity.FINAL_LOCATION);
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
             if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) {
                 Word memory = refillAllocate(intArrayHub, sizeInBytes, logging());
@@ -241,6 +241,6 @@
 
     public static final ForeignCallDescriptor NEW_INSTANCE_C = descriptorFor(NewInstanceStub.class, "newInstanceC");
 
-    @NodeIntrinsic(ForeignCallNode.class)
+    @NodeIntrinsic(StubForeignCallNode.class)
     public static native void newInstanceC(@ConstantNodeParameter ForeignCallDescriptor newInstanceC, Word thread, Word hub);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Jun 07 14:15:38 2013 +0200
@@ -173,8 +173,9 @@
                             if (Debug.isDumpEnabled()) {
                                 Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                             }
-                            // TTY.println(stub.toString());
-                            // TTY.println(runtime.disassemble(installedCode));
+                            if (Debug.isLogEnabled()) {
+                                Debug.log("%s", runtime.disassemble(installedCode));
+                            }
                             return installedCode;
                         }
                     });
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Fri Jun 07 14:15:38 2013 +0200
@@ -35,7 +35,6 @@
 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.replacements.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.word.*;
@@ -50,15 +49,15 @@
     public static final ForeignCallDescriptor VM_MESSAGE_C = descriptorFor(StubUtil.class, "vmMessageC");
 
     /**
-     * Looks for a {@link ForeignCallNode} node intrinsic named {@code name} in {@code stubClass}
-     * and returns a {@link ForeignCallDescriptor} based on its signature and the value of
-     * {@code hasSideEffect}.
+     * Looks for a {@link StubForeignCallNode} node intrinsic named {@code name} in
+     * {@code stubClass} and returns a {@link ForeignCallDescriptor} based on its signature and the
+     * value of {@code hasSideEffect}.
      */
     public static ForeignCallDescriptor descriptorFor(Class<?> stubClass, String name) {
         Method found = null;
         for (Method method : stubClass.getDeclaredMethods()) {
             if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) {
-                if (method.getAnnotation(NodeIntrinsic.class).value() == ForeignCallNode.class) {
+                if (method.getAnnotation(NodeIntrinsic.class).value() == StubForeignCallNode.class) {
                     assert found == null : "found more than one foreign call named " + name + " in " + stubClass;
                     assert method.getParameterTypes().length != 0 && method.getParameterTypes()[0] == ForeignCallDescriptor.class : "first parameter of foreign call '" + name + "' in " + stubClass +
                                     " must be of type " + ForeignCallDescriptor.class.getSimpleName();
@@ -81,7 +80,7 @@
         }
     }
 
-    @NodeIntrinsic(ForeignCallNode.class)
+    @NodeIntrinsic(StubForeignCallNode.class)
     private static native void vmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java	Fri Jun 07 14:15:38 2013 +0200
@@ -34,8 +34,8 @@
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -99,6 +99,6 @@
 
     public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = descriptorFor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress");
 
-    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
+    @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
     public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress);
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.bytecode.Bytecodes.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -31,7 +32,6 @@
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 
 /**
  * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph
@@ -187,7 +187,7 @@
         makeExceptionEntries();
         iterateOverBytecodes();
         if (hasJsrBytecodes) {
-            if (!GraalOptions.SupportJsrBytecodes) {
+            if (!SupportJsrBytecodes.getValue()) {
                 throw new JsrNotSupportedBailout("jsr/ret parsing disabled");
             }
             createJsrAlternatives(blockMap[0]);
@@ -209,7 +209,7 @@
         if (Debug.isLogEnabled()) {
             this.log("Before LivenessAnalysis");
         }
-        if (GraalOptions.OptLivenessAnalysis) {
+        if (OptLivenessAnalysis.getValue()) {
             Debug.scope("LivenessAnalysis", new Runnable() {
 
                 @Override
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Fri Jun 07 14:15:38 2013 +0200
@@ -49,6 +49,10 @@
     private ValueNode[] locks;
 
     private int stackSize;
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     private boolean rethrowException;
 
     public FrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) {
@@ -82,7 +86,7 @@
             if (kind == Kind.Object && type instanceof ResolvedJavaType) {
                 stamp = StampFactory.declared((ResolvedJavaType) type);
             } else {
-                stamp = StampFactory.forKind(kind);
+                stamp = StampFactory.forKind(type.getKind());
             }
             LocalNode local = graph.unique(new LocalNode(index, stamp));
             storeLocal(javaIndex, local);
@@ -144,7 +148,7 @@
         for (int i = 0; i < stackSize(); i++) {
             ValueNode x = stackAt(i);
             ValueNode y = other.stackAt(i);
-            if (x != y && ValueNodeUtil.typeMismatch(x, y)) {
+            if (x != y && (x == null || x.isDeleted() || y == null || y.isDeleted() || x.kind() != y.kind())) {
                 return false;
             }
         }
@@ -171,11 +175,11 @@
     }
 
     private ValueNode merge(ValueNode currentValue, ValueNode otherValue, MergeNode block) {
-        if (currentValue == null) {
+        if (currentValue == null || currentValue.isDeleted()) {
             return null;
 
         } else if (block.isPhiAtMerge(currentValue)) {
-            if (otherValue == null || currentValue.kind() != otherValue.kind()) {
+            if (otherValue == null || otherValue.isDeleted() || currentValue.kind() != otherValue.kind()) {
                 propagateDelete((PhiNode) currentValue);
                 return null;
             }
@@ -184,7 +188,7 @@
 
         } else if (currentValue != otherValue) {
             assert !(block instanceof LoopBeginNode) : "Phi functions for loop headers are create eagerly for all locals and stack slots";
-            if (otherValue == null || currentValue.kind() != otherValue.kind()) {
+            if (otherValue == null || otherValue.isDeleted() || currentValue.kind() != otherValue.kind()) {
                 return null;
             }
 
@@ -308,10 +312,16 @@
         }
     }
 
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     public boolean rethrowException() {
         return rethrowException;
     }
 
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     public void setRethrowException(boolean b) {
         rethrowException = b;
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,6 +27,7 @@
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static java.lang.reflect.Modifier.*;
 
 import java.lang.reflect.*;
@@ -158,7 +159,7 @@
         methodSynchronizedObject = null;
         this.currentGraph = graph;
         this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
-        TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
+        TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
         try {
             build();
         } finally {
@@ -182,7 +183,7 @@
     }
 
     private void build() {
-        if (GraalOptions.PrintProfilingInformation) {
+        if (PrintProfilingInformation.getValue()) {
             TTY.println("Profiling info for " + method);
             TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), "  "));
         }
@@ -921,11 +922,11 @@
         append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.1));
         lastInstr = falseSucc;
 
-        if (GraalOptions.OmitHotExceptionStacktrace) {
+        if (OmitHotExceptionStacktrace.getValue()) {
             ValueNode exception = ConstantNode.forObject(cachedNullPointerException, runtime, currentGraph);
             trueSucc.setNext(handleException(exception, bci()));
         } else {
-            ForeignCallStateSplitNode call = currentGraph.add(new ForeignCallStateSplitNode(runtime, CREATE_NULL_POINTER_EXCEPTION));
+            ForeignCallNode call = currentGraph.add(new ForeignCallNode(runtime, CREATE_NULL_POINTER_EXCEPTION));
             call.setStateAfter(frameState.create(bci()));
             trueSucc.setNext(call);
             call.setNext(handleException(call, bci()));
@@ -945,11 +946,11 @@
         append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.9));
         lastInstr = trueSucc;
 
-        if (GraalOptions.OmitHotExceptionStacktrace) {
+        if (OmitHotExceptionStacktrace.getValue()) {
             ValueNode exception = ConstantNode.forObject(cachedArrayIndexOutOfBoundsException, runtime, currentGraph);
             falseSucc.setNext(handleException(exception, bci()));
         } else {
-            ForeignCallStateSplitNode call = currentGraph.add(new ForeignCallStateSplitNode(runtime, CREATE_OUT_OF_BOUNDS_EXCEPTION, index));
+            ForeignCallNode call = currentGraph.add(new ForeignCallNode(runtime, CREATE_OUT_OF_BOUNDS_EXCEPTION, index));
             call.setStateAfter(frameState.create(bci()));
             falseSucc.setNext(call);
             call.setNext(handleException(call, bci()));
@@ -1023,7 +1024,7 @@
         if (target instanceof ResolvedJavaMethod) {
             ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
             ResolvedJavaType holder = resolvedTarget.getDeclaringClass();
-            if (!holder.isInitialized() && GraalOptions.ResolveClassBeforeStaticInvoke) {
+            if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue()) {
                 handleUnresolvedInvoke(target, InvokeKind.Static);
             } else {
                 ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false));
@@ -1107,8 +1108,11 @@
         }
         if (exact != null) {
             // either the holder class is exact, or the receiver object has an exact type
-            invokeDirect(exact.resolveMethod(target), args);
-            return;
+            ResolvedJavaMethod exactMethod = exact.resolveMethod(target);
+            if (exactMethod != null) {
+                invokeDirect(exactMethod, args);
+                return;
+            }
         }
         // devirtualization failed, produce an actual invokevirtual
         appendInvoke(invokeKind, target, args);
@@ -1120,7 +1124,7 @@
 
     private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) {
         Kind resultType = targetMethod.getSignature().getReturnKind();
-        if (GraalOptions.DeoptALot) {
+        if (DeoptALot.getValue()) {
             append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph));
             return;
@@ -1763,7 +1767,7 @@
     }
 
     private void traceState() {
-        if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && Debug.isLogEnabled()) {
+        if (TraceBytecodeParserLevel.getValue() >= TRACELEVEL_STATE && Debug.isLogEnabled()) {
             Debug.log(String.format("|   state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method));
             for (int i = 0; i < frameState.localsSize(); ++i) {
                 ValueNode value = frameState.localAt(i);
@@ -1993,7 +1997,7 @@
     }
 
     private void traceInstruction(int bci, int opcode, boolean blockStart) {
-        if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) {
+        if (TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) {
             StringBuilder sb = new StringBuilder(40);
             sb.append(blockStart ? '+' : '|');
             if (bci < 10) {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Fri Jun 07 14:15:38 2013 +0200
@@ -273,7 +273,7 @@
         protected void verify() {
             super.verify();
             // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx
-            assert asRegister(x) == AMD64.rax;
+            assert asRegister(x).equals(AMD64.rax);
             assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue());
             verifyKind(opcode, divResult, x, y);
             verifyKind(opcode, remResult, x, y);
@@ -360,9 +360,9 @@
                 case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break;
                 case IOR:  masm.orl(asIntReg(dst),   asIntReg(src)); break;
                 case IXOR: masm.xorl(asIntReg(dst),  asIntReg(src)); break;
-                case ISHL: assert asIntReg(src) == AMD64.rcx; masm.shll(asIntReg(dst)); break;
-                case ISHR: assert asIntReg(src) == AMD64.rcx; masm.sarl(asIntReg(dst)); break;
-                case IUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrl(asIntReg(dst)); break;
+                case ISHL: assert asIntReg(src).equals(AMD64.rcx); masm.shll(asIntReg(dst)); break;
+                case ISHR: assert asIntReg(src).equals(AMD64.rcx); masm.sarl(asIntReg(dst)); break;
+                case IUSHR: assert asIntReg(src).equals(AMD64.rcx); masm.shrl(asIntReg(dst)); break;
 
                 case LADD: masm.addq(asLongReg(dst),  asLongReg(src)); break;
                 case LSUB: masm.subq(asLongReg(dst),  asLongReg(src)); break;
@@ -370,9 +370,9 @@
                 case LAND: masm.andq(asLongReg(dst),  asLongReg(src)); break;
                 case LOR:  masm.orq(asLongReg(dst),   asLongReg(src)); break;
                 case LXOR: masm.xorq(asLongReg(dst),  asLongReg(src)); break;
-                case LSHL: assert asIntReg(src) == AMD64.rcx; masm.shlq(asLongReg(dst)); break;
-                case LSHR: assert asIntReg(src) == AMD64.rcx; masm.sarq(asLongReg(dst)); break;
-                case LUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrq(asLongReg(dst)); break;
+                case LSHL: assert asIntReg(src).equals(AMD64.rcx); masm.shlq(asLongReg(dst)); break;
+                case LSHR: assert asIntReg(src).equals(AMD64.rcx); masm.sarq(asLongReg(dst)); break;
+                case LUSHR: assert asIntReg(src).equals(AMD64.rcx); masm.shrq(asLongReg(dst)); break;
 
                 case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break;
                 case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break;
@@ -556,6 +556,6 @@
             || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
             || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
             || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)
-            || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y) == AMD64.rcx));
+            || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y).equals(AMD64.rcx)));
     }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 public class AMD64BitManipulationOp extends AMD64LIRInstruction {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BreakpointOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BreakpointOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 @Opcode("BSWAP")
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Fri Jun 07 14:15:38 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.spi.*;
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Fri Jun 07 14:15:38 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 // @formatter:off
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri Jun 07 14:15:38 2013 +0200
@@ -35,7 +35,6 @@
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.StandardOp.FallThroughOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.*;
@@ -404,7 +403,7 @@
 
     private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, ConditionFlag cond, Value other) {
         if (isRegister(other)) {
-            assert asRegister(other) != asRegister(result) : "other already overwritten by previous move";
+            assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move";
             switch (other.getKind()) {
                 case Int:  masm.cmovl(cond, asRegister(result), asRegister(other)); break;
                 case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 // @formatter:off
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Fri Jun 07 14:15:38 2013 +0200
@@ -35,7 +35,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
 
@@ -118,6 +117,36 @@
         }
     }
 
+    public static class LoadCompressedOop extends LoadOp {
+
+        private long narrowOopBase;
+        private int narrowOopShift;
+        private int logMinObjAlignment;
+        @Temp({REG}) private AllocatableValue scratch;
+
+        public LoadCompressedOop(Kind kind, AllocatableValue result, AllocatableValue scratch, AMD64AddressValue address, LIRFrameState state, long narrowOopBase, int narrowOopShift,
+                        int logMinObjAlignment) {
+            super(kind, result, address, state);
+            this.narrowOopBase = narrowOopBase;
+            this.narrowOopShift = narrowOopShift;
+            this.logMinObjAlignment = logMinObjAlignment;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitMemAccess(AMD64MacroAssembler masm) {
+            switch (kind) {
+                case Object:
+                    Register resRegister = asRegister(result);
+                    masm.movl(resRegister, address.toAddress());
+                    decodeOop(masm, resRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
     public static class LoadOp extends MemOp {
 
         @Def({REG}) protected AllocatableValue result;
@@ -161,6 +190,51 @@
         }
     }
 
+    public static class StoreCompressedOop extends AMD64LIRInstruction {
+
+        protected final Kind kind;
+        private long narrowOopBase;
+        private int narrowOopShift;
+        private int logMinObjAlignment;
+        @Temp({REG}) private AllocatableValue scratch;
+        @Alive({REG}) protected AllocatableValue input;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @State protected LIRFrameState state;
+
+        public StoreCompressedOop(Kind kind, AMD64AddressValue address, AllocatableValue input, AllocatableValue scratch, LIRFrameState state, long narrowOopBase, int narrowOopShift,
+                        int logMinObjAlignment) {
+            this.narrowOopBase = narrowOopBase;
+            this.narrowOopShift = narrowOopShift;
+            this.logMinObjAlignment = logMinObjAlignment;
+            this.scratch = scratch;
+            this.kind = kind;
+            this.address = address;
+            this.state = state;
+            this.input = input;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            emitMemAccess(tasm, masm);
+        }
+
+        public void emitMemAccess(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            switch (kind) {
+                case Object:
+                    masm.movq(asRegister(scratch), asRegister(input));
+                    encodeOop(masm, asRegister(scratch), narrowOopBase, narrowOopShift, logMinObjAlignment);
+                    if (state != null) {
+                        tasm.recordImplicitException(masm.codeBuffer.position(), state);
+                    }
+                    masm.movl(address.toAddress(), asRegister(scratch));
+                    // masm.movq(asRegister(scratch), 0xDEADBEEF);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
     public static class StoreOp extends MemOp {
 
         @Use({REG}) protected AllocatableValue input;
@@ -206,10 +280,12 @@
     public static class StoreConstantOp extends MemOp {
 
         protected final Constant input;
+        private final boolean compress;
 
-        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state) {
+        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state, boolean compress) {
             super(kind, address, state);
             this.input = input;
+            this.compress = compress;
         }
 
         @Override
@@ -240,7 +316,11 @@
                     throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                 case Object:
                     if (input.isNull()) {
-                        masm.movptr(address.toAddress(), 0);
+                        if (compress) {
+                            masm.movl(address.toAddress(), 0);
+                        } else {
+                            masm.movptr(address.toAddress(), 0);
+                        }
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                     }
@@ -335,6 +415,37 @@
         }
     }
 
+    @Opcode("CAS")
+    public static class CompareAndSwapCompressedOp extends AMD64LIRInstruction {
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Alive protected AllocatableValue cmpValue;
+        @Alive protected AllocatableValue newValue;
+        @Temp({REG}) protected AllocatableValue scratch;
+
+        private long narrowOopBase;
+        private int narrowOopShift;
+        private int logMinObjAlignment;
+
+        public CompareAndSwapCompressedOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, AllocatableValue scratch, long narrowOopBase,
+                        int narrowOopShift, int logMinObjAlignment) {
+            this.narrowOopBase = narrowOopBase;
+            this.narrowOopShift = narrowOopShift;
+            this.logMinObjAlignment = logMinObjAlignment;
+            this.scratch = scratch;
+            this.result = result;
+            this.address = address;
+            this.cmpValue = cmpValue;
+            this.newValue = newValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            compareAndSwapCompressed(tasm, masm, result, address, cmpValue, newValue, scratch, narrowOopBase, narrowOopShift, logMinObjAlignment);
+        }
+    }
+
     public static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) {
         if (isRegister(input)) {
             if (isRegister(result)) {
@@ -526,7 +637,7 @@
     }
 
     protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
-        assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax;
+        assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax);
 
         if (tasm.target.isMP) {
             masm.lock();
@@ -543,4 +654,51 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
+
+    protected static void compareAndSwapCompressed(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue,
+                    AllocatableValue newValue, AllocatableValue scratch, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+        assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax;
+
+        switch (cmpValue.getKind()) {
+            case Object:
+                final Register scratchRegister = asRegister(scratch);
+                final Register cmpRegister = asRegister(cmpValue);
+                final Register newRegister = asRegister(newValue);
+                encodeOop(masm, cmpRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+                masm.movq(scratchRegister, newRegister);
+                encodeOop(masm, scratchRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+                if (tasm.target.isMP) {
+                    masm.lock();
+                }
+                masm.cmpxchgl(scratchRegister, address.toAddress());
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void encodeOop(AMD64MacroAssembler masm, Register scratchRegister, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+        if (narrowOopBase == 0) {
+            if (narrowOopShift != 0) {
+                assert logMinObjAlignment == narrowOopShift : "Encode algorithm is wrong";
+                masm.shrq(scratchRegister, logMinObjAlignment);
+            }
+        } else {
+            masm.subq(scratchRegister, AMD64.r12);
+            masm.shrq(scratchRegister, logMinObjAlignment);
+        }
+    }
+
+    private static void decodeOop(AMD64MacroAssembler masm, Register resRegister, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+        if (narrowOopBase == 0) {
+            if (narrowOopShift != 0) {
+                assert logMinObjAlignment == narrowOopShift : "Decode algorithm is wrong";
+                masm.shlq(resRegister, logMinObjAlignment);
+            }
+        } else {
+            masm.shlq(resRegister, logMinObjAlignment);
+            masm.addq(resRegister, AMD64.r12);
+        }
+    }
+
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 public class PTXBitManipulationOp extends PTXLIRInstruction {
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Fri Jun 07 14:15:38 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.*;
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Fri Jun 07 14:15:38 2013 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.sparc;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+
+public class SPARCAddressValue extends CompositeValue {
+
+    private static final long serialVersionUID = -3583286416638228207L;
+
+    @Component({ REG, OperandFlag.ILLEGAL })
+    protected AllocatableValue base;
+    protected final int displacement;
+
+    public SPARCAddressValue(PlatformKind kind, AllocatableValue baseRegister,
+            int finalDisp) {
+        super(kind);
+        this.base = baseRegister;
+        this.displacement = finalDisp;
+    }
+
+    private static Register toRegister(AllocatableValue value) {
+        if (value.equals(Value.ILLEGAL)) {
+            return Register.None;
+        } else {
+            RegisterValue reg = (RegisterValue) value;
+            return reg.getRegister();
+        }
+    }
+
+    public SPARCAddress toAddress() {
+        return new SPARCAddress(toRegister(base), displacement);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Add;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.And;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fadds;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Faddd;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fdivs;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fdivd;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fdtoi;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fmuls;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fmuld;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fnegs;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fnegd;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fstoi;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fsubs;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Fsubd;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Mulx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Or;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Sdivx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Sll;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Sllx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Srl;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Srlx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Sra;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Sub;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Xor;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.isSimm13;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.CONST;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.HINT;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.STACK;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.TargetMethodAssembler;
+
+//@formatter:off
+public enum SPARCArithmetic {
+    // @formatter:off
+    IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
+    LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
+    DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
+    INEG, LNEG, FNEG, DNEG,
+    I2L, L2I, I2B, I2C, I2S,
+    F2D, D2F,
+    I2F, I2D, F2I, D2I,
+    L2F, L2D, F2L, D2L,
+    MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
+
+    /**
+     * Binary operation with single source/destination operand and one constant.
+     */
+    public static class BinaryRegConst extends SPARCLIRInstruction {
+        @Opcode private final SPARCArithmetic opcode;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+        protected Constant y;
+
+        public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            SPARCMove.move(tasm, masm, result, x);
+            emit(tasm, masm, opcode, result, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    /**
+     * Unary operation with separate source and destination operand.
+     */
+    public static class Unary2Op extends SPARCLIRInstruction {
+
+        @Opcode
+        private final SPARCArithmetic opcode;
+        @Def({ REG })
+        protected AllocatableValue result;
+        @Use({ REG, STACK })
+        protected AllocatableValue x;
+
+        public Unary2Op(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            SPARCMove.move(tasm, masm, result, x);
+            emit(tasm, masm, opcode, result, x, null);
+        }
+    }
+
+    /**
+     * Unary operation with single operand for source and destination.
+     */
+    public static class Unary1Op extends SPARCLIRInstruction {
+
+        @Opcode
+        private final SPARCArithmetic opcode;
+        @Def({ REG, HINT })
+        protected AllocatableValue result;
+        @Use({ REG, STACK })
+        protected AllocatableValue x;
+
+        public Unary1Op(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            emit(masm, opcode, result);
+        }
+    }
+
+    public static class Op1Stack extends SPARCLIRInstruction {
+
+        @Opcode
+        private final SPARCArithmetic opcode;
+        @Def({ REG, HINT })
+        protected Value result;
+        @Use({ REG, STACK, CONST })
+        protected Value x;
+
+        public Op1Stack(SPARCArithmetic opcode, Value result, Value x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            emit(tasm, masm, opcode, result, x, null);
+        }
+    }
+
+    public static class Op2Stack extends SPARCLIRInstruction {
+
+        @Opcode
+        private final SPARCArithmetic opcode;
+        @Def({ REG, HINT })
+        protected Value result;
+        @Use({ REG, STACK, CONST })
+        protected Value x;
+        @Alive({ REG, STACK, CONST })
+        protected Value y;
+
+        public Op2Stack(SPARCArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            emit(tasm, masm, opcode, result, x, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    public static class Op2Reg extends SPARCLIRInstruction {
+
+        @Opcode
+        private final SPARCArithmetic opcode;
+        @Def({ REG, HINT })
+        protected Value result;
+        @Use({ REG, STACK, CONST })
+        protected Value x;
+        @Alive({ REG, CONST })
+        protected Value y;
+
+        public Op2Reg(SPARCArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            emit(tasm, masm, opcode, result, x, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    public static class ShiftOp extends SPARCLIRInstruction {
+
+        @Opcode
+        private final SPARCArithmetic opcode;
+        @Def({ REG, HINT })
+        protected Value result;
+        @Use({ REG, STACK, CONST })
+        protected Value x;
+        @Alive({ REG, CONST })
+        protected Value y;
+
+        public ShiftOp(SPARCArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            emit(tasm, masm, opcode, result, x, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, x);
+            assert y.getKind().getStackKind() == Kind.Int;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    protected static void emit(SPARCAssembler masm, SPARCArithmetic opcode, Value result) {
+        switch (opcode) {
+        case L2I:
+            new And(masm, asIntReg(result), -1, asIntReg(result));
+            break;
+        case I2C:
+            new Sll(masm, asIntReg(result), 16, asIntReg(result));
+            new Srl(masm, asIntReg(result), 16, asIntReg(result));
+            break;
+        default:
+            throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static void emit(TargetMethodAssembler tasm, SPARCAssembler masm,
+            SPARCArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) {
+        int exceptionOffset = -1;
+        if (isConstant(src1)) {
+            switch (opcode) {
+            case ISUB:
+                assert isSimm13(tasm.asIntConst(src1));
+                new Add(masm, asIntReg(src2), -(tasm.asIntConst(src1)), asIntReg(dst));
+                break;
+            case IAND:
+                throw new InternalError("NYI");
+            case IDIV:
+                assert isSimm13(tasm.asIntConst(src1));
+                throw new InternalError("NYI");
+                // new Sdivx(masm, asIntReg(src1), asIntReg(src2),
+                // asIntReg(dst));
+            case FSUB:
+                throw new InternalError("NYI");
+            case FDIV:
+                throw new InternalError("NYI");
+            case DSUB:
+                throw new InternalError("NYI");
+            case DDIV:
+                throw new InternalError("NYI");
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(src2)) {
+            switch (opcode) {
+            case IADD:
+                assert isSimm13(tasm.asIntConst(src2));
+                new Add(masm, asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst));
+                break;
+            case ISUB:
+                assert isSimm13(tasm.asIntConst(src2));
+                new Sub(masm, asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst));
+                break;
+            case IMUL:
+                assert isSimm13(tasm.asIntConst(src2));
+                new Mulx(masm, asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst));
+                break;
+            case IAND:
+                assert isSimm13(tasm.asIntConst(src2));
+                new And(masm, asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst));
+                break;
+            case ISHL:
+                assert isSimm13(tasm.asIntConst(src2));
+                new Sll(masm, asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst));
+                break;
+            case ISHR:
+                assert isSimm13(tasm.asIntConst(src2));
+                new Srl(masm, asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst));
+                break;
+            case IUSHR:
+                assert isSimm13(tasm.asIntConst(src2));
+                new Sra(masm, asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst));
+                break;
+            case IXOR:
+                assert isSimm13(tasm.asIntConst(src2));
+                new Xor(masm, asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst));
+                break;
+            case LXOR:
+                assert isSimm13(tasm.asIntConst(src2));
+                new Add(masm, asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst));
+                break;
+            case LUSHR:
+                throw new InternalError("NYI");
+            case FADD:
+                throw new InternalError("NYI");
+            case FMUL:
+                throw new InternalError("NYI");
+            case FDIV:
+                throw new InternalError("NYI");
+            case DADD:
+                throw new InternalError("NYI");
+            case DMUL:
+                throw new InternalError("NYI");
+            case DDIV:
+                throw new InternalError("NYI");
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (opcode) {
+            case IADD:
+                new Add(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case ISUB:
+                new Sub(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case IMUL:
+                new Mulx(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case IDIV:
+                new Sdivx(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case IAND:
+                new And(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case IOR:
+                new Or(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case IXOR:
+                new Xor(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case ISHL:
+                new Sll(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case ISHR:
+                new Srl(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case IUSHR:
+                new Sra(masm, asIntReg(src1), asIntReg(src2), asIntReg(dst));
+                break;
+            case IREM:
+                throw new InternalError("NYI");
+            case LADD:
+                new Add(masm, asLongReg(src1), asLongReg(src2), asLongReg(dst));
+                break;
+            case LSUB:
+                new Sub(masm, asLongReg(src1), asLongReg(src2), asLongReg(dst));
+                break;
+            case LMUL:
+                new Mulx(masm, asLongReg(src1), asLongReg(src2), asLongReg(dst));
+                break;
+            case LDIV:
+                new Sdivx(masm, asLongReg(src1), asLongReg(src2),
+                        asLongReg(dst));
+                break;
+            case LAND:
+                new And(masm, asLongReg(src1), asLongReg(src2), asLongReg(dst));
+                break;
+            case LOR:
+                new Or(masm, asLongReg(src1), asLongReg(src2), asLongReg(dst));
+                break;
+            case LXOR:
+                new Xor(masm, asLongReg(src1), asLongReg(src2), asLongReg(dst));
+                break;
+            case LSHL:
+                new Sll(masm, asLongReg(src1), asLongReg(src2), asLongReg(dst));
+                break;
+            case LSHR:
+                new Srl(masm, asLongReg(src1), asLongReg(src2), asLongReg(dst));
+                break;
+            case LUSHR:
+                new Sra(masm, asLongReg(src1), asIntReg(src2), asLongReg(dst));
+                break;
+            case LDIVREM:
+            case LUDIV:
+            case LUREM:
+            case LREM:
+                throw new InternalError("NYI");
+            case FADD:
+                new Fadds(masm, asFloatReg(src1), asFloatReg(src2),
+                        asFloatReg(dst));
+                break;
+            case FSUB:
+                new Fsubs(masm, asFloatReg(src1), asFloatReg(src2),
+                        asFloatReg(dst));
+                break;
+            case FMUL:
+                new Fmuls(masm, asFloatReg(src1), asFloatReg(src2),
+                        asFloatReg(dst));
+                break;
+            case FDIV:
+                new Fdivs(masm, asFloatReg(src1), asFloatReg(src2),
+                        asFloatReg(dst));
+                break;
+            case FREM:
+                throw new InternalError("NYI");
+            case DADD:
+                new Faddd(masm, asDoubleReg(src1), asDoubleReg(src2),
+                        asDoubleReg(dst));
+                break;
+            case DSUB:
+                new Fsubd(masm, asDoubleReg(src1), asDoubleReg(src2),
+                        asDoubleReg(dst));
+                break;
+            case DMUL:
+                new Fmuld(masm, asDoubleReg(src1), asDoubleReg(src2),
+                        asDoubleReg(dst));
+                break;
+            case DDIV:
+                new Fdivd(masm, asDoubleReg(src1), asDoubleReg(src2),
+                        asDoubleReg(dst));
+                break;
+            case DREM:
+                throw new InternalError("NYI");
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: "
+                        + opcode);
+            }
+        }
+
+        if (info != null) {
+            assert exceptionOffset != -1;
+            tasm.recordImplicitException(exceptionOffset, info);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static void emit(TargetMethodAssembler tasm, SPARCAssembler masm,
+            SPARCArithmetic opcode, Value dst, Value src, LIRFrameState info) {
+        int exceptionOffset = -1;
+        if (isRegister(src)) {
+            switch (opcode) {
+            case I2L:
+                new Sra(masm, asIntReg(src), 0, asLongReg(dst));
+                break;
+            case I2B:
+                new Sll(masm, asIntReg(src), 24, asIntReg(src));
+                new Srl(masm, asIntReg(dst), 24, asIntReg(src));
+                break;
+            case I2F:
+                new Fstoi(masm, asIntReg(src), asFloatReg(dst));
+                break;
+            case I2D:
+                new Fdtoi(masm, asIntReg(src), asDoubleReg(dst));
+                break;
+            case FNEG:
+                new Fnegs(masm, asFloatReg(src), asFloatReg(dst));
+                break;
+            case DNEG:
+                new Fnegd(masm, asDoubleReg(src), asDoubleReg(dst));
+                break;
+            case LSHL:
+                new Sllx(masm, asLongReg(dst), asIntReg(src), asLongReg(dst));
+                break;
+            case LSHR:
+                new Srlx(masm, asLongReg(dst), asIntReg(src), asLongReg(dst));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: "
+                        + opcode);
+            }
+        } else if (isConstant(src)) {
+            switch (opcode) {
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: "
+                        + opcode);
+            }
+        } else {
+            switch (opcode) {
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: "
+                        + opcode);
+            }
+        }
+
+        if (info != null) {
+            assert exceptionOffset != -1;
+            tasm.recordImplicitException(exceptionOffset, info);
+        }
+    }
+
+    private static void verifyKind(SPARCArithmetic opcode, Value result, Value x, Value y) {
+        Kind rk;
+        Kind xk;
+        Kind yk;
+        Kind xsk;
+        Kind ysk;
+
+        switch (opcode) {
+        case IADD:
+        case ISUB:
+        case IMUL:
+        case IDIV:
+        case IREM:
+        case IAND:
+        case IOR:
+        case IXOR:
+        case ISHL:
+        case ISHR:
+        case IUSHR:
+            rk = result.getKind();
+            xsk = x.getKind().getStackKind();
+            ysk = y.getKind().getStackKind();
+
+            assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int;
+            break;
+        case LADD:
+        case LSUB:
+        case LMUL:
+        case LDIV:
+        case LREM:
+        case LAND:
+        case LOR:
+        case LXOR:
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+            rk = result.getKind();
+            xk = x.getKind();
+            yk = y.getKind();
+
+            assert rk == Kind.Long && xk == Kind.Long && yk == Kind.Long;
+            break;
+        case FADD:
+        case FSUB:
+        case FMUL:
+        case FDIV:
+        case FREM:
+            rk = result.getKind();
+            xk = x.getKind();
+            yk = y.getKind();
+
+            assert rk == Kind.Float && xk == Kind.Float && yk == Kind.Float;
+            break;
+        case DADD:
+        case DSUB:
+        case DMUL:
+        case DDIV:
+        case DREM:
+            rk = result.getKind();
+            xk = x.getKind();
+            yk = y.getKind();
+
+            assert rk == Kind.Double && xk == Kind.Double && yk == Kind.Double;
+            break;
+        default:
+            throw new InternalError("NYI: " + opcode);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,108 @@
+/*
+ * 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.lir.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Popc;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Srl;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.isSimm13;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.sparc.SPARC;
+
+public class SPARCBitManipulationOp extends SPARCLIRInstruction {
+
+    public enum IntrinsicOpcode {
+        IPOPCNT, LPOPCNT, IBSR, LBSR, BSF;
+    }
+
+    @Opcode private final IntrinsicOpcode opcode;
+    @Def protected AllocatableValue result;
+    @Use({OperandFlag.REG, OperandFlag.STACK}) protected AllocatableValue input;
+
+    public SPARCBitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input) {
+        this.opcode = opcode;
+        this.result = result;
+        this.input = input;
+    }
+
+    @Override
+    @SuppressWarnings("unused")
+    public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+        Register dst = ValueUtil.asIntReg(result);
+        if (ValueUtil.isRegister(input)) {
+            Register src = ValueUtil.asRegister(input);
+            switch (opcode) {
+                case IPOPCNT:
+                    // clear upper word for 64 bit POPC
+                    new Srl(masm, src, SPARC.g0, dst);
+                    new Popc(masm, src, dst);
+                    break;
+                case LPOPCNT:
+                    new Popc(masm, src, dst);
+                    break;
+                case BSF:  // masm.bsfq(dst, src);
+                case IBSR:  // masm.bsrl(dst, src);
+                case LBSR:  // masm.bsrq(dst, src);
+                default:
+                    throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+
+            }
+        } else if (ValueUtil.isConstant(input) && isSimm13(tasm.asIntConst(input))) {
+            switch (opcode) {
+                case IPOPCNT:
+                    new Popc(masm, tasm.asIntConst(input), dst);
+                    break;
+                case LPOPCNT:
+                    new Popc(masm, tasm.asIntConst(input), dst);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+            }
+        } else {
+            SPARCAddress src = (SPARCAddress) tasm.asAddress(input);
+            switch (opcode) {
+                case IPOPCNT:
+                    // masm.popcntl(dst, src);
+                    break;
+                case LPOPCNT:
+                    // masm.popcntq(dst, src);
+                    break;
+                case BSF:
+                    // masm.bsfq(dst, src);
+                    break;
+                case IBSR:
+                    // masm.bsrl(dst, src);
+                    break;
+                case LBSR:
+                    // masm.bsrq(dst, src);
+                    break;
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.lir.sparc;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Trap;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Emits a breakpoint.
+ */
+@Opcode("BREAKPOINT")
+public class SPARCBreakpointOp extends SPARCLIRInstruction {
+
+    // historical - from hotspot src/cpu/sparc/vm
+    // <sys/trap.h> promises that the system will not use traps 16-31
+    // We want to use ST_BREAKPOINT here, but the debugger is confused by it.
+    public static final int ST_RESERVED_FOR_USER_0 = 0x10;
+
+    /**
+     * A set of values loaded into the Java ABI parameter locations (for inspection by a debugger).
+     */
+    @Use({REG, STACK}) protected Value[] parameters;
+
+    public SPARCBreakpointOp(Value[] parameters) {
+        this.parameters = parameters;
+    }
+
+    @Override
+    @SuppressWarnings("unused")
+    public void emitCode(TargetMethodAssembler tasm, SPARCAssembler asm) {
+        new Trap(asm, ST_RESERVED_FOR_USER_0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.sparc;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+@Opcode("BSWAP")
+public class SPARCByteSwapOp extends SPARCLIRInstruction {
+
+    @Def({OperandFlag.REG, OperandFlag.HINT}) protected Value result;
+    @Use protected Value input;
+
+    public SPARCByteSwapOp(Value result, Value input) {
+        this.result = result;
+        this.input = input;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+        SPARCMove.move(tasm, masm, result, input);
+        switch (input.getKind()) {
+        // case Int:
+        // masm.bswapl(ValueUtil.asIntReg(result));
+        // case Long:
+        // masm.bswapq(ValueUtil.asLongReg(result));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.isSimm13;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+//@formatter:off
+public enum SPARCCompare {
+    ICMP, LCMP, ACMP, FCMP, DCMP;
+
+    public static class CompareOp extends SPARCLIRInstruction {
+
+        @Opcode private final SPARCCompare opcode;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Use({REG, STACK, CONST}) protected Value y;
+
+        public CompareOp(SPARCCompare opcode, Value x, Value y) {
+            this.opcode = opcode;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            emit(tasm, masm, opcode, x, y);
+        }
+
+        @Override
+        protected void verify() {
+            super.verify();
+            assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
+                || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
+                || (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object)
+                || (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
+                || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static void emit(TargetMethodAssembler tasm, SPARCAssembler masm, SPARCCompare opcode, Value x, Value y) {
+        if (isRegister(y)) {
+            switch (opcode) {
+                case ICMP:
+                    new Cmp(masm, asIntReg(x), asIntReg(y));
+                    break;
+                case LCMP:
+                    new Cmp(masm, asLongReg(x), asLongReg(y));
+                    break;
+                case ACMP:
+                    // masm.cmpptr(asObjectReg(x), asObjectReg(y));
+                    break;
+                case FCMP:
+                    // masm.ucomiss(asFloatReg(x), asFloatReg(y));
+                    break;
+                case DCMP:
+                    // masm.ucomisd(asDoubleReg(x), asDoubleReg(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(y)) {
+            switch (opcode) {
+                case ICMP:
+                    assert isSimm13(tasm.asIntConst(y));
+                    new Cmp(masm, asIntReg(x), tasm.asIntConst(y));
+                    break;
+                case LCMP:
+                    assert isSimm13(tasm.asIntConst(y));
+                    new Cmp(masm, asLongReg(x), tasm.asIntConst(y));
+                    break;
+                case ACMP:
+                    if (((Constant) y).isNull()) {
+                        // masm.cmpq(asObjectReg(x), 0);
+                        break;
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons");
+                    }
+                case FCMP:
+                    // masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatConstRef(y));
+                    break;
+                case DCMP:
+                    // masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleConstRef(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (opcode) {
+                case ICMP:
+                    // masm.cmpl(asIntReg(x), (AMD64Address) tasm.asIntAddr(y)); 
+                    break;
+                case LCMP:
+                    // masm.cmpq(asLongReg(x), (AMD64Address) tasm.asLongAddr(y));
+                    break;
+                case ACMP:
+                    // masm.cmpptr(asObjectReg(x), (AMD64Address) tasm.asObjectAddr(y));
+                    break;
+                case FCMP:
+                    // masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatAddr(y));
+                    break;
+                case DCMP:
+                    // masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleAddr(y)); 
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.CompilationResult.JumpTable;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Bpe;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Subcc;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.sparc.*;
+
+public class SPARCControlFlow {
+
+    public static class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp {
+
+        protected Condition condition;
+        protected LabelRef destination;
+
+        public BranchOp(Condition condition, LabelRef destination) {
+            this.condition = condition;
+            this.destination = destination;
+        }
+
+        @Override
+        @SuppressWarnings("unused")
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            // masm.at();
+            Label l = destination.label();
+            // l.addPatchAt(tasm.asm.codeBuffer.position());
+            String target = l.isBound() ? "L" + l.toString() : AbstractSPARCAssembler.UNBOUND_TARGET;
+            // masm.bra(target);
+        }
+
+        @Override
+        public LabelRef destination() {
+            return destination;
+        }
+
+        @Override
+        public void negate(LabelRef newDestination) {
+            destination = newDestination;
+            condition = condition.negate();
+        }
+    }
+
+    @Opcode("CMOVE")
+    public static class CondMoveOp extends SPARCLIRInstruction {
+
+        @Def({REG, HINT}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Use({REG, STACK, CONST}) protected Value falseValue;
+
+        private final ConditionFlag condition;
+
+        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+            this.result = result;
+            this.condition = intCond(condition);
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            cmove(tasm, masm, result, false, condition, false, trueValue, falseValue);
+        }
+    }
+
+    @Opcode("CMOVE")
+    public static class FloatCondMoveOp extends SPARCLIRInstruction {
+
+        @Def({REG}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Alive({REG}) protected Value falseValue;
+        private final ConditionFlag condition;
+        private final boolean unorderedIsTrue;
+
+        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+            this.result = result;
+            this.condition = floatCond(condition);
+            this.unorderedIsTrue = unorderedIsTrue;
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
+        }
+    }
+
+    private static void cmove(TargetMethodAssembler tasm, SPARCAssembler masm, Value result, boolean isFloat, ConditionFlag condition, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
+        // check that we don't overwrite an input operand before it is used.
+        assert !result.equals(trueValue);
+
+        SPARCMove.move(tasm, masm, result, falseValue);
+        cmove(tasm, masm, result, condition, trueValue);
+
+        if (isFloat) {
+            if (unorderedIsTrue && !trueOnUnordered(condition)) {
+                // cmove(tasm, masm, result, ConditionFlag.Parity, trueValue);
+            } else if (!unorderedIsTrue && trueOnUnordered(condition)) {
+                // cmove(tasm, masm, result, ConditionFlag.Parity, falseValue);
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static void cmove(TargetMethodAssembler tasm, SPARCAssembler masm, Value result, ConditionFlag cond, Value other) {
+        if (isRegister(other)) {
+            assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move";
+            switch (other.getKind()) {
+                case Int:
+                    // masm.cmovl(cond, asRegister(result), asRegister(other));
+                    break;
+                case Long:
+                    // masm.cmovq(cond, asRegister(result), asRegister(other));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            SPARCAddress addr = (SPARCAddress) tasm.asAddress(other);
+            switch (other.getKind()) {
+                case Int:
+                    // masm.cmovl(cond, asRegister(result), addr);
+                    break;
+                case Long:
+                    // masm.cmovq(cond, asRegister(result), addr);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static ConditionFlag intCond(Condition cond) {
+        switch (cond) {
+            case EQ:
+                return ConditionFlag.Equal;
+            case NE:
+                return ConditionFlag.NotEqual;
+            case LT:
+                return ConditionFlag.Less;
+            case LE:
+                return ConditionFlag.LessEqual;
+            case GE:
+                return ConditionFlag.GreaterEqual;
+            case GT:
+                return ConditionFlag.Greater;
+            case BE:
+            case AE:
+            case AT:
+            case BT:
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static ConditionFlag floatCond(Condition cond) {
+        switch (cond) {
+            case EQ:
+                return ConditionFlag.Equal;
+            case NE:
+                return ConditionFlag.NotEqual;
+            case LT:
+            case LE:
+            case GE:
+            case GT:
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static boolean trueOnUnordered(ConditionFlag condition) {
+        switch (condition) {
+            case NotEqual:
+            case Less:
+                return false;
+            case Equal:
+            case GreaterEqual:
+                return true;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static class ReturnOp extends SPARCLIRInstruction {
+
+        @Use({REG, ILLEGAL}) protected Value x;
+
+        public ReturnOp(Value x) {
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            if (tasm.frameContext != null) {
+                tasm.frameContext.leave(tasm);
+            }
+            // masm.return();
+        }
+    }
+
+    public static class SequentialSwitchOp extends SPARCLIRInstruction implements FallThroughOp {
+
+        @Use({CONST}) protected Constant[] keyConstants;
+        private final LabelRef[] keyTargets;
+        private LabelRef defaultTarget;
+        @Alive({REG}) protected Value key;
+        @Temp({REG, ILLEGAL}) protected Value scratch;
+
+        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
+            assert keyConstants.length == keyTargets.length;
+            this.keyConstants = keyConstants;
+            this.keyTargets = keyTargets;
+            this.defaultTarget = defaultTarget;
+            this.key = key;
+            this.scratch = scratch;
+        }
+
+        @Override
+        @SuppressWarnings("unused")
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            if (key.getKind() == Kind.Int) {
+                Register intKey = asIntReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    if (tasm.runtime.needsDataPatch(keyConstants[i])) {
+                        tasm.recordDataReferenceInCode(keyConstants[i], 0, true);
+                    }
+                    long lc = keyConstants[i].asLong();
+                    assert NumUtil.isInt(lc);
+                    new Subcc(masm, intKey, (int) lc, SPARC.r0); // CMP
+                    Label l = keyTargets[i].label();
+                    l.addPatchAt(tasm.asm.codeBuffer.position());
+                    new Bpe(masm, CC.Icc, l);
+                }
+            } else if (key.getKind() == Kind.Long) {
+                Register longKey = asLongReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    // masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]),
+                    // longKey);
+                    // masm.at();
+                    Label l = keyTargets[i].label();
+                    l.addPatchAt(tasm.asm.codeBuffer.position());
+                    new Bpe(masm, CC.Xcc, l);
+                }
+            } else if (key.getKind() == Kind.Object) {
+                Register intKey = asObjectReg(key);
+                Register temp = asObjectReg(scratch);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    SPARCMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
+                    new Subcc(masm, intKey, temp, SPARC.r0); // CMP
+                    new Bpe(masm, CC.Icc, keyTargets[i].label());
+                }
+            } else {
+                throw new GraalInternalError("sequential switch only supported for int, long and object");
+            }
+            if (defaultTarget != null) {
+                masm.jmp(defaultTarget.label());
+            } else {
+                // masm.hlt();
+            }
+        }
+
+        @Override
+        public LabelRef fallThroughTarget() {
+            return defaultTarget;
+        }
+
+        @Override
+        public void setFallThroughTarget(LabelRef target) {
+            defaultTarget = target;
+        }
+    }
+
+    public static class SwitchRangesOp extends SPARCLIRInstruction implements FallThroughOp {
+
+        private final LabelRef[] keyTargets;
+        private LabelRef defaultTarget;
+        private final int[] lowKeys;
+        private final int[] highKeys;
+        @Alive protected Value key;
+
+        public SwitchRangesOp(int[] lowKeys, int[] highKeys, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
+            this.lowKeys = lowKeys;
+            this.highKeys = highKeys;
+            this.keyTargets = keyTargets;
+            this.defaultTarget = defaultTarget;
+            this.key = key;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            assert isSorted(lowKeys) && isSorted(highKeys);
+
+            @SuppressWarnings("unused")
+            Label actualDefaultTarget = defaultTarget == null ? new Label() : defaultTarget.label();
+            int prevHighKey = 0;
+            boolean skipLowCheck = false;
+            for (int i = 0; i < lowKeys.length; i++) {
+                int lowKey = lowKeys[i];
+                int highKey = highKeys[i];
+                if (lowKey == highKey) {
+                    // masm.cmpl(asIntReg(key), lowKey);
+                    // masm.jcc(ConditionFlag.Equal, keyTargets[i].label());
+                    skipLowCheck = false;
+                } else {
+                    if (!skipLowCheck || (prevHighKey + 1) != lowKey) {
+                        // masm.cmpl(asIntReg(key), lowKey);
+                        // masm.jcc(ConditionFlag.Less, actualDefaultTarget);
+                    }
+                    // masm.cmpl(asIntReg(key), highKey);
+                    // masm.jcc(ConditionFlag.LessEqual, keyTargets[i].label());
+                    skipLowCheck = true;
+                }
+                prevHighKey = highKey;
+            }
+            if (defaultTarget != null) {
+                // masm.jmp(defaultTarget.label());
+            } else {
+                // masm.bind(actualDefaultTarget);
+                // masm.hlt();
+            }
+        }
+
+        @Override
+        protected void verify() {
+            super.verify();
+            assert lowKeys.length == keyTargets.length;
+            assert highKeys.length == keyTargets.length;
+            assert key.getKind() == Kind.Int;
+        }
+
+        @Override
+        public LabelRef fallThroughTarget() {
+            return defaultTarget;
+        }
+
+        @Override
+        public void setFallThroughTarget(LabelRef target) {
+            defaultTarget = target;
+        }
+
+        private static boolean isSorted(int[] values) {
+            for (int i = 1; i < values.length; i++) {
+                if (values[i - 1] >= values[i]) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    public static class TableSwitchOp extends SPARCLIRInstruction {
+
+        private final int lowKey;
+        private final LabelRef defaultTarget;
+        private final LabelRef[] targets;
+        @Alive protected Value index;
+        @Temp protected Value scratch;
+
+        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) {
+            this.lowKey = lowKey;
+            this.defaultTarget = defaultTarget;
+            this.targets = targets;
+            this.index = index;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch));
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static void tableswitch(TargetMethodAssembler tasm, SPARCAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, Register value, Register scratch) {
+        Buffer buf = masm.codeBuffer;
+        // Compare index against jump table bounds
+        int highKey = lowKey + targets.length - 1;
+        if (lowKey != 0) {
+            // subtract the low value from the switch value
+            // masm.sub_s32(value, value, lowKey);
+            // masm.setp_gt_s32(value, highKey - lowKey);
+        } else {
+            // masm.setp_gt_s32(value, highKey);
+        }
+
+        // Jump to default target if index is not within the jump table
+        if (defaultTarget != null) {
+            // masm.at();
+            // masm.bra(defaultTarget.label().toString());
+        }
+
+        // address of jump table
+        int tablePos = buf.position();
+
+        JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
+        tasm.compilationResult.addAnnotation(jt);
+
+        // SPARC: unimp: tableswitch extract
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 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.lir.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Fsqrtd;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+public class SPARCMathIntrinsicOp extends SPARCLIRInstruction {
+
+    public enum IntrinsicOpcode {
+        SQRT, SIN, COS, TAN, LOG, LOG10
+    }
+
+    @Opcode private final IntrinsicOpcode opcode;
+    @Def protected Value result;
+    @Use protected Value input;
+
+    public SPARCMathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) {
+        this.opcode = opcode;
+        this.result = result;
+        this.input = input;
+    }
+
+    @Override
+    @SuppressWarnings("unused")
+    public void emitCode(TargetMethodAssembler tasm, SPARCAssembler asm) {
+        switch (opcode) {
+            case SQRT:
+                new Fsqrtd(asm, asDoubleReg(result), asDoubleReg(input));
+                break;
+            case LOG:
+            case LOG10:
+            case SIN:
+            case COS:
+            case TAN:
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsh;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Lduw;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Membar;
+import com.oracle.graal.asm.sparc.SPARCAssembler.NullCheck;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Or;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stb;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Sth;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stw;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setuw;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.sparc.*;
+
+public class SPARCMove {
+
+    public static class LoadOp extends SPARCLIRInstruction {
+
+        private final Kind kind;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE}) protected SPARCAddressValue address;
+        @State protected LIRFrameState state;
+
+        public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state) {
+            this.kind = kind;
+            this.result = result;
+            this.address = address;
+            this.state = state;
+        }
+
+        @Override
+        @SuppressWarnings("unused")
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            SPARCAddress addr = address.toAddress();
+            switch (kind) {
+                case Byte:
+                    new Ldsb(masm, addr, asRegister(result));
+                    break;
+                case Short:
+                    new Ldsh(masm, addr, asRegister(result));
+                    break;
+                case Char:
+                    new Lduw(masm, addr, asRegister(result));
+                    break;
+                case Int:
+                    new Ldsw(masm, addr, asRegister(result));
+                    break;
+                case Long:
+                    new Ldx(masm, addr, asRegister(result));
+                    break;
+                case Float:
+                    new Ldf(masm, addr, asRegister(result));
+                    break;
+                case Double:
+                    new Lddf(masm, addr, asRegister(result));
+                    break;
+                case Object:
+                    new Ldx(masm, addr, asRegister(result));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class MembarOp extends SPARCLIRInstruction {
+
+        private final int barriers;
+
+        public MembarOp(final int barriers) {
+            this.barriers = barriers;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler asm) {
+            new Membar(asm, barriers);
+        }
+    }
+
+    @Opcode("MOVE")
+    public static class MoveToRegOp extends SPARCLIRInstruction implements MoveOp {
+
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK, CONST}) protected Value input;
+
+        public MoveToRegOp(AllocatableValue result, Value input) {
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            move(tasm, masm, getResult(), getInput());
+        }
+
+        @Override
+        public Value getInput() {
+            return input;
+        }
+
+        @Override
+        public AllocatableValue getResult() {
+            return result;
+        }
+    }
+
+    @Opcode("MOVE")
+    public static class MoveFromRegOp extends SPARCLIRInstruction implements MoveOp {
+
+        @Def({REG, STACK}) protected AllocatableValue result;
+        @Use({REG, CONST, HINT}) protected Value input;
+
+        public MoveFromRegOp(AllocatableValue result, Value input) {
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            move(tasm, masm, getResult(), getInput());
+        }
+
+        @Override
+        public Value getInput() {
+            return input;
+        }
+
+        @Override
+        public AllocatableValue getResult() {
+            return result;
+        }
+    }
+
+    public static class NullCheckOp extends SPARCLIRInstruction {
+
+        @Use({REG}) protected AllocatableValue input;
+        @State protected LIRFrameState state;
+
+        public NullCheckOp(Variable input, LIRFrameState state) {
+            this.input = input;
+            this.state = state;
+        }
+
+        @Override
+        @SuppressWarnings("unused")
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            tasm.recordImplicitException(masm.codeBuffer.position(), state);
+            new NullCheck(masm, new SPARCAddress(asRegister(input), 0));
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class StackLoadAddressOp extends SPARCLIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({STACK, UNINITIALIZED}) protected StackSlot slot;
+
+        public StackLoadAddressOp(AllocatableValue result, StackSlot slot) {
+            this.result = result;
+            this.slot = slot;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler asm) {
+            new Ldx(asm, (SPARCAddress) tasm.asAddress(slot), asLongReg(result));
+        }
+    }
+
+    public static class StoreOp extends SPARCLIRInstruction {
+
+        private final Kind kind;
+        @Use({COMPOSITE}) protected SPARCAddressValue address;
+        @Use({REG}) protected AllocatableValue input;
+        @State protected LIRFrameState state;
+
+        public StoreOp(Kind kind, SPARCAddressValue address, AllocatableValue input, LIRFrameState state) {
+            this.kind = kind;
+            this.address = address;
+            this.input = input;
+            this.state = state;
+        }
+
+        @Override
+        @SuppressWarnings("unused")
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            assert isRegister(input);
+            SPARCAddress addr = address.toAddress();
+            switch (kind) {
+                case Byte:
+                    new Stb(masm, asRegister(input), addr);
+                    break;
+                case Short:
+                    new Sth(masm, asRegister(input), addr);
+                    break;
+                case Int:
+                    new Stw(masm, asRegister(input), addr);
+                    break;
+                case Long:
+                    new Stx(masm, asRegister(input), addr);
+                    break;
+                case Float:
+                    new Stx(masm, asRegister(input), addr);
+                    break;
+                case Double:
+                    new Stx(masm, asRegister(input), addr);
+                    break;
+                case Object:
+                    new Stx(masm, asRegister(input), addr);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
+            }
+        }
+    }
+
+    public static void move(TargetMethodAssembler tasm, SPARCAssembler masm, Value result, Value input) {
+        if (isRegister(input)) {
+            if (isRegister(result)) {
+                reg2reg(masm, result, input);
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(input)) {
+            if (isRegister(result)) {
+                const2reg(tasm, masm, result, (Constant) input);
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static void reg2reg(SPARCAssembler masm, Value result, Value input) {
+        if (asRegister(input).equals(asRegister(result))) {
+            return;
+        }
+        switch (input.getKind()) {
+            case Int:
+                new Or(masm, SPARC.r0, asRegister(input), asRegister(result));
+                break;
+            case Long:
+                new Or(masm, SPARC.r0, asRegister(input), asRegister(result));
+                break;
+            case Float:
+                new Or(masm, SPARC.r0, asRegister(input), asRegister(result));
+                break;
+            case Double:
+                new Or(masm, SPARC.r0, asRegister(input), asRegister(result));
+                break;
+            case Object:
+                new Or(masm, SPARC.r0, asRegister(input), asRegister(result));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static void const2reg(TargetMethodAssembler tasm, SPARCAssembler masm, Value result, Constant input) {
+        switch (input.getKind().getStackKind()) {
+            case Int:
+                if (tasm.runtime.needsDataPatch(input)) {
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                }
+                new Setuw(masm, input.asInt(), asRegister(result));
+                break;
+            case Long:
+                if (tasm.runtime.needsDataPatch(input)) {
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                }
+                new Setx(masm, input.asInt(), null, asRegister(result));
+                break;
+            case Object:
+                if (input.isNull()) {
+                    new Setx(masm, 0x0L, null, asRegister(result));
+                } else if (tasm.target.inlineObjects) {
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                    new Setx(masm, 0xDEADDEADDEADDEADL, null, asRegister(result));
+                } else {
+                    throw new InternalError("NYI");
+                }
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011, 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.lir.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.asm.*;
+
+public class SPARCTestOp extends SPARCLIRInstruction {
+
+    @Use({REG}) protected Value x;
+    @Use({REG, STACK, CONST}) protected Value y;
+
+    public SPARCTestOp(Value x, Value y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    @Override
+    @SuppressWarnings("unused")
+    public void emitCode(TargetMethodAssembler tasm, SPARCAssembler asm) {
+        if (isRegister(y)) {
+            switch (x.getKind()) {
+                case Int:
+                    new Cmp(asm, asIntReg(x), asIntReg(y));
+                    break;
+                case Long:
+                    new Cmp(asm, asLongReg(x), asLongReg(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(y)) {
+            switch (x.getKind()) {
+                case Int:
+                    new Cmp(asm, asIntReg(x), tasm.asIntConst(y));
+                    break;
+                case Long:
+                    new Cmp(asm, asLongReg(x), tasm.asIntConst(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (x.getKind()) {
+                case Int:
+                    new Ldsw(asm, (SPARCAddress) tasm.asIntAddr(y), asIntReg(y));
+                    new Cmp(asm, asIntReg(x), asIntReg(y));
+                    break;
+                case Long:
+                    new Ldx(asm, (SPARCAddress) tasm.asLongAddr(y), asLongReg(y));
+                    new Cmp(asm, asLongReg(x), asLongReg(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.lir;
 
-import static com.oracle.graal.lir.LIRInstruction.Opcode;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Fri Jun 07 14:15:38 2013 +0200
@@ -144,13 +144,6 @@
     public static @interface State {
     }
 
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.TYPE, ElementType.FIELD})
-    public static @interface Opcode {
-
-        String value() default "";
-    }
-
     /**
      * Flags for an operand.
      */
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Fri Jun 07 14:15:38 2013 +0200
@@ -174,8 +174,8 @@
 
         @Override
         protected void scan(Class<?> clazz) {
-            if (clazz.getAnnotation(LIRInstruction.Opcode.class) != null) {
-                opcodeConstant = clazz.getAnnotation(LIRInstruction.Opcode.class).value();
+            if (clazz.getAnnotation(Opcode.class) != null) {
+                opcodeConstant = clazz.getAnnotation(Opcode.class).value();
             }
             opcodeOffset = -1;
 
@@ -199,7 +199,7 @@
                 super.scanField(field, type, offset);
             }
 
-            if (field.getAnnotation(LIRInstruction.Opcode.class) != null) {
+            if (field.getAnnotation(Opcode.class) != null) {
                 assert opcodeConstant == null && opcodeOffset == -1 : "Can have only one Opcode definition: " + field.getType();
                 opcodeOffset = offset;
             }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Fri Jun 07 14:15:38 2013 +0200
@@ -31,7 +31,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.LIRInstruction.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.nodes.cfg.*;
 
 public final class LIRVerifier {
@@ -230,14 +232,17 @@
         return value;
     }
 
+    // @formatter:off
     private static Value allowed(Object op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if ((isVariable(value) && flags.contains(OperandFlag.REG)) || (isRegister(value) && flags.contains(OperandFlag.REG)) || (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
-                        (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
+        if ((isVariable(value) && flags.contains(OperandFlag.REG)) ||
+            (isRegister(value) && flags.contains(OperandFlag.REG)) ||
+            (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
+            (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
+            (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
             return value;
         }
-        TTY.println("instruction %s", op);
-        TTY.println("mode: %s  flags: %s", mode, flags);
-        TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value);
-        throw GraalInternalError.shouldNotReachHere();
+        throw new GraalInternalError("Invalid LIR%n  Instruction: %s%n  Mode: %s%n  Flags: %s%n  Unexpected value: %s %s",
+                        op, mode, flags, value.getClass().getSimpleName(), value);
     }
+    // @formatter:on
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Opcode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import java.lang.annotation.*;
+
+/**
+ * Denotes an opcode name for an annotated {@link LIRInstruction}.
+ * <p>
+ * Note: Unlike the other LIR related annotations declared as inner classes of
+ * {@link LIRInstruction}, this annotation is in a top level file to work around a <a
+ * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=409824">bug</a> in Eclipse causing spurious
+ * warnings about unused imports.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})
+public @interface Opcode {
+
+    String value() default "";
+}
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.loop;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
 
 public abstract class LoopPolicies {
 
@@ -39,7 +40,7 @@
     public static boolean shouldPeel(LoopEx loop, NodesToDoubles probabilities) {
         LoopBeginNode loopBegin = loop.loopBegin();
         double entryProbability = probabilities.get(loopBegin.forwardEnd());
-        return entryProbability > GraalOptions.MinimumPeelProbability && loop.size() + loopBegin.graph().getNodeCount() < GraalOptions.MaximumDesiredSize;
+        return entryProbability > MinimumPeelProbability.getValue() && loop.size() + loopBegin.graph().getNodeCount() < MaximumDesiredSize.getValue();
     }
 
     public static boolean shouldFullUnroll(LoopEx loop) {
@@ -48,14 +49,14 @@
         }
         CountedLoopInfo counted = loop.counted();
         long exactTrips = counted.constantMaxTripCount();
-        int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? GraalOptions.ExactFullUnrollMaxNodes : GraalOptions.FullUnrollMaxNodes;
-        maxNodes = Math.min(maxNodes, GraalOptions.MaximumDesiredSize - loop.loopBegin().graph().getNodeCount());
+        int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? ExactFullUnrollMaxNodes.getValue() : FullUnrollMaxNodes.getValue();
+        maxNodes = Math.min(maxNodes, MaximumDesiredSize.getValue() - loop.loopBegin().graph().getNodeCount());
         int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
         return size * exactTrips <= maxNodes;
     }
 
     public static boolean shouldTryUnswitch(LoopEx loop) {
-        return loop.loopBegin().unswitches() <= GraalOptions.LoopMaxUnswitch;
+        return loop.loopBegin().unswitches() <= LoopMaxUnswitch.getValue();
     }
 
     public static boolean shouldUnswitch(LoopEx loop, ControlSplitNode controlSplit) {
@@ -77,7 +78,7 @@
         }
         int netDiff = loopTotal - (inBranchTotal);
         double uncertainty = 1 - maxProbability;
-        int maxDiff = GraalOptions.LoopUnswitchMaxIncrease + (int) (GraalOptions.LoopUnswitchUncertaintyBoost * loop.loopBegin().loopFrequency() * uncertainty);
+        int maxDiff = LoopUnswitchMaxIncrease.getValue() + (int) (LoopUnswitchUncertaintyBoost.getValue() * loop.loopBegin().loopFrequency() * uncertainty);
         Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of branches", loop, controlSplit, netDiff, maxDiff, (double) (inBranchTotal) / loopTotal * 100);
         return netDiff <= maxDiff;
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.loop;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -29,12 +31,11 @@
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 
 public abstract class LoopTransformations {
 
-    private static final int UNROLL_LIMIT = GraalOptions.FullUnrollMaxNodes * 2;
+    private static final int UNROLL_LIMIT = FullUnrollMaxNodes.getValue() * 2;
 
     private LoopTransformations() {
         // does not need to be instantiated
@@ -52,7 +53,7 @@
         loop.inside().duplicate().insertBefore(loop);
     }
 
-    public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime, Assumptions assumptions) {
+    public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) {
         // assert loop.isCounted(); //TODO (gd) strenghten : counted with known trip count
         int iterations = 0;
         LoopBeginNode loopBegin = loop.loopBegin();
@@ -60,8 +61,8 @@
         while (!loopBegin.isDeleted()) {
             int mark = graph.getMark();
             peel(loop);
-            new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph);
-            if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) {
+            new CanonicalizerPhase.Instance(runtime, assumptions, canonicalizeReads, mark, null).apply(graph);
+            if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > MaximumDesiredSize.getValue() * 3) {
                 throw new BailoutException("FullUnroll : Graph seems to grow out of proportion");
             }
         }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -31,8 +31,10 @@
 public class LoopFullUnrollPhase extends BasePhase<HighTierContext> {
 
     private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls");
+    private final boolean canonicalizeReads;
 
-    public LoopFullUnrollPhase() {
+    public LoopFullUnrollPhase(boolean canonicalizeReads) {
+        this.canonicalizeReads = canonicalizeReads;
     }
 
     @Override
@@ -46,7 +48,7 @@
                 for (LoopEx loop : dataCounted.countedLoops()) {
                     if (LoopPolicies.shouldFullUnroll(loop)) {
                         Debug.log("FullUnroll %s", loop);
-                        LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions());
+                        LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions(), canonicalizeReads);
                         FULLY_UNROLLED_LOOPS.increment();
                         Debug.dump(graph, "After fullUnroll %s", loop);
                         peeled = true;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -39,9 +39,15 @@
             loops.detectedCountedLoops();
             for (LoopEx loop : loops.countedLoops()) {
                 if (loop.lirLoop().children.isEmpty() && loop.counted().getKind() == Kind.Int) {
-                    loop.counted().createOverFlowGuard();
+                    boolean hasSafepoint = false;
                     for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) {
-                        loopEnd.disableSafepoint();
+                        hasSafepoint |= loopEnd.canSafepoint();
+                    }
+                    if (hasSafepoint) {
+                        loop.counted().createOverFlowGuard();
+                        for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) {
+                            loopEnd.disableSafepoint();
+                        }
                     }
                 }
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.loop.phases;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
@@ -34,7 +36,7 @@
     @Override
     protected void run(StructuredGraph graph) {
         if (graph.hasLoops()) {
-            if (GraalOptions.LoopPeeling) {
+            if (LoopPeeling.getValue()) {
                 NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply();
                 LoopsData data = new LoopsData(graph);
                 for (LoopEx loop : data.outterFirst()) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.loop.phases;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.loop.*;
@@ -35,7 +37,7 @@
     @Override
     protected void run(StructuredGraph graph) {
         if (graph.hasLoops()) {
-            if (GraalOptions.ReassociateInvariants) {
+            if (ReassociateInvariants.getValue()) {
                 final LoopsData dataReassociate = new LoopsData(graph);
                 Debug.scope("ReassociateInvariants", new Runnable() {
 
@@ -47,7 +49,7 @@
                     }
                 });
             }
-            if (GraalOptions.LoopUnswitch) {
+            if (LoopUnswitch.getValue()) {
                 boolean unswitched;
                 do {
                     unswitched = false;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -83,9 +83,4 @@
     public DeoptimizationReason getDeoptimizationReason() {
         return reason;
     }
-
-    @Override
-    public boolean isCallSiteDeoptimization() {
-        return false;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -42,9 +42,4 @@
         updateUsages(deoptState, f);
         deoptState = f;
     }
-
-    @Override
-    public boolean isCallSiteDeoptimization() {
-        return false;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,29 +25,24 @@
 import com.oracle.graal.api.meta.*;
 
 /**
- * Interface that needs to be implemented by nodes which need deoptimization information.
- * 
+ * Interface implemented by nodes which need deoptimization information.
  */
 public interface DeoptimizingNode {
 
     /**
-     * Returns true if this particular instance needs deoptimization information.
-     * 
-     * @return true if this particular instance needs deoptimization information
+     * Determines if this node needs deoptimization information.
      */
     boolean canDeoptimize();
 
     /**
-     * Returns the deoptimization information associated with this node if any.
-     * 
-     * @return the deoptimization information associated with this node if any.
+     * Gets the deoptimization information associated with this node if any.
      */
     FrameState getDeoptimizationState();
 
     /**
-     * Set the deoptimization information associated with this node.
+     * Sets the deoptimization information associated with this node.
      * 
-     * @param state the FrameState which represents the deoptimization information.
+     * @param state the FrameState which represents the deoptimization information
      */
     void setDeoptimizationState(FrameState state);
 
@@ -59,13 +54,4 @@
      * @return the reason for deoptimization triggered by this node.
      */
     DeoptimizationReason getDeoptimizationReason();
-
-    /**
-     * Returns true if this node needs deoptimization information for stack-walking purposes because
-     * it is a call-site. While most other nodes use deoptimization information representing a state
-     * that happened before them, these nodes use a state that is valid during the call itself.
-     * 
-     * @return true if this node needs deoptimization information for stack-walking purposes.
-     */
-    boolean isCallSiteDeoptimization();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,12 +25,13 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}")
-public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable {
+public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable, GuardingNode {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
@@ -51,7 +52,7 @@
     }
 
     public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
-        super(StampFactory.forVoid());
+        super(StampFactory.dependency());
         this.action = action;
         this.negated = negated;
         this.condition = condition;
@@ -84,6 +85,7 @@
         if (condition instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition;
             if (c.getValue() != negated) {
+                this.replaceAtUsages(BeginNode.prevBegin(this));
                 graph().removeFixed(this);
             } else {
                 FixedNode next = this.next();
@@ -121,4 +123,9 @@
         negated = !negated;
         return this;
     }
+
+    @Override
+    public FixedGuardNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Fri Jun 07 14:15:38 2013 +0200
@@ -41,6 +41,9 @@
 
     protected final int stackSize;
 
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     private boolean rethrowException;
 
     private boolean duringCall;
@@ -160,6 +163,9 @@
         this.outerFrameState = x;
     }
 
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     public boolean rethrowException() {
         return rethrowException;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/HeapAccess.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+/**
+ * A HeapAccess is a node that access the heap and therefore may be subjected to certain rules of
+ * the underlying runtime.
+ */
+public interface HeapAccess {
+
+    /*
+     * The types of write barriers attached to stores.
+     */
+    public enum WriteBarrierType {
+        /*
+         * Primitive stores which do not necessitate write barriers.
+         */
+        NONE,
+        /*
+         * Array object stores which necessitate precise write barriers.
+         */
+        PRECISE,
+        /*
+         * Field object stores which necessitate imprecise write barriers.
+         */
+        IMPRECISE
+    }
+
+    /**
+     * Gets the write barrier type for that particular access.
+     */
+    WriteBarrierType getWriteBarrierType();
+
+    /**
+     * Returns whether or not the heap access is a compressed pointer candidate.
+     */
+    boolean compress();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,13 +22,15 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.Stamp;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -47,11 +49,22 @@
     /**
      * Constructs a new Invoke instruction.
      * 
+     * @param callTarget the target method being called
      * @param bci the bytecode index of the original invoke (used for debug infos)
-     * @param callTarget the target method being called
      */
     public InvokeNode(CallTargetNode callTarget, int bci) {
-        super(callTarget.returnStamp());
+        this(callTarget, bci, callTarget.returnStamp());
+    }
+
+    /**
+     * Constructs a new Invoke instruction.
+     * 
+     * @param callTarget the target method being called
+     * @param bci the bytecode index of the original invoke (used for debug infos)
+     * @param stamp the stamp to be used for this value
+     */
+    public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) {
+        super(stamp);
         this.callTarget = callTarget;
         this.bci = bci;
         this.polymorphic = false;
@@ -93,7 +106,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
@@ -188,11 +201,6 @@
     }
 
     @Override
-    public boolean isCallSiteDeoptimization() {
-        return true;
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
@@ -154,7 +155,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     public FrameState stateDuring() {
@@ -237,11 +238,6 @@
     }
 
     @Override
-    public boolean isCallSiteDeoptimization() {
-        return true;
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -199,6 +199,7 @@
 
     public void addInput(ValueNode x) {
         assert !(x instanceof PhiNode) || ((PhiNode) x).merge() instanceof LoopBeginNode || ((PhiNode) x).merge() != this.merge();
+        assert x.kind() == kind() || type != PhiType.Value;
         values.add(x);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -61,12 +61,6 @@
 
     @Override
     public boolean inferStamp() {
-        if (stamp() instanceof ObjectStamp && object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            // a null value flowing into a nonNull PiNode should be guarded by a type/isNull guard,
-            // but the
-            // compiler might see this situation before the branch is deleted
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 
 /**
  * The start node of a graph.
@@ -32,6 +34,6 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -60,7 +60,7 @@
      * @return true if the stamp has changed, false otherwise.
      */
     protected final boolean updateStamp(Stamp newStamp) {
-        if (newStamp.equals(stamp)) {
+        if (newStamp == null || newStamp.equals(stamp)) {
             return false;
         } else {
             stamp = newStamp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Fri Jun 07 14:15:38 2013 +0200
@@ -72,10 +72,6 @@
         assert x == null;
     }
 
-    public static boolean typeMismatch(ValueNode x, ValueNode y) {
-        return y == null || x == null || x.kind() != y.kind();
-    }
-
     @SuppressWarnings("unchecked")
     public static <T extends Node> Collection<T> filter(Iterable<Node> nodes, Class<T> clazz) {
         ArrayList<T> phis = new ArrayList<>();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Fri Jun 07 14:15:38 2013 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.nodes.*;
 
-public interface Access extends DeoptimizingNode, GuardedNode {
+public interface Access extends DeoptimizingNode, GuardedNode, HeapAccess {
 
     ValueNode object();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -37,6 +37,8 @@
     @Input private ValueNode object;
     @Input private ValueNode location;
     private boolean nullCheck;
+    private WriteBarrierType barrierType;
+    private boolean compress;
 
     public ValueNode object() {
         return object;
@@ -59,14 +61,20 @@
     }
 
     public AccessNode(ValueNode object, ValueNode location, Stamp stamp) {
-        this(object, location, stamp, null);
+        this(object, location, stamp, null, WriteBarrierType.NONE, false);
     }
 
-    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard) {
+    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
+        this(object, location, stamp, null, barrierType, compress);
+    }
+
+    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
         super(stamp);
         this.object = object;
         this.location = location;
         this.guard = guard;
+        this.barrierType = barrierType;
+        this.compress = compress;
     }
 
     @Override
@@ -94,4 +102,14 @@
         updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode());
         this.guard = guard;
     }
+
+    @Override
+    public WriteBarrierType getWriteBarrierType() {
+        return barrierType;
+    }
+
+    @Override
+    public boolean compress() {
+        return compress;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -34,8 +34,12 @@
         super(object, location, stamp);
     }
 
-    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard) {
-        super(object, location, stamp, guard);
+    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, guard, barrierType, compress);
+    }
+
+    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, barrierType, compress);
     }
 
     public abstract FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -32,6 +32,8 @@
     @Input private LocationNode location;
     @Input private FrameState deoptState;
     private boolean nullCheck;
+    private WriteBarrierType barrierType;
+    private boolean compress;
 
     public ValueNode object() {
         return object;
@@ -59,10 +61,12 @@
         this.location = location;
     }
 
-    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard) {
+    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
         super(stamp, guard);
         this.object = object;
         this.location = location;
+        this.barrierType = barrierType;
+        this.compress = compress;
     }
 
     @Override
@@ -92,8 +96,13 @@
     }
 
     @Override
-    public boolean isCallSiteDeoptimization() {
-        return false;
+    public WriteBarrierType getWriteBarrierType() {
+        return barrierType;
+    }
+
+    @Override
+    public boolean compress() {
+        return compress;
     }
 
     public abstract Access asFixedNode();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -37,11 +37,11 @@
     @Input private Node lastLocationAccess;
 
     public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp) {
-        this(object, location, lastLocationAccess, stamp, null);
+        this(object, location, lastLocationAccess, stamp, null, WriteBarrierType.NONE, false);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard) {
-        super(object, location, stamp, guard);
+    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, guard, barrierType, compress);
         this.lastLocationAccess = lastLocationAccess;
     }
 
@@ -62,6 +62,6 @@
 
     @Override
     public Access asFixedNode() {
-        return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard()));
+        return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard(), getWriteBarrierType(), compress()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,7 +26,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -34,22 +33,31 @@
  * Node for a {@linkplain ForeignCallDescriptor foreign} call.
  */
 @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}")
-public class ForeignCallNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint {
+public class ForeignCallNode extends AbstractStateSplit implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint {
 
     @Input private final NodeInputList<ValueNode> arguments;
+    private final MetaAccessProvider runtime;
+    @Input private FrameState deoptState;
 
     private final ForeignCallDescriptor descriptor;
 
-    public ForeignCallNode(ForeignCallDescriptor descriptor, ValueNode... arguments) {
+    public ForeignCallNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, ValueNode... arguments) {
         super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())));
         this.arguments = new NodeInputList<>(this, arguments);
         this.descriptor = descriptor;
+        this.runtime = runtime;
     }
 
-    protected ForeignCallNode(ForeignCallDescriptor descriptor, Stamp stamp) {
+    protected ForeignCallNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, Stamp stamp) {
         super(stamp);
         this.arguments = new NodeInputList<>(this);
         this.descriptor = descriptor;
+        this.runtime = runtime;
+    }
+
+    @Override
+    public boolean hasSideEffect() {
+        return !runtime.isReexecutable(descriptor);
     }
 
     public ForeignCallDescriptor getDescriptor() {
@@ -58,7 +66,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return runtime.getKilledLocations(descriptor);
     }
 
     protected Value[] operands(LIRGeneratorTool gen) {
@@ -80,6 +88,30 @@
     }
 
     @Override
+    public FrameState getDeoptimizationState() {
+        if (deoptState != null) {
+            return deoptState;
+        } else if (stateAfter() != null && canDeoptimize()) {
+            FrameState stateDuring = stateAfter();
+            if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
+                stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind());
+            }
+            setDeoptimizationState(stateDuring);
+            return stateDuring;
+        }
+        return null;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
+        if (deoptState != null) {
+            throw new IllegalStateException(toString(Verbosity.Debugger));
+        }
+        deoptState = f;
+    }
+
+    @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
             return super.toString(verbosity) + "#" + descriptor;
@@ -89,7 +121,7 @@
 
     @Override
     public boolean canDeoptimize() {
-        return true;
+        return runtime.canDeoptimize(descriptor);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallStateSplitNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +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.nodes.extended;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * A foreign call that is also a state split.
- */
-@NodeInfo(nameTemplate = "ForeignCallStateSplit#{p#descriptor/s}")
-public class ForeignCallStateSplitNode extends ForeignCallNode implements LIRLowerable, StateSplit, DeoptimizingNode {
-
-    @Input(notDataflow = true) private FrameState stateAfter;
-    private MetaAccessProvider runtime;
-
-    public ForeignCallStateSplitNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, ValueNode... arguments) {
-        super(descriptor, arguments);
-        this.runtime = runtime;
-    }
-
-    public FrameState stateAfter() {
-        return stateAfter;
-    }
-
-    public void setStateAfter(FrameState x) {
-        assert x == null || x.isAlive() : "frame state must be in a graph";
-        updateUsages(stateAfter, x);
-        stateAfter = x;
-    }
-
-    public boolean hasSideEffect() {
-        return runtime.hasSideEffect(getDescriptor());
-    }
-
-    @Override
-    public FrameState getDeoptimizationState() {
-        if (super.getDeoptimizationState() != null) {
-            return super.getDeoptimizationState();
-        } else if (stateAfter() != null) {
-            FrameState stateDuring = stateAfter();
-            if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
-                stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind());
-            }
-            setDeoptimizationState(stateDuring);
-            return stateDuring;
-        }
-        return null;
-    }
-
-    @Override
-    public void setDeoptimizationState(FrameState f) {
-        if (super.getDeoptimizationState() != null) {
-            throw new IllegalStateException();
-        }
-        super.setDeoptimizationState(f);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.nodes.calc.*;
@@ -38,61 +36,6 @@
 public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable {
 
     /**
-     * Marker interface for location identities. Apart from the special values {@link #ANY_LOCATION}
-     * and {@link #FINAL_LOCATION}, a different location identity of two memory accesses guarantees
-     * that the two accesses do not interfere.
-     */
-    public interface LocationIdentity {
-    }
-
-    /**
-     * Denotes any location. A write to such a location kills all values in a memory map during an
-     * analysis of memory accesses in a graph. A read from this location cannot be moved or
-     * coalesced with other reads because its interaction with other reads is not known.
-     */
-    public static final LocationIdentity ANY_LOCATION = createLocation("ANY_LOCATION");
-
-    /**
-     * Denotes the location of a value that is guaranteed to be final.
-     */
-    public static final LocationIdentity FINAL_LOCATION = createLocation("FINAL_LOCATION");
-
-    /**
-     * Creates a new unique location identity for read and write operations.
-     * 
-     * @param name the name of the new location identity, for debugging purposes
-     * @return the new location identity
-     */
-    public static LocationIdentity createLocation(final String name) {
-        return new LocationIdentity() {
-
-            @Override
-            public String toString() {
-                return name;
-            }
-        };
-    }
-
-    /**
-     * Returns the location identity for an array of the given element kind. Array accesses of the
-     * same kind must have the same location identity unless an alias analysis guarantees that two
-     * distinct arrays are accessed.
-     */
-    public static LocationIdentity getArrayLocation(Kind elementKind) {
-        return ARRAY_LOCATIONS.get(elementKind);
-    }
-
-    private static final EnumMap<Kind, LocationIdentity> ARRAY_LOCATIONS = initArrayLocations();
-
-    private static EnumMap<Kind, LocationIdentity> initArrayLocations() {
-        EnumMap<Kind, LocationIdentity> result = new EnumMap<>(Kind.class);
-        for (Kind kind : Kind.values()) {
-            result.put(kind, createLocation("Array: " + kind.getJavaName()));
-        }
-        return result;
-    }
-
-    /**
      * Marker interface for locations in snippets.
      */
     public interface Location {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import java.lang.reflect.*;
@@ -29,9 +30,9 @@
 import sun.misc.*;
 
 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.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -52,7 +53,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 
 /**
  * This interface marks subclasses of {@link FixedNode} that kill a set of memory locations
@@ -34,7 +34,7 @@
 
     /**
      * This method is used to determine which set of memory locations is killed by this node.
-     * Returning the special value {@link LocationNode#ANY_LOCATION} will kill all memory locations.
+     * Returning the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory locations.
      * 
      * @return the identities of all locations killed by this node.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -30,9 +30,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     public NodeIterable<OSRLocalNode> getOSRLocals() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,33 +25,33 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Reads an {@linkplain AccessNode accessed} value.
  */
-public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable {
+public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable, Virtualizable {
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp) {
-        super(object, location, stamp);
+    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, barrierType, compress);
     }
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard) {
-        super(object, location, stamp, guard);
+    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, guard, barrierType, compress);
     }
 
     private ReadNode(ValueNode object, int displacement, LocationIdentity locationIdentity, Kind kind) {
         super(object, ConstantLocationNode.create(locationIdentity, kind, displacement, object.graph()), StampFactory.forKind(kind));
     }
 
-    private ReadNode(ValueNode object, ValueNode location, GuardingNode guard) {
+    private ReadNode(ValueNode object, ValueNode location, ValueNode guard) {
         /*
          * Used by node intrinsics. Since the initial value for location is a parameter, i.e., a
          * LocalNode, the constructor cannot use the declared type LocationNode.
          */
-        super(object, location, StampFactory.forNodeIntrinsic(), guard);
+        super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, WriteBarrierType.NONE, false);
     }
 
     @Override
@@ -67,7 +67,7 @@
 
     @Override
     public FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess) {
-        return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard()));
+        return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getWriteBarrierType(), compress()));
     }
 
     public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool) {
@@ -76,8 +76,8 @@
             // Read without usages can be savely removed.
             return null;
         }
-        if (runtime != null && object != null && object.isConstant()) {
-            if (location.getLocationIdentity() == LocationNode.FINAL_LOCATION && location instanceof ConstantLocationNode) {
+        if (tool.canonicalizeReads() && runtime != null && object != null && object.isConstant()) {
+            if (location.getLocationIdentity() == LocationIdentity.FINAL_LOCATION && location instanceof ConstantLocationNode) {
                 long displacement = ((ConstantLocationNode) location).getDisplacement();
                 Kind kind = location.getValueKind();
                 if (object.kind() == Kind.Object) {
@@ -129,6 +129,21 @@
         return false;
     }
 
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (location() instanceof ConstantLocationNode) {
+            ConstantLocationNode constantLocation = (ConstantLocationNode) location();
+            State state = tool.getObjectState(object());
+            if (state != null && state.getState() == EscapeState.Virtual) {
+                VirtualObjectNode virtual = state.getVirtualObject();
+                int entryIndex = virtual.entryIndexForOffset(constantLocation.getDisplacement());
+                if (entryIndex != -1 && virtual.entryKind(entryIndex) == constantLocation.getValueKind()) {
+                    tool.replaceWith(state.getEntry(entryIndex));
+                }
+            }
+        }
+    }
+
     /**
      * Reads a value from memory.
      * 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -74,7 +76,7 @@
             return (LocationIdentity) locationIdentity.asConstant().asObject();
         }
         // We do not know our actual location identity yet, so be conservative.
-        return LocationNode.ANY_LOCATION;
+        return ANY_LOCATION;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -52,12 +52,6 @@
         if (stamp() == StampFactory.forNodeIntrinsic()) {
             return false;
         }
-        if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull
-            // guard, but the
-            // compiler might see this situation before the branch is deleted
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -83,8 +83,8 @@
                                                                   // UnsafeAccess only have an
                                                                   // object base
                 ObjectStamp receiverStamp = object().objectStamp();
-                if (receiverStamp.nonNull()) {
-                    ResolvedJavaType receiverType = receiverStamp.type();
+                ResolvedJavaType receiverType = receiverStamp.type();
+                if (receiverStamp.nonNull() && receiverType != null) {
                     ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement());
                     if (field != null) {
                         return this.graph().add(new LoadFieldNode(object(), field));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -76,7 +76,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -61,6 +61,10 @@
         }
     }
 
+    public void removeAnchoredNode(ValueNode value) {
+        this.anchored.remove(value);
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (permanent) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -39,7 +41,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,37 +26,19 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.LocationNode.Location;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
  */
-public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint, Node.IterableNodeType {
+public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint, Node.IterableNodeType, Virtualizable {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
     private final WriteBarrierType barrierType;
 
-    /*
-     * The types of write barriers attached to stores.
-     */
-    public enum WriteBarrierType {
-        /*
-         * Primitive stores which do not necessitate write barriers.
-         */
-        NONE,
-        /*
-         * Array object stores which necessitate precise write barriers.
-         */
-        PRECISE,
-        /*
-         * Field object stores which necessitate imprecise write barriers.
-         */
-        IMPRECISE
-    }
-
     public FrameState stateAfter() {
         return stateAfter;
     }
@@ -75,12 +57,8 @@
         return value;
     }
 
-    public WriteBarrierType getWriteBarrierType() {
-        return barrierType;
-    }
-
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType) {
-        super(object, location, StampFactory.forVoid());
+    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, StampFactory.forVoid(), barrierType, compress);
         this.value = value;
         this.barrierType = barrierType;
     }
@@ -92,10 +70,26 @@
     }
 
     @NodeIntrinsic
-    public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter WriteBarrierType barrierType);
+    public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter WriteBarrierType barrierType, @ConstantNodeParameter boolean compress);
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
         return new LocationIdentity[]{location().getLocationIdentity()};
     }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (location() instanceof ConstantLocationNode) {
+            ConstantLocationNode constantLocation = (ConstantLocationNode) location();
+            State state = tool.getObjectState(object());
+            if (state != null && state.getState() == EscapeState.Virtual) {
+                VirtualObjectNode virtual = state.getVirtualObject();
+                int entryIndex = virtual.entryIndexForOffset(constantLocation.getDisplacement());
+                if (entryIndex != -1 && virtual.entryKind(entryIndex) == constantLocation.getValueKind()) {
+                    tool.setVirtualEntry(state, entryIndex, value());
+                    tool.delete();
+                }
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -69,9 +69,6 @@
 
     @Override
     public boolean inferStamp() {
-        if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
-            return false;
-        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,14 +22,13 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -37,7 +36,7 @@
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
  * value matched the expected value.
  */
-public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint, Node.IterableNodeType {
+public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint, Node.IterableNodeType, HeapAccess {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
@@ -46,6 +45,7 @@
     @Input private LocationNode location;
     private final int displacement;
     private WriteBarrierType barrierType;
+    private boolean compress;
 
     public ValueNode object() {
         return object;
@@ -76,6 +76,7 @@
         this.location = location;
     }
 
+    @Override
     public WriteBarrierType getWriteBarrierType() {
         return barrierType;
     }
@@ -84,6 +85,15 @@
         this.barrierType = type;
     }
 
+    @Override
+    public boolean compress() {
+        return compress;
+    }
+
+    public void setCompress() {
+        this.compress = true;
+    }
+
     public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
         super(StampFactory.forKind(Kind.Boolean.getStackKind()));
         assert expected.kind() == newValue.kind();
@@ -93,11 +103,12 @@
         this.newValue = newValue;
         this.displacement = displacement;
         this.barrierType = WriteBarrierType.NONE;
+        this.compress = false;
     }
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -41,7 +42,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -57,7 +57,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
-        if (runtime != null) {
+        if (tool.canonicalizeReads() && runtime != null) {
             Constant constant = null;
             if (isStatic()) {
                 constant = field().readConstantValue(null);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,9 +22,11 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -46,7 +48,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,10 +22,12 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -47,7 +49,7 @@
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
-        return new LocationIdentity[]{LocationNode.ANY_LOCATION};
+        return new LocationIdentity[]{ANY_LOCATION};
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -100,9 +100,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -78,9 +78,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -63,9 +63,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     public ResolvedJavaType type() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -106,11 +106,6 @@
         return null;
     }
 
-    @Override
-    public boolean isCallSiteDeoptimization() {
-        return false;
-    }
-
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void register(Object thisObj) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -74,7 +74,7 @@
             int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1;
             if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) {
                 ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType();
-                if (componentType.isPrimitive() || value.objectStamp().alwaysNull() || componentType.isAssignableFrom(value.objectStamp().type())) {
+                if (componentType.isPrimitive() || value.objectStamp().alwaysNull() || (value.objectStamp().type() != null && componentType.isAssignableFrom(value.objectStamp().type()))) {
                     tool.setVirtualEntry(arrayState, index, value());
                     tool.delete();
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java	Fri Jun 07 14:15:38 2013 +0200
@@ -32,5 +32,7 @@
 
     MetaAccessProvider runtime();
 
+    boolean canonicalizeReads();
+
     void removeIfUnused(Node node);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Fri Jun 07 14:15:38 2013 +0200
@@ -28,11 +28,14 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 
 public interface LoweringTool {
 
     GraalCodeCacheProvider getRuntime();
 
+    LoweringType getLoweringType();
+
     Replacements getReplacements();
 
     GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.type;
 
+import java.lang.reflect.*;
+
 import com.oracle.graal.api.meta.*;
 
 public class ObjectStamp extends Stamp {
@@ -33,14 +35,29 @@
 
     public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
         super(Kind.Object);
-        assert !exactType || type != null;
-        assert !(nonNull && alwaysNull);
+        assert isValid(type, exactType, nonNull, alwaysNull);
         this.type = type;
         this.exactType = exactType;
         this.nonNull = nonNull;
         this.alwaysNull = alwaysNull;
     }
 
+    public static boolean isValid(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
+        if (exactType && type == null) {
+            return false;
+        }
+
+        if (exactType && Modifier.isAbstract(type.getModifiers()) && !type.isArray()) {
+            return false;
+        }
+
+        if (nonNull && alwaysNull) {
+            return false;
+        }
+
+        return true;
+    }
+
     @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
         if (type != null) {
@@ -152,12 +169,19 @@
                 joinType = type;
             }
         }
+
         if (joinType == type && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) {
             return this;
         } else if (joinType == other.type && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) {
             return other;
         } else {
-            return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
+            if (isValid(joinType, joinExactType, joinNonNull, joinAlwaysNull)) {
+                return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull);
+            } else {
+                // This situation can happen in case the compiler wants to join two contradicting
+                // stamps.
+                return null;
+            }
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -66,9 +66,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/META-INF/services/javax.annotation.processing.Processor	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,1 @@
+com.oracle.graal.options.OptionProcessor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/Option.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+import java.lang.annotation.*;
+
+/**
+ * Describes the attributes of an option whose {@link OptionValue value} is in a static field
+ * annotated by this annotation type.
+ * 
+ * @see OptionProcessor
+ * @see OptionDescriptor
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.FIELD)
+public @interface Option {
+
+    /**
+     * Gets a help message for the option.
+     */
+    String help();
+
+    /**
+     * The name of the option. By default, the name of the annotated field should be used.
+     */
+    String name() default "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+/**
+ * Describes the attributes of a static field {@linkplain Option option} and provides access to its
+ * {@linkplain OptionValue value}.
+ */
+public class OptionDescriptor {
+
+    protected final String name;
+    protected final Class type;
+    protected final String help;
+    protected final OptionValue<?> option;
+    protected final String location;
+
+    public OptionDescriptor(String name, Class type, String help, String location, OptionValue<?> option) {
+        this.name = name;
+        this.type = type;
+        this.help = help;
+        this.option = option;
+        this.location = location;
+    }
+
+    /**
+     * Gets the type of values stored in the option.
+     */
+    public Class getType() {
+        return type;
+    }
+
+    /**
+     * Gets a descriptive help message for the option.
+     */
+    public String getHelp() {
+        return help;
+    }
+
+    /**
+     * Gets the name of the option. It's up to the client of this object how to use the name to get
+     * a user specified value for the option from the environment.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the boxed option value.
+     */
+    public OptionValue<?> getOptionValue() {
+        return option;
+    }
+
+    /**
+     * Gets a description of the location where this option is stored.
+     */
+    public String getLocation() {
+        return location;
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.*;
+
+/**
+ * Processes static fields annotated with {@link Option}. An {@link Options} service is generated
+ * for each top level class containing at least one such field. These service objects can be
+ * retrieved as follows:
+ * 
+ * <pre>
+ * ServiceLoader&lt;Options&gt; sl = ServiceLoader.loadInstalled(Options.class);
+ * for (OptionDescriptor desc : sl) {
+ *     // use desc
+ * }
+ * </pre>
+ */
+@SupportedSourceVersion(SourceVersion.RELEASE_7)
+@SupportedAnnotationTypes({"com.oracle.graal.options.Option"})
+public class OptionProcessor extends AbstractProcessor {
+
+    private final Set<Element> processed = new HashSet<>();
+
+    private void processElement(Element element, OptionsInfo info) {
+
+        if (!element.getModifiers().contains(Modifier.STATIC)) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
+            return;
+        }
+
+        Option annotation = element.getAnnotation(Option.class);
+        assert annotation != null;
+        assert element instanceof VariableElement;
+        assert element.getKind() == ElementKind.FIELD;
+        VariableElement field = (VariableElement) element;
+        String fieldName = field.getSimpleName().toString();
+
+        Elements elements = processingEnv.getElementUtils();
+        Types types = processingEnv.getTypeUtils();
+
+        TypeMirror fieldType = field.asType();
+        if (fieldType.getKind() != TypeKind.DECLARED) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + OptionValue.class.getName(), element);
+            return;
+        }
+        DeclaredType declaredFieldType = (DeclaredType) fieldType;
+
+        TypeMirror optionValueType = elements.getTypeElement(OptionValue.class.getName()).asType();
+        if (!types.isSubtype(fieldType, types.erasure(optionValueType))) {
+            String msg = String.format("Option field type %s is not a subclass of %s", fieldType, optionValueType);
+            processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
+            return;
+        }
+
+        if (!field.getModifiers().contains(Modifier.STATIC)) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
+            return;
+        }
+
+        String optionName = annotation.name();
+        if (optionName.equals("")) {
+            optionName = fieldName;
+        }
+
+        String optionType = declaredFieldType.getTypeArguments().get(0).toString();
+        if (optionType.startsWith("java.lang.")) {
+            optionType = optionType.substring("java.lang.".length());
+        }
+
+        Element enclosing = element.getEnclosingElement();
+        String declaringClass = "";
+        String separator = "";
+        Set<Element> originatingElementsList = info.originatingElements;
+        originatingElementsList.add(field);
+        while (enclosing != null) {
+            if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) {
+                if (enclosing.getModifiers().contains(Modifier.PRIVATE)) {
+                    String msg = String.format("Option field cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing);
+                    processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
+                    return;
+                }
+                originatingElementsList.add(enclosing);
+                declaringClass = enclosing.getSimpleName() + separator + declaringClass;
+                separator = ".";
+            } else {
+                assert enclosing.getKind() == ElementKind.PACKAGE;
+            }
+            enclosing = enclosing.getEnclosingElement();
+        }
+
+        info.options.add(new OptionInfo(optionName, annotation.help(), optionType, declaringClass, field));
+    }
+
+    private void createFiles(OptionsInfo info) {
+        String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString();
+        Name declaringClass = info.topDeclaringType.getSimpleName();
+
+        String optionsClassName = declaringClass + "_" + Options.class.getSimpleName();
+        Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]);
+
+        Filer filer = processingEnv.getFiler();
+        try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) {
+
+            out.println("// CheckStyle: stop header check");
+            out.println("// GENERATED CONTENT - DO NOT EDIT");
+            out.println("// Source: " + declaringClass + ".java");
+            out.println("package " + pkg + ";");
+            out.println("");
+            out.println("import java.util.*;");
+            out.println("import " + Options.class.getPackage().getName() + ".*;");
+            out.println("");
+            out.println("public class " + optionsClassName + " implements " + Options.class.getSimpleName() + " {");
+            out.println("    @Override");
+            out.println("    public Iterator<" + OptionDescriptor.class.getSimpleName() + "> iterator() {");
+            out.println("        List<" + OptionDescriptor.class.getSimpleName() + "> options = Arrays.asList(");
+
+            boolean needPrivateFieldAccessor = false;
+            int i = 0;
+            for (OptionInfo option : info.options) {
+                String optionValue;
+                if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
+                    needPrivateFieldAccessor = true;
+                    optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")";
+                } else {
+                    optionValue = option.declaringClass + "." + option.field.getSimpleName();
+                }
+                String name = option.name;
+                String type = option.type;
+                String help = option.help;
+                String location = pkg + "." + option.declaringClass + "." + option.field.getSimpleName();
+                String comma = i == info.options.size() - 1 ? "" : ",";
+                out.printf("            new %s(\"%s\", %s.class, \"%s\", \"%s\", %s)%s%n", OptionDescriptor.class.getSimpleName(), name, type, help, location, optionValue, comma);
+                i++;
+            }
+            out.println("        );");
+            out.println("        return options.iterator();");
+            out.println("    }");
+            if (needPrivateFieldAccessor) {
+                out.println("    private static " + OptionValue.class.getSimpleName() + " field(Class<?> declaringClass, String fieldName) {");
+                out.println("        try {");
+                out.println("            java.lang.reflect.Field field = declaringClass.getDeclaredField(fieldName);");
+                out.println("            field.setAccessible(true);");
+                out.println("            return (" + OptionValue.class.getSimpleName() + ") field.get(null);");
+                out.println("        } catch (Exception e) {");
+                out.println("            throw (InternalError) new InternalError().initCause(e);");
+                out.println("        }");
+                out.println("    }");
+            }
+            out.println("}");
+        }
+
+        try {
+            createProviderFile(pkg, optionsClassName, originatingElements);
+        } catch (IOException e) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType);
+        }
+    }
+
+    private void createProviderFile(String pkg, String providerClassName, Element... originatingElements) throws IOException {
+        String filename = "META-INF/providers/" + pkg + "." + providerClassName;
+        FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements);
+        PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"));
+        writer.println(Options.class.getName());
+        writer.close();
+    }
+
+    protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) {
+        try {
+            // Ensure Unix line endings to comply with Graal code style guide checked by Checkstyle
+            JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, originatingElements);
+            return new PrintWriter(sourceFile.openWriter()) {
+
+                @Override
+                public void println() {
+                    print("\n");
+                }
+            };
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static class OptionInfo {
+
+        final String name;
+        final String help;
+        final String type;
+        final String declaringClass;
+        final VariableElement field;
+
+        public OptionInfo(String name, String help, String type, String declaringClass, VariableElement field) {
+            this.name = name;
+            this.help = help;
+            this.type = type;
+            this.declaringClass = declaringClass;
+            this.field = field;
+        }
+
+        @Override
+        public String toString() {
+            return declaringClass + "." + field;
+        }
+    }
+
+    static class OptionsInfo {
+
+        final Element topDeclaringType;
+        final List<OptionInfo> options = new ArrayList<>();
+        final Set<Element> originatingElements = new HashSet<>();
+
+        public OptionsInfo(Element topDeclaringType) {
+            this.topDeclaringType = topDeclaringType;
+        }
+    }
+
+    private static Element topDeclaringType(Element element) {
+        Element enclosing = element.getEnclosingElement();
+        if (element == null || enclosing.getKind() == ElementKind.PACKAGE) {
+            assert element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE;
+            return element;
+        }
+        return topDeclaringType(enclosing);
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver()) {
+            return true;
+        }
+
+        Map<Element, OptionsInfo> map = new HashMap<>();
+        for (Element element : roundEnv.getElementsAnnotatedWith(Option.class)) {
+            if (!processed.contains(element)) {
+                processed.add(element);
+                Element topDeclaringType = topDeclaringType(element);
+                OptionsInfo options = map.get(topDeclaringType);
+                if (options == null) {
+                    options = new OptionsInfo(topDeclaringType);
+                    map.put(topDeclaringType, options);
+                }
+                processElement(element, options);
+            }
+        }
+
+        boolean ok = true;
+        Map<String, OptionInfo> uniqueness = new HashMap<>();
+        for (OptionsInfo info : map.values()) {
+            for (OptionInfo option : info.options) {
+                OptionInfo conflict = uniqueness.put(option.name, option);
+                if (conflict != null) {
+                    processingEnv.getMessager().printMessage(Kind.ERROR, "Duplicate option names for " + option + " and " + conflict, option.field);
+                    ok = false;
+                }
+            }
+        }
+
+        if (ok) {
+            for (OptionsInfo info : map.values()) {
+                createFiles(info);
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+/**
+ * An option value.
+ */
+public class OptionValue<T> {
+
+    /**
+     * The raw option value.
+     */
+    protected T value;
+
+    public OptionValue(T value) {
+        this.value = value;
+    }
+
+    private static final Object UNINITIALIZED = "UNINITIALIZED";
+
+    /**
+     * Creates an uninitialized option value for a subclass that initializes itself
+     * {@link #initialValue() lazily}.
+     */
+    @SuppressWarnings("unchecked")
+    protected OptionValue() {
+        this.value = (T) UNINITIALIZED;
+    }
+
+    /**
+     * Lazy initialization of value.
+     */
+    protected T initialValue() {
+        throw new InternalError("Uninitialized option value must override initialValue()");
+    }
+
+    /**
+     * Gets the value of this option.
+     */
+    public T getValue() {
+        if (value == UNINITIALIZED) {
+            value = initialValue();
+        }
+        return value;
+    }
+
+    /**
+     * Sets the value of this option.
+     */
+    @SuppressWarnings("unchecked")
+    public void setValue(Object v) {
+        this.value = (T) v;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/Options.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+import java.util.*;
+
+/**
+ * A {@linkplain ServiceLoader service} for accessing a set of {@link OptionDescriptor}s.
+ */
+public interface Options extends Iterable<OptionDescriptor> {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+/**
+ * An option that always returns the same {@linkplain #getValue() value}.
+ */
+public class StableOptionValue<T> extends OptionValue<T> {
+
+    /**
+     * Creates a stable option value.
+     */
+    public StableOptionValue(T value) {
+        super(value);
+    }
+
+    /**
+     * Used to assert the invariant for stability. Without using locks, this check is not safe
+     * against races and so it's only an assertion.
+     */
+    private boolean getValueCalled;
+
+    /**
+     * Creates an uninitialized stable option value for a subclass that initializes itself
+     * {@link #initialValue() lazily}.
+     */
+    public StableOptionValue() {
+    }
+
+    /**
+     * Gets the value of this option.
+     */
+    @Override
+    public final T getValue() {
+        T result = super.getValue();
+        assert initGetValueCalled();
+        return result;
+    }
+
+    private boolean initGetValueCalled() {
+        getValueCalled = true;
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * This must only be called if {@link #getValue()} has never been called.
+     */
+    @Override
+    public final void setValue(Object v) {
+        assert !getValueCalled;
+        super.setValue(v);
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -47,30 +47,20 @@
     private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes");
     public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
 
-    private final CustomCanonicalizer customCanonicalizer;
-    private final Iterable<Node> workingSet;
+    private final boolean canonicalizeReads;
 
     public interface CustomCanonicalizer {
 
         ValueNode canonicalize(ValueNode node);
     }
 
-    public CanonicalizerPhase() {
-        this(null);
-    }
-
-    public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) {
-        this(customCanonicalizer, null);
-    }
-
-    public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer, Iterable<Node> workingSet) {
-        this.customCanonicalizer = customCanonicalizer;
-        this.workingSet = workingSet;
+    public CanonicalizerPhase(boolean canonicalizeReads) {
+        this.canonicalizeReads = canonicalizeReads;
     }
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
-        new Instance(context.getRuntime(), context.getAssumptions(), workingSet, customCanonicalizer).run(graph);
+        new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads).run(graph);
     }
 
     public static class Instance extends Phase {
@@ -80,12 +70,13 @@
         private final MetaAccessProvider runtime;
         private final CustomCanonicalizer customCanonicalizer;
         private final Iterable<Node> initWorkingSet;
+        private final boolean canonicalizeReads;
 
         private NodeWorkList workList;
         private Tool tool;
 
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions) {
-            this(runtime, assumptions, null, 0, null);
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) {
+            this(runtime, assumptions, canonicalizeReads, null, 0, null);
         }
 
         /**
@@ -95,23 +86,24 @@
          *            should be an auto-grow node bitmap
          * @param customCanonicalizer
          */
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
-            this(runtime, assumptions, workingSet, 0, customCanonicalizer);
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, canonicalizeReads, workingSet, 0, customCanonicalizer);
         }
 
         /**
          * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
          *            this mark are processed otherwise all nodes in the graph are processed
          */
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
-            this(runtime, assumptions, null, newNodesMark, customCanonicalizer);
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, canonicalizeReads, null, newNodesMark, customCanonicalizer);
         }
 
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
             super("Canonicalizer");
             this.newNodesMark = newNodesMark;
             this.assumptions = assumptions;
             this.runtime = runtime;
+            this.canonicalizeReads = canonicalizeReads;
             this.customCanonicalizer = customCanonicalizer;
             this.initWorkingSet = workingSet;
         }
@@ -127,7 +119,7 @@
             if (newNodesMark > 0) {
                 workList.addAll(graph.getNewNodes(newNodesMark));
             }
-            tool = new Tool(workList, runtime, assumptions);
+            tool = new Tool(workList, runtime, assumptions, canonicalizeReads);
             processWorkSet(graph);
         }
 
@@ -211,21 +203,6 @@
 
                     public Boolean call() {
                         ValueNode canonical = ((Canonicalizable) node).canonical(tool);
-// @formatter:off
-//     cases:                                           original node:
-//                                         |Floating|Fixed-unconnected|Fixed-connected|
-//                                         --------------------------------------------
-//                                     null|   1    |        X        |       3       |
-//                                         --------------------------------------------
-//                                 Floating|   2    |        X        |       4       |
-//       canonical node:                   --------------------------------------------
-//                        Fixed-unconnected|   X    |        X        |       5       |
-//                                         --------------------------------------------
-//                          Fixed-connected|   2    |        X        |       6       |
-//                                         --------------------------------------------
-//       X: must not happen (checked with assertions)
-// @formatter:on
-
                         return performReplacement(node, graph, canonical);
                     }
                 });
@@ -242,6 +219,20 @@
             return node.isDeleted();
         }
 
+// @formatter:off
+//     cases:                                           original node:
+//                                         |Floating|Fixed-unconnected|Fixed-connected|
+//                                         --------------------------------------------
+//                                     null|   1    |        X        |       3       |
+//                                         --------------------------------------------
+//                                 Floating|   2    |        X        |       4       |
+//       canonical node:                   --------------------------------------------
+//                        Fixed-unconnected|   X    |        X        |       5       |
+//                                         --------------------------------------------
+//                          Fixed-connected|   2    |        X        |       6       |
+//                                         --------------------------------------------
+//       X: must not happen (checked with assertions)
+// @formatter:on
         private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) {
             if (canonical == node) {
                 Debug.log("Canonicalizer: work on %s", node);
@@ -323,11 +314,13 @@
             private final NodeWorkList nodeWorkSet;
             private final MetaAccessProvider runtime;
             private final Assumptions assumptions;
+            private final boolean canonicalizeReads;
 
-            public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) {
+            public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) {
                 this.nodeWorkSet = nodeWorkSet;
                 this.runtime = runtime;
                 this.assumptions = assumptions;
+                this.canonicalizeReads = canonicalizeReads;
             }
 
             @Override
@@ -359,6 +352,11 @@
             public void removeIfUnused(Node node) {
                 tryKillUnused(node);
             }
+
+            @Override
+            public boolean canonicalizeReads() {
+                return canonicalizeReads;
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,12 +22,14 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.graph.ReentrantNodeIterator.LoopInfo;
@@ -45,7 +47,7 @@
 
         public MemoryMap(StartNode start) {
             this();
-            lastMemorySnapshot.put(LocationNode.ANY_LOCATION, start);
+            lastMemorySnapshot.put(ANY_LOCATION, start);
         }
 
         public MemoryMap() {
@@ -54,12 +56,12 @@
 
         private ValueNode getLastLocationAccess(LocationIdentity locationIdentity) {
             ValueNode lastLocationAccess;
-            if (locationIdentity == LocationNode.FINAL_LOCATION) {
+            if (locationIdentity == FINAL_LOCATION) {
                 return null;
             } else {
                 lastLocationAccess = lastMemorySnapshot.get(locationIdentity);
                 if (lastLocationAccess == null) {
-                    lastLocationAccess = lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                    lastLocationAccess = lastMemorySnapshot.get(ANY_LOCATION);
                     assert lastLocationAccess != null;
                 }
                 return lastLocationAccess;
@@ -122,7 +124,7 @@
                 exit.addAll(modifiedLocations);
                 exit.addAll(initialState);
             }
-            assert !modifiedLocations.contains(LocationNode.FINAL_LOCATION);
+            assert !modifiedLocations.contains(FINAL_LOCATION);
             modifiedInLoops.put(loop, modifiedLocations);
             return loopInfo.exitStates;
         }
@@ -149,7 +151,7 @@
 
         private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) {
             for (LocationIdentity identity : checkpoint.getLocationIdentities()) {
-                if (identity == LocationNode.ANY_LOCATION) {
+                if (identity == ANY_LOCATION) {
                     state.lastMemorySnapshot.clear();
                 }
                 state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint);
@@ -160,7 +162,7 @@
             StructuredGraph graph = accessNode.graph();
             assert accessNode.getNullCheck() == false;
             LocationIdentity locationIdentity = accessNode.location().getLocationIdentity();
-            if (locationIdentity != LocationNode.ANY_LOCATION) {
+            if (locationIdentity != ANY_LOCATION) {
                 ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
                 FloatingAccessNode floatingNode = accessNode.asFloatingNode(lastLocationAccess);
                 floatingNode.setNullCheck(accessNode.getNullCheck());
@@ -182,7 +184,7 @@
             for (MemoryMap other : states) {
                 keys.addAll(other.lastMemorySnapshot.keySet());
             }
-            assert !keys.contains(LocationNode.FINAL_LOCATION);
+            assert !keys.contains(FINAL_LOCATION);
 
             for (LocationIdentity key : keys) {
                 int mergedStatesCount = 0;
@@ -236,7 +238,7 @@
         @Override
         protected Map<LoopExitNode, MemoryMap> processLoop(LoopBeginNode loop, MemoryMap initialState) {
             Set<LocationIdentity> modifiedLocations = modifiedInLoops.get(loop);
-            if (modifiedLocations.contains(LocationNode.ANY_LOCATION)) {
+            if (modifiedLocations.contains(ANY_LOCATION)) {
                 // create phis for all locations if ANY is modified in the loop
                 modifiedLocations = new HashSet<>(modifiedLocations);
                 modifiedLocations.addAll(initialState.lastMemorySnapshot.keySet());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -41,6 +41,7 @@
             if (node instanceof DeoptimizingNode) {
                 DeoptimizingNode deopt = (DeoptimizingNode) node;
                 if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) {
+                    GraalInternalError.guarantee(currentState != null, "no FrameState at DeoptimizingNode %s", deopt);
                     deopt.setDeoptimizationState(currentState);
                 }
             }
@@ -58,10 +59,7 @@
 
         @Override
         protected FrameState merge(MergeNode merge, List<FrameState> states) {
-            if (merge.stateAfter() != null) {
-                return merge.stateAfter();
-            }
-            return singleFrameState(merge, states);
+            return merge.stateAfter() != null ? merge.stateAfter() : singleFrameState(merge, states);
         }
 
         @Override
@@ -73,7 +71,6 @@
         protected Map<LoopExitNode, FrameState> processLoop(LoopBeginNode loop, FrameState initialState) {
             return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
         }
-
     }
 
     @Override
@@ -93,33 +90,12 @@
     }
 
     private static FrameState singleFrameState(@SuppressWarnings("unused") MergeNode merge, List<FrameState> states) {
-        if (states.size() == 0) {
-            return null;
-        }
-        FrameState firstState = states.get(0);
-        FrameState singleState = firstState;
-        if (singleState == null) {
-            return null;
-        }
-        int singleBci = singleState.bci;
+        FrameState singleState = states.get(0);
         for (int i = 1; i < states.size(); ++i) {
-            FrameState cur = states.get(i);
-            if (cur == null) {
+            if (states.get(i) != singleState) {
                 return null;
             }
-
-            if (cur != singleState) {
-                singleState = null;
-            }
-
-            if (cur.bci != singleBci) {
-                singleBci = FrameState.INVALID_FRAMESTATE_BCI;
-            }
-
         }
-        if (singleState != null) {
-            return singleState;
-        }
-        return null;
+        return singleState;
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 import java.util.Map.Entry;
 
@@ -220,7 +222,7 @@
 
     private static void processBlock(Block block, SchedulePhase schedule, int implicitNullCheckLimit) {
         List<ScheduledNode> nodes = schedule.nodesFor(block);
-        if (GraalOptions.OptImplicitNullChecks && implicitNullCheckLimit > 0) {
+        if (OptImplicitNullChecks.getValue() && implicitNullCheckLimit > 0) {
             new UseImplicitNullChecks(implicitNullCheckLimit).processNodes(nodes, block.getBeginNode());
         }
         new LowerGuards(block).processNodes(nodes, block.getBeginNode());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -43,6 +43,6 @@
     protected void run(StructuredGraph graph, C context) {
         int mark = graph.getMark();
         super.run(graph, context);
-        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), mark, customCanonicalizer).apply(graph);
+        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), GraalOptions.OptCanonicalizeReads.getValue(), mark, customCanonicalizer).apply(graph);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -33,6 +35,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
@@ -45,6 +48,11 @@
 
 public class InliningPhase extends Phase {
 
+    // @formatter:off
+    @Option(help = "Unconditionally inline intrinsics")
+    public static final OptionValue<Boolean> AlwaysInlineIntrinsics = new OptionValue<>(false);
+    // @formatter:on
+
     private final PhasePlan plan;
     private final MetaAccessProvider runtime;
     private final Assumptions compilationAssumptions;
@@ -184,9 +192,9 @@
             metricInliningRuns.increment();
             Debug.dump(callerGraph, "after %s", callee);
 
-            if (GraalOptions.OptCanonicalizer) {
+            if (OptCanonicalizer.getValue()) {
                 int markBeforeCanonicalization = callerGraph.getMark();
-                new CanonicalizerPhase.Instance(runtime, callerAssumptions, invokeUsages, markBeforeInlining, customCanonicalizer).apply(callerGraph);
+                new CanonicalizerPhase.Instance(runtime, callerAssumptions, OptCanonicalizeReads.getValue(), invokeUsages, markBeforeInlining, customCanonicalizer).apply(callerGraph);
 
                 // process invokes that are possibly created during canonicalization
                 for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) {
@@ -257,7 +265,7 @@
                         callerHasMoreInformationAboutArguments = true;
                     } else {
                         Stamp joinedStamp = localNode.stamp().join(arg.stamp());
-                        if (!joinedStamp.equals(localNode.stamp())) {
+                        if (joinedStamp != null && !joinedStamp.equals(localNode.stamp())) {
                             localNode.setStamp(joinedStamp);
                             callerHasMoreInformationAboutArguments = true;
                         }
@@ -270,8 +278,8 @@
                     // probability to check the inlining
                 }
 
-                if (GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph);
+                if (OptCanonicalizer.getValue()) {
+                    new CanonicalizerPhase.Instance(runtime, assumptions, OptCanonicalizeReads.getValue()).apply(newGraph);
                 }
 
                 return newGraph;
@@ -280,7 +288,7 @@
     }
 
     private StructuredGraph getCachedGraph(ResolvedJavaMethod method) {
-        if (GraalOptions.CacheGraphs && cache != null) {
+        if (CacheGraphs.getValue() && cache != null) {
             StructuredGraph cachedGraph = cache.get(method);
             if (cachedGraph != null) {
                 return cachedGraph;
@@ -297,14 +305,14 @@
 
         new DeadCodeEliminationPhase().apply(newGraph);
 
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph);
+        if (OptCanonicalizer.getValue()) {
+            new CanonicalizerPhase.Instance(runtime, assumptions, OptCanonicalizeReads.getValue()).apply(newGraph);
         }
 
-        if (GraalOptions.CullFrameStates) {
+        if (CullFrameStates.getValue()) {
             new CullFrameStatesPhase().apply(newGraph);
         }
-        if (GraalOptions.CacheGraphs && cache != null) {
+        if (CacheGraphs.getValue() && cache != null) {
             cache.put(newGraph.copy());
         }
         return newGraph;
@@ -330,7 +338,7 @@
         }
 
         protected double computeMaximumSize(double relevance, int configuredMaximum) {
-            double inlineRatio = Math.min(GraalOptions.RelevanceCapForInlining, relevance);
+            double inlineRatio = Math.min(RelevanceCapForInlining.getValue(), relevance);
             return configuredMaximum * inlineRatio;
         }
 
@@ -342,7 +350,7 @@
         }
 
         protected boolean isIntrinsic(InlineInfo info) {
-            if (GraalOptions.AlwaysInlineIntrinsics) {
+            if (AlwaysInlineIntrinsics.getValue()) {
                 return onlyIntrinsics(info);
             } else {
                 return onlyForcedIntrinsics(info);
@@ -412,7 +420,7 @@
         }
 
         public boolean continueInlining(StructuredGraph currentGraph) {
-            if (currentGraph.getNodeCount() >= GraalOptions.MaximumDesiredSize) {
+            if (currentGraph.getNodeCount() >= MaximumDesiredSize.getValue()) {
                 InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize");
                 metricInliningStoppedByMaxDesiredSize.increment();
                 return false;
@@ -429,33 +437,34 @@
             double inliningBonus = getInliningBonus(info);
 
             int lowLevelGraphSize = previousLowLevelGraphSize(info);
-            if (GraalOptions.SmallCompiledLowLevelGraphSize > 0 && lowLevelGraphSize > GraalOptions.SmallCompiledLowLevelGraphSize * inliningBonus) {
+            if (SmallCompiledLowLevelGraphSize.getValue() > 0 && lowLevelGraphSize > SmallCompiledLowLevelGraphSize.getValue() * inliningBonus) {
                 return InliningUtil.logNotInlinedMethod(info, inliningDepth, "too large previous low-level graph: %d", lowLevelGraphSize);
             }
 
+            int nodes = determineNodeCount(info);
+            if (nodes < TrivialInliningSize.getValue() * inliningBonus) {
+                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (nodes=%d)", nodes);
+            }
+
             /*
              * TODO (chaeubl): invoked methods that are on important paths but not yet compiled ->
              * will be compiled anyways and it is likely that we are the only caller... might be
              * useful to inline those methods but increases bootstrap time (maybe those methods are
              * also getting queued in the compilation queue concurrently)
              */
-
-            int nodes = determineNodeCount(info);
-            if (nodes < GraalOptions.TrivialInliningSize * inliningBonus) {
-                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (nodes=%d)", nodes);
+            double invokes = determineInvokeProbability(info);
+            if (LimitInlinedInvokes.getValue() > 0 && fullyProcessed && invokes > LimitInlinedInvokes.getValue() * inliningBonus) {
+                return InliningUtil.logNotInlinedMethod(info, inliningDepth, "callee invoke probability is too high (%f)", invokes);
             }
 
-            double invokes = determineInvokeProbability(info);
-            if (GraalOptions.LimitInlinedInvokes > 0 && fullyProcessed && invokes > GraalOptions.LimitInlinedInvokes * inliningBonus) {
-                return InliningUtil.logNotInlinedMethod(info, inliningDepth, "invoke probability is too high (%f)", invokes);
+            double maximumNodes = computeMaximumSize(relevance, (int) (MaximumInliningSize.getValue() * inliningBonus));
+            if (nodes <= maximumNodes) {
+                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= max=%f)", relevance, probability,
+                                inliningBonus, nodes, maximumNodes);
             }
 
-            double maximumNodes = computeMaximumSize(relevance, (int) (GraalOptions.MaximumInliningSize * inliningBonus));
-            if (nodes < maximumNodes) {
-                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, nodes=%d)", relevance, nodes);
-            }
-
-            return InliningUtil.logNotInlinedMethod(info, inliningDepth, "(relevance=%f, probability=%f, bonus=%f)", relevance, probability, inliningBonus);
+            return InliningUtil.logNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > max=%f)", relevance, probability, inliningBonus, nodes,
+                            maximumNodes);
         }
     }
 
@@ -786,7 +795,7 @@
         }
 
         public double invokeRelevance(Invoke invoke) {
-            return Math.min(GraalOptions.CapInheritedRelevance, relevance) * nodeRelevance.get(invoke.asNode());
+            return Math.min(CapInheritedRelevance.getValue(), relevance) * nodeRelevance.get(invoke.asNode());
         }
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -128,7 +130,7 @@
      * Print a HotSpot-style inlining message to the console.
      */
     private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final int inliningDepth, final boolean success, final String msg, final Object... args) {
-        if (GraalOptions.HotSpotPrintInlining) {
+        if (HotSpotPrintInlining.getValue()) {
             final int mod = method.getModifiers();
             // 1234567
             TTY.print("        ");     // print timestamp
@@ -698,7 +700,7 @@
                 replacementNodes.add(null);
             }
 
-            if (GraalOptions.OptTailDuplication) {
+            if (OptTailDuplication.getValue()) {
                 /*
                  * We might want to perform tail duplication at the merge after a type switch, if
                  * there are invokes that would benefit from the improvement in type information.
@@ -1059,20 +1061,29 @@
                 holder = receiverType;
                 if (receiverStamp.isExactType()) {
                     assert targetMethod.getDeclaringClass().isAssignableFrom(holder) : holder + " subtype of " + targetMethod.getDeclaringClass() + " for " + targetMethod;
-                    return getExactInlineInfo(data, invoke, replacements, optimisticOpts, holder.resolveMethod(targetMethod));
+                    ResolvedJavaMethod resolvedMethod = holder.resolveMethod(targetMethod);
+                    if (resolvedMethod != null) {
+                        return getExactInlineInfo(data, invoke, replacements, optimisticOpts, resolvedMethod);
+                    }
                 }
             }
         }
 
         if (holder.isArray()) {
             // arrays can be treated as Objects
-            return getExactInlineInfo(data, invoke, replacements, optimisticOpts, holder.resolveMethod(targetMethod));
+            ResolvedJavaMethod resolvedMethod = holder.resolveMethod(targetMethod);
+            if (resolvedMethod != null) {
+                return getExactInlineInfo(data, invoke, replacements, optimisticOpts, resolvedMethod);
+            }
         }
 
         if (assumptions.useOptimisticAssumptions()) {
             ResolvedJavaType uniqueSubtype = holder.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                return getAssumptionInlineInfo(data, invoke, replacements, optimisticOpts, uniqueSubtype.resolveMethod(targetMethod), new Assumptions.ConcreteSubtype(holder, uniqueSubtype));
+                ResolvedJavaMethod resolvedMethod = uniqueSubtype.resolveMethod(targetMethod);
+                if (resolvedMethod != null) {
+                    return getAssumptionInlineInfo(data, invoke, replacements, optimisticOpts, resolvedMethod, new Assumptions.ConcreteSubtype(holder, uniqueSubtype));
+                }
             }
 
             ResolvedJavaMethod concrete = holder.findUniqueConcreteMethod(targetMethod);
@@ -1148,6 +1159,9 @@
             ArrayList<Double> concreteMethodsProbabilities = new ArrayList<>();
             for (int i = 0; i < ptypes.length; i++) {
                 ResolvedJavaMethod concrete = ptypes[i].getType().resolveMethod(targetMethod);
+                if (concrete == null) {
+                    return logNotInlinedMethodAndReturnNull(invoke, data.inliningDepth(), targetMethod, "could not resolve method");
+                }
                 int index = concreteMethods.indexOf(concrete);
                 double curProbability = ptypes[i].getProbability();
                 if (index < 0) {
@@ -1168,7 +1182,7 @@
                 ArrayList<ResolvedJavaMethod> newConcreteMethods = new ArrayList<>();
                 ArrayList<Double> newConcreteMethodsProbabilities = new ArrayList<>();
                 for (int i = 0; i < concreteMethods.size(); ++i) {
-                    if (concreteMethodsProbabilities.get(i) >= GraalOptions.MegamorphicInliningMinMethodProbability) {
+                    if (concreteMethodsProbabilities.get(i) >= GraalOptions.MegamorphicInliningMinMethodProbability.getValue()) {
                         newConcreteMethods.add(concreteMethods.get(i));
                         newConcreteMethodsProbabilities.add(concreteMethodsProbabilities.get(i));
                     }
@@ -1241,7 +1255,7 @@
     private static boolean checkTargetConditions(InliningData data, Replacements replacements, Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) {
         if (method == null) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method is not resolved");
-        } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(replacements, method))) {
+        } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is a non-intrinsic native method");
         } else if (Modifier.isAbstract(method.getModifiers())) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is an abstract method");
@@ -1249,7 +1263,7 @@
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method's class is not initialized");
         } else if (!method.canBeInlined()) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is marked non-inlinable");
-        } else if (data.countRecursiveInlining(method) > GraalOptions.MaximumRecursiveInlining) {
+        } else if (data.countRecursiveInlining(method) > MaximumRecursiveInlining.getValue()) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it exceeds the maximum recursive inlining depth");
         } else if (new OptimisticOptimizations(method).lessOptimisticThan(optimisticOpts)) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the callee uses less optimistic optimizations than caller");
@@ -1283,6 +1297,10 @@
 
         FrameState stateAfter = invoke.stateAfter();
         assert stateAfter == null || stateAfter.isAlive();
+        GuardingNode receiverNullCheckNode = null;
+        if (receiverNullCheck) {
+            receiverNullCheckNode = receiverNullCheck(invoke);
+        }
 
         IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
         ArrayList<Node> nodes = new ArrayList<>();
@@ -1294,7 +1312,18 @@
             if (node == entryPointNode || node == entryPointNode.stateAfter()) {
                 // Do nothing.
             } else if (node instanceof LocalNode) {
-                replacements.put(node, parameters.get(((LocalNode) node).index()));
+                int localIndex = ((LocalNode) node).index();
+                ValueNode parameter = parameters.get(localIndex);
+                if (receiverNullCheckNode != null && localIndex == 0) {
+                    Stamp piStamp = parameter.stamp();
+                    if (piStamp instanceof ObjectStamp) {
+                        piStamp = piStamp.join(StampFactory.objectNonNull());
+                    }
+                    PiNode piReceiver = graph.add(new PiNode(parameter, piStamp));
+                    piReceiver.setGuard(receiverNullCheckNode);
+                    parameter = piReceiver;
+                }
+                replacements.put(node, parameter);
             } else {
                 nodes.add(node);
                 if (node instanceof ReturnNode) {
@@ -1314,9 +1343,6 @@
 
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
-        if (receiverNullCheck) {
-            receiverNullCheck(invoke);
-        }
         invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate);
 
         FrameState stateAtExceptionEdge = null;
@@ -1422,15 +1448,17 @@
         return true;
     }
 
-    public static void receiverNullCheck(Invoke invoke) {
+    public static GuardingNode receiverNullCheck(Invoke invoke) {
         MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
         StructuredGraph graph = callTarget.graph();
         NodeInputList<ValueNode> parameters = callTarget.arguments();
         ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0);
         if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) {
-            graph.addBeforeFixed(invoke.asNode(),
-                            graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true)));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true));
+            graph.addBeforeFixed(invoke.asNode(), guard);
+            return guard;
         }
+        return null;
     }
 
     public static boolean canIntrinsify(Replacements replacements, ResolvedJavaMethod target) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InsertStateAfterPlaceholderPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InsertStateAfterPlaceholderPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -48,6 +48,9 @@
 
         @Override
         public ValueNode canonical(CanonicalizerTool tool) {
+            if (!usages().isEmpty()) {
+                return this;
+            }
             if (stateAfter() == null) {
                 return null;
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -44,7 +44,7 @@
             if (canonicalizationRoots.isEmpty()) {
                 break;
             }
-            new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), canonicalizationRoots, null).apply(graph);
+            new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), GraalOptions.OptCanonicalizeReads.getValue(), canonicalizationRoots, null).apply(graph);
             canonicalizationRoots.clear();
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -69,6 +71,11 @@
         }
 
         @Override
+        public LoweringType getLoweringType() {
+            return loweringType;
+        }
+
+        @Override
         public GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object) {
             if (object.objectStamp().nonNull()) {
                 // Short cut creation of null check guard if the object is known to be non-null.
@@ -95,7 +102,7 @@
             if (loweringType == LoweringType.AFTER_GUARDS) {
                 throw new GraalInternalError("Cannot create guards in after-guard lowering");
             }
-            if (GraalOptions.OptEliminateGuards) {
+            if (OptEliminateGuards.getValue()) {
                 for (Node usage : condition.usages()) {
                     if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).negated() == negated) {
                         return (GuardNode) usage;
@@ -103,7 +110,7 @@
                 }
             }
             GuardNode newGuard = guardAnchor.asNode().graph().unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated));
-            if (GraalOptions.OptEliminateGuards) {
+            if (OptEliminateGuards.getValue()) {
                 activeGuards.grow();
                 activeGuards.mark(newGuard);
             }
@@ -203,7 +210,7 @@
                 }
             }
 
-            if (parentAnchor == null && GraalOptions.OptEliminateGuards) {
+            if (parentAnchor == null && OptEliminateGuards.getValue()) {
                 for (GuardNode guard : anchor.asNode().usages().filter(GuardNode.class)) {
                     activeGuards.clear(guard);
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
@@ -33,7 +35,7 @@
 
     @Override
     protected void run(StructuredGraph graph) {
-        if (GraalOptions.GenLoopSafepoints) {
+        if (GenLoopSafepoints.getValue()) {
             for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) {
                 if (!loopEndNode.canSafepoint()) {
                     continue;
@@ -43,8 +45,8 @@
             }
         }
 
-        if (GraalOptions.GenSafepoints) {
-            if (!GraalOptions.OptEliminateSafepoints || graph.getNodes(MethodCallTargetNode.class).isNotEmpty()) {
+        if (GenSafepoints.getValue()) {
+            if (!OptEliminateSafepoints.getValue() || graph.getNodes(MethodCallTargetNode.class).isNotEmpty()) {
                 for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) {
                     SafepointNode safepoint = graph.add(new SafepointNode());
                     graph.addBeforeFixed(returnNode, safepoint);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 
 import com.oracle.graal.debug.*;
@@ -80,7 +82,7 @@
     public static final TailDuplicationDecision DEFAULT_DECISION = new TailDuplicationDecision() {
 
         public boolean doTransform(MergeNode merge, int fixedNodeCount) {
-            if (fixedNodeCount < GraalOptions.TailDuplicationTrivialSize) {
+            if (fixedNodeCount < TailDuplicationTrivialSize.getValue()) {
                 return true;
             }
             HashSet<PhiNode> improvements = new HashSet<>();
@@ -136,7 +138,7 @@
         // A snapshot is taken here, so that new MergeNode instances aren't considered for tail
         // duplication.
         for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
-            if (!(merge instanceof LoopBeginNode) && nodeProbabilities.get(merge) >= GraalOptions.TailDuplicationProbability) {
+            if (!(merge instanceof LoopBeginNode) && nodeProbabilities.get(merge) >= TailDuplicationProbability.getValue()) {
                 tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext);
             }
         }
@@ -298,7 +300,7 @@
                     phi.setMerge(mergeAfter);
                 }
             }
-            new CanonicalizerPhase(null, graph.getNewNodes(startMark)).apply(graph, phaseContext);
+            new CanonicalizerPhase.Instance(phaseContext.getRuntime(), phaseContext.getAssumptions(), GraalOptions.OptCanonicalizeReads.getValue(), graph.getNewNodes(startMark), null).apply(graph);
             Debug.dump(graph, "After tail duplication at %s", merge);
         }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,239 +22,330 @@
  */
 package com.oracle.graal.phases;
 
+import com.oracle.graal.options.*;
+
 /**
  * This class encapsulates options that control the behavior of the Graal compiler.
- * 
- * (thomaswue) WARNING: Fields of this class are treated as final by Graal.
  */
 // @formatter:off
 public final class GraalOptions {
 
-    // Checkstyle: stop
-    private static final boolean ____ = false;
-    // Checkstyle: resume
-
-    public static int     Threads;
-    static {
-        Threads = Runtime.getRuntime().availableProcessors();
-    }
-
-    public static String  CompilerConfiguration              = "basic";
-    public static String  GraalRuntime                       = "basic";
+    @Option(help = "Enable use of compiler intrinsics")
+    public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true);
+    @Option(help = "Enable inlining of monomorphic calls")
+    static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true);
+    @Option(help = "Enable inlining of polymorphic calls")
+    static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true);
+    @Option(help = "Enable inlining of megamorphic calls")
+    static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(5000);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(1);
 
     // inlining settings
-    public static boolean Inline                             = true;
-    public static boolean AlwaysInlineIntrinsics             = ____;
-    public static boolean Intrinsify                         = true;
-           static boolean InlineMonomorphicCalls             = true;
-           static boolean InlinePolymorphicCalls             = true;
-           static boolean InlineMegamorphicCalls             = true;
-    public static double  MegamorphicInliningMinMethodProbability = 0.33;
-    public static int     MaximumDesiredSize                 = 5000;
-    public static int     MaximumRecursiveInlining           = 1;
-    public static float   BoostInliningForEscapeAnalysis     = 2f;
-    public static float   RelevanceCapForInlining            = 1f;
-    public static float   CapInheritedRelevance              = 1f;
-    public static boolean IterativeInlining                  = ____;
+    @Option(help = "")
+    public static final OptionValue<Float> BoostInliningForEscapeAnalysis = new OptionValue<>(2f);
+    @Option(help = "")
+    public static final OptionValue<Float> RelevanceCapForInlining = new OptionValue<>(1f);
+    @Option(help = "")
+    public static final OptionValue<Float> CapInheritedRelevance = new OptionValue<>(1f);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IterativeInlining = new OptionValue<>(false);
 
-    public static int     TrivialInliningSize                = 10;
-    public static int     MaximumInliningSize                = 300;
-    public static int     SmallCompiledLowLevelGraphSize     = 300;
-    public static double  LimitInlinedInvokes                = 5.0;
+    @Option(help = "")
+    public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0);
 
     // escape analysis settings
-    public static boolean PartialEscapeAnalysis              = true;
-    public static boolean EscapeAnalysisHistogram            = ____;
-    public static int     EscapeAnalysisIterations           = 2;
-    public static String  EscapeAnalyzeOnly                  = null;
-    public static int     MaximumEscapeAnalysisArrayLength   = 32;
-    public static boolean PEAInliningHints                   = ____;
+    @Option(help = "")
+    public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> EscapeAnalysisHistogram = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2);
+    @Option(help = "")
+    public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false);
 
-    public static double  TailDuplicationProbability         = 0.5;
-    public static int     TailDuplicationTrivialSize         = 1;
+    @Option(help = "")
+    public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5);
+    @Option(help = "")
+    public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1);
 
     // profiling information
-    public static int     DeoptsToDisableOptimisticOptimization = 40;
-    public static int     MatureExecutionsBranch             = 1;
-    public static int     MatureExecutionsPerSwitchCase      = 1;
-    public static int     MatureExecutionsTypeProfile        = 1;
+    @Option(help = "")
+    public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40);
+    @Option(help = "")
+    public static final OptionValue<Integer> MatureExecutionsBranch = new OptionValue<>(1);
+    @Option(help = "")
+    public static final OptionValue<Integer> MatureExecutionsPerSwitchCase = new OptionValue<>(1);
+    @Option(help = "")
+    public static final OptionValue<Integer> MatureExecutionsTypeProfile = new OptionValue<>(1);
 
     // comilation queue
-    public static int     TimedBootstrap                     = -1;
-    public static boolean PriorityCompileQueue               = true;
-    public static int     SlowQueueCutoff                    = 100000;
-    public static boolean SlowCompileThreads                 = ____;
-    public static boolean DynamicCompilePriority             = ____;
-    public static String  CompileTheWorld                    = null;
-    public static int     CompileTheWorldStartAt             = 1;
-    public static int     CompileTheWorldStopAt              = Integer.MAX_VALUE;
+    @Option(help = "")
+    public static final OptionValue<Boolean> DynamicCompilePriority = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<String> CompileTheWorld = new OptionValue<>(null);
+    @Option(help = "")
+    public static final OptionValue<Integer> CompileTheWorldStartAt = new OptionValue<>(1);
+    @Option(help = "")
+    public static final OptionValue<Integer> CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE);
 
     // graph caching
-    public static boolean CacheGraphs                        = true;
-    public static int     GraphCacheSize                     = 1000;
-    public static boolean PrintGraphCache                    = ____;
+    @Option(help = "")
+    public static final OptionValue<Boolean> CacheGraphs = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> GraphCacheSize = new OptionValue<>(1000);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintGraphCache = new OptionValue<>(false);
 
     //loop transform settings TODO (gd) tune
-    public static boolean LoopPeeling                        = true;
-    public static boolean ReassociateInvariants              = true;
-    public static boolean FullUnroll                         = true;
-    public static boolean LoopUnswitch                       = true;
-    public static int     FullUnrollMaxNodes                 = 300;
-    public static int     ExactFullUnrollMaxNodes            = 1200;
-    public static float   MinimumPeelProbability             = 0.35f;
-    public static int     LoopMaxUnswitch                    = 3;
-    public static int     LoopUnswitchMaxIncrease            = 50;
-    public static int     LoopUnswitchUncertaintyBoost       = 5;
-    public static boolean UseLoopLimitChecks                 = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> FullUnrollMaxNodes = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Integer> ExactFullUnrollMaxNodes = new OptionValue<>(1200);
+    @Option(help = "")
+    public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(50);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopUnswitchUncertaintyBoost = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true);
 
     // debugging settings
-    public static boolean ZapStackOnMethodEntry              = ____;
-    public static boolean DeoptALot                          = ____;
-    public static boolean VerifyPhases                       = false;
+    @Option(help = "")
+    public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false);
 
-    public static String  PrintFilter                        = null;
+    @Option(help = "")
+    public static final OptionValue<String> PrintFilter = new OptionValue<>(null);
 
     // Debug settings:
-    public static boolean Debug                              = true;
-    public static boolean DebugReplacements                  = ____;
-    public static boolean BootstrapReplacements              = ____;
-    public static boolean PerThreadDebugValues               = ____;
-    public static boolean SummarizeDebugValues               = ____;
-    public static boolean SummarizePerPhase                  = ____;
-    public static String  Dump                               = null;
-    public static String  Meter                              = null;
-    public static String  Time                               = null;
-    public static String  Log                                = null;
-    public static String  LogFile                            = null;
-    public static String  MethodFilter                       = null;
-    public static boolean DumpOnError                        = ____;
-    public static boolean GenericDynamicCounters             = ____;
-    public static String  BenchmarkDynamicCounters           = null;
+    @Option(help = "")
+    public static final OptionValue<Boolean> BootstrapReplacements = new OptionValue<>(false);
 
     // Ideal graph visualizer output settings
-    public static boolean PrintBinaryGraphs                  = true;
-    public static boolean PrintCFG                           = ____;
-    public static boolean PrintIdealGraphFile                = ____;
-    public static String  PrintIdealGraphAddress             = "127.0.0.1";
-    public static int     PrintIdealGraphPort                = 4444;
-    public static int     PrintBinaryGraphPort               = 4445;
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintBinaryGraphs = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintCFG = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintIdealGraphFile = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<String> PrintIdealGraphAddress = new OptionValue<>("127.0.0.1");
+    @Option(help = "")
+    public static final OptionValue<Integer> PrintIdealGraphPort = new OptionValue<>(4444);
+    @Option(help = "")
+    public static final OptionValue<Integer> PrintBinaryGraphPort = new OptionValue<>(4445);
 
     // Other printing settings
-    public static boolean PrintQueue                         = ____;
-    public static boolean PrintCompilation                   = ____;
-    public static boolean PrintProfilingInformation          = ____;
-    public static boolean PrintIRWithLIR                     = ____;
-    public static boolean PrintCodeBytes                     = ____;
-    public static boolean PrintBailout                       = ____;
-    public static int     TraceLinearScanLevel               = 0;
-    public static int     TraceLIRGeneratorLevel             = 0;
-    public static boolean TraceEscapeAnalysis                = ____;
-    public static int     TraceBytecodeParserLevel           = 0;
-    public static boolean ExitVMOnBailout                    = ____;
-    public static boolean ExitVMOnException                  = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintCodeBytes = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Integer> TraceLinearScanLevel = new OptionValue<>(0);
+    @Option(help = "")
+    public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TraceEscapeAnalysis = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Integer> TraceBytecodeParserLevel = new OptionValue<>(0);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
 
     // HotSpot command line options
-    public static boolean HotSpotPrintCompilation            = ____;
-    public static boolean HotSpotPrintInlining               = ____;
+    @Option(help = "")
+    public static final OptionValue<Boolean> HotSpotPrintCompilation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false);
 
     // Register allocator debugging
-    public static String  RegisterPressure                   = null;
+    @Option(help = "")
+    public static final OptionValue<String> RegisterPressure = new OptionValue<>(null);
 
     // Code generator settings
-    public static boolean ConditionalElimination             = true;
-    public static boolean CullFrameStates                    = ____;
-    public static boolean UseProfilingInformation            = true;
-           static boolean RemoveNeverExecutedCode            = true;
-           static boolean UseExceptionProbability            = true;
-           static boolean UseExceptionProbabilityForOperations = true;
-    public static boolean OmitHotExceptionStacktrace         = ____;
-    public static boolean GenSafepoints                      = true;
-    public static boolean GenLoopSafepoints                  = true;
-           static boolean UseTypeCheckHints                  = true;
-    public static boolean InlineVTableStubs                  = true;
-    public static boolean AlwaysInlineVTableStubs            = ____;
-    public static boolean GenAssertionCode                   = ____;
-    public static boolean AlignCallsForPatching              = true;
-    public static boolean ResolveClassBeforeStaticInvoke     = ____;
-    public static boolean CanOmitFrame                       = true;
-    public static int     SafepointPollOffset                = 256;
+    @Option(help = "")
+    public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> CullFrameStates = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
+    @Option(help = "")
+           static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true);
+           @Option(help = "")
+           static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true);
+           @Option(help = "")
+           static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true);
+           @Option(help = "")
+    public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true);
+    @Option(help = "")
+           static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true);
+           @Option(help = "")
+    public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenAssertionCode = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> AlignCallsForPatching = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> SafepointPollOffset = new OptionValue<>(256);
 
-    public static boolean MemoryAwareScheduling              = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> MemoryAwareScheduling = new OptionValue<>(true);
 
     // Translating tableswitch instructions
-    public static int     MinimumJumpTableSize               = 5;
-    public static int     RangeTestsSwitchDensity            = 5;
-    public static double  MinTableSwitchDensity              = 0.5;
-
-    public static boolean DetailedAsserts                    = ____;
+    @Option(help = "")
+    public static final OptionValue<Integer> MinimumJumpTableSize = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Integer> RangeTestsSwitchDensity = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Double> MinTableSwitchDensity = new OptionValue<>(0.5);
 
     // Runtime settings
-    public static int     StackShadowPages                   = 2;
+    @Option(help = "")
+    public static final OptionValue<Integer> StackShadowPages = new OptionValue<>(2);
 
-    public static boolean SupportJsrBytecodes                = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> SupportJsrBytecodes = new OptionValue<>(true);
 
-    public static boolean OptAssumptions                     = true;
-    public static boolean OptConvertDeoptsToGuards           = true;
-    public static boolean OptReadElimination                 = true;
-    public static boolean OptEarlyReadElimination            = true;
-    public static boolean OptCanonicalizer                   = true;
-    public static boolean OptScheduleOutOfLoops              = true;
-    public static boolean OptEliminateGuards                 = true;
-    public static boolean OptEliminateSafepoints             = true;
-    public static boolean OptImplicitNullChecks              = true;
-    public static boolean OptLivenessAnalysis                = true;
-    public static boolean OptLoopTransform                   = true;
-    public static boolean OptFloatingReads                   = true;
-    public static boolean OptTailDuplication                 = true;
-    public static boolean OptEliminatePartiallyRedundantGuards = true;
-    public static boolean OptFilterProfiledTypes             = true;
-    public static boolean OptDevirtualizeInvokesOptimistically = true;
-    public static boolean OptPushThroughPi                   = true;
-
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEarlyReadElimination = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptCanonicalizeReads = new OptionValue<>(true);
+    @Option(help = "")
+     public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEliminateSafepoints = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
 
     // Intrinsification settings
-    public static boolean IntrinsifyObjectClone              = ____;
-    public static boolean IntrinsifyArrayCopy                = true;
-    public static boolean IntrinsifyObjectMethods            = true;
-    public static boolean IntrinsifySystemMethods            = true;
-    public static boolean IntrinsifyClassMethods             = true;
-    public static boolean IntrinsifyThreadMethods            = true;
-    public static boolean IntrinsifyUnsafeMethods            = true;
-    public static boolean IntrinsifyMathMethods              = true;
-    public static boolean IntrinsifyAESMethods               = true;
-    public static boolean IntrinsifyReflectionMethods        = true;
-    public static boolean IntrinsifyInstalledCodeMethods     = true;
-    public static boolean IntrinsifyCallSiteTarget           = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyObjectClone = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyArrayCopy = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyObjectMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifySystemMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyClassMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyThreadMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyUnsafeMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyMathMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyAESMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyReflectionMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyInstalledCodeMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyCallSiteTarget = new OptionValue<>(true);
     /**
      * Counts the various paths taken through snippets.
      */
-    public static boolean SnippetCounters = false;
+    @Option(help = "")
+    public static final OptionValue<Boolean> SnippetCounters = new OptionValue<>(false);
 
     /**
      * If the probability that a checkcast will hit one the profiled types (up to {@link #CheckcastMaxHints})
      * is below this value, the checkcast will be compiled without hints.
      */
-    public static double CheckcastMinHintHitProbability = 0.5;
+    @Option(help = "")
+    public static final OptionValue<Double> CheckcastMinHintHitProbability = new OptionValue<>(0.5);
 
     /**
      * The maximum number of hint types that will be used when compiling a checkcast for which
      * profiling information is available. Note that {@link #CheckcastMinHintHitProbability}
      * also influences whether hints are used.
      */
-    public static int CheckcastMaxHints = 2;
+    @Option(help = "")
+    public static final OptionValue<Integer> CheckcastMaxHints = new OptionValue<>(2);
 
     /**
      * @see #CheckcastMinHintHitProbability
      */
-    public static double InstanceOfMinHintHitProbability = 0.5;
+    @Option(help = "")
+    public static final OptionValue<Double> InstanceOfMinHintHitProbability = new OptionValue<>(0.5);
 
     /**
      * @see #CheckcastMaxHints
      */
-    public static int InstanceOfMaxHints = 2;
-
-    static {
-        // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
-        assert (DetailedAsserts = true) == true;
-    }
+    @Option(help = "")
+    public static final OptionValue<Integer> InstanceOfMaxHints = new OptionValue<>(2);
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Fri Jun 07 14:15:38 2013 +0200
@@ -79,39 +79,39 @@
     }
 
     public boolean removeNeverExecutedCode() {
-        return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
+        return GraalOptions.RemoveNeverExecutedCode.getValue() && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
     }
 
     public boolean useTypeCheckHints() {
-        return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints);
+        return GraalOptions.UseTypeCheckHints.getValue() && enabledOpts.contains(Optimization.UseTypeCheckHints);
     }
 
     public boolean inlineMonomorphicCalls() {
-        return GraalOptions.InlineMonomorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+        return GraalOptions.InlineMonomorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
     public boolean inlinePolymorphicCalls() {
-        return GraalOptions.InlinePolymorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+        return GraalOptions.InlinePolymorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
     public boolean inlineMegamorphicCalls() {
-        return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+        return GraalOptions.InlineMegamorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
     public boolean devirtualizeInvokes() {
-        return GraalOptions.OptDevirtualizeInvokesOptimistically && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+        return GraalOptions.OptDevirtualizeInvokesOptimistically.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
     public boolean useExceptionProbability() {
-        return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability);
+        return GraalOptions.UseExceptionProbability.getValue() && enabledOpts.contains(Optimization.UseExceptionProbability);
     }
 
     public boolean useExceptionProbabilityForOperations() {
-        return GraalOptions.UseExceptionProbabilityForOperations && enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations);
+        return GraalOptions.UseExceptionProbabilityForOperations.getValue() && enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations);
     }
 
     public boolean useLoopLimitChecks() {
-        return GraalOptions.UseLoopLimitChecks && enabledOpts.contains(Optimization.UseLoopLimitChecks);
+        return GraalOptions.UseLoopLimitChecks.getValue() && enabledOpts.contains(Optimization.UseLoopLimitChecks);
     }
 
     public boolean lessOptimisticThan(OptimisticOptimizations other) {
@@ -124,6 +124,6 @@
     }
 
     private static boolean checkDeoptimizations(ProfilingInfo profilingInfo, DeoptimizationReason reason) {
-        return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization;
+        return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization.getValue();
     }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -24,6 +24,12 @@
 
 import com.oracle.graal.nodes.*;
 
+/***
+ * This phase serves as a verification, in order to check the graph for certain properties. The
+ * {@link #verify(StructuredGraph)} method will be used as an assertion, and implements the actual
+ * check. Instead of returning false, it is also valid to throw an {@link AssertionError} in the
+ * implemented {@link #verify(StructuredGraph)} method.
+ */
 public abstract class VerifyPhase extends Phase {
 
     @Override
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Fri Jun 07 14:15:38 2013 +0200
@@ -37,6 +37,8 @@
 
     public abstract static class BlockIteratorClosure<StateT> {
 
+        protected abstract StateT getInitialState();
+
         protected abstract StateT processBlock(Block block, StateT currentState);
 
         protected abstract StateT merge(Block merge, List<StateT> states);
@@ -70,7 +72,11 @@
         return info;
     }
 
-    public static <StateT> IdentityHashMap<FixedNode, StateT> apply(BlockIteratorClosure<StateT> closure, Block start, StateT initialState, Set<Block> boundary) {
+    public static <StateT> void apply(BlockIteratorClosure<StateT> closure, Block start) {
+        apply(closure, start, closure.getInitialState(), null);
+    }
+
+    private static <StateT> IdentityHashMap<FixedNode, StateT> apply(BlockIteratorClosure<StateT> closure, Block start, StateT initialState, Set<Block> boundary) {
         Deque<Block> blockQueue = new ArrayDeque<>();
         /*
          * States are stored on EndNodes before merges, and on BeginNodes after ControlSplitNodes.
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,8 +22,12 @@
  */
 package com.oracle.graal.phases.schedule;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
@@ -31,7 +35,6 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
@@ -84,6 +87,11 @@
     private class MemoryScheduleClosure extends BlockIteratorClosure<HashSet<FloatingReadNode>> {
 
         @Override
+        protected HashSet<FloatingReadNode> getInitialState() {
+            return new HashSet<>();
+        }
+
+        @Override
         protected HashSet<FloatingReadNode> processBlock(Block block, HashSet<FloatingReadNode> currentState) {
             for (Node node : getBlockToNodesMap().get(block)) {
                 if (node instanceof FloatingReadNode) {
@@ -93,7 +101,7 @@
                         for (Iterator<FloatingReadNode> iter = currentState.iterator(); iter.hasNext();) {
                             FloatingReadNode read = iter.next();
                             FixedNode fixed = (FixedNode) node;
-                            if (identity == LocationNode.ANY_LOCATION || read.location().getLocationIdentity() == identity) {
+                            if (identity == ANY_LOCATION || read.location().getLocationIdentity() == identity) {
                                 addPhantomReference(read, fixed);
                                 iter.remove();
                             }
@@ -165,7 +173,7 @@
     private final SchedulingStrategy selectedStrategy;
 
     public SchedulePhase() {
-        this(GraalOptions.OptScheduleOutOfLoops ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST);
+        this(OptScheduleOutOfLoops.getValue() ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST);
     }
 
     public SchedulePhase(SchedulingStrategy strategy) {
@@ -178,13 +186,13 @@
         earliestCache = graph.createNodeMap();
         blockToNodesMap = new BlockMap<>(cfg);
 
-        if (GraalOptions.MemoryAwareScheduling && selectedStrategy != SchedulingStrategy.EARLIEST && graph.getNodes(FloatingReadNode.class).isNotEmpty()) {
+        if (MemoryAwareScheduling.getValue() && selectedStrategy != SchedulingStrategy.EARLIEST && graph.getNodes(FloatingReadNode.class).isNotEmpty()) {
 
             assignBlockToNodes(graph, SchedulingStrategy.EARLIEST);
             sortNodesWithinBlocks(graph, SchedulingStrategy.EARLIEST);
 
             MemoryScheduleClosure closure = new MemoryScheduleClosure();
-            ReentrantBlockIterator.apply(closure, getCFG().getStartBlock(), new HashSet<FloatingReadNode>(), null);
+            ReentrantBlockIterator.apply(closure, getCFG().getStartBlock());
 
             cfg.clearNodeToBlock();
             blockToNodesMap = new BlockMap<>(cfg);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Fri Jun 07 14:15:38 2013 +0200
@@ -25,10 +25,16 @@
 import java.util.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 
 public final class Suites {
 
+    // @formatter:off
+    @Option(help = "The compiler configuration to use")
+    private static final OptionValue<String> CompilerConfiguration = new OptionValue<>("basic");
+    // @formatter:on
+
     public static final Suites DEFAULT;
 
     private final PhaseSuite<HighTierContext> highTier;
@@ -69,7 +75,7 @@
     }
 
     public static Suites createDefaultSuites() {
-        return createSuites(GraalOptions.CompilerConfiguration);
+        return createSuites(CompilerConfiguration.getValue());
     }
 
     public static Suites createSuites(String name) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.verify;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * For certain types object identity should not be used for object equality check. This phase checks
+ * the correct usage of the given type. Equality checks with == or != (except null checks) results
+ * in an {@link AssertionError}.
+ */
+public class VerifyUsageWithEquals extends VerifyPhase {
+
+    private MetaAccessProvider runtime;
+    private Class<?> klass;
+
+    public VerifyUsageWithEquals(MetaAccessProvider runtime, Class<?> klass) {
+        this.runtime = runtime;
+        this.klass = klass;
+    }
+
+    private boolean isAssignableType(ValueNode node) {
+        if (node.stamp() instanceof ObjectStamp) {
+            ResolvedJavaType valueType = runtime.lookupJavaType(klass);
+            ResolvedJavaType nodeType = node.objectStamp().type();
+
+            if (nodeType != null && valueType.isAssignableFrom(nodeType)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean isNullConstant(ValueNode node) {
+        return node.isConstant() && node.asConstant().isNull();
+    }
+
+    private boolean checkUsage(ValueNode x, ValueNode y) {
+        return isAssignableType(x) && !isNullConstant(y);
+    }
+
+    private static boolean isEqualsMethod(StructuredGraph graph) {
+        Signature signature = graph.method().getSignature();
+        return graph.method().getName().equals("equals") && signature.getParameterCount(false) == 1 && signature.getParameterKind(0).equals(Kind.Object);
+    }
+
+    @Override
+    protected boolean verify(StructuredGraph graph) {
+        for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
+            if (!isEqualsMethod(graph)) {
+                // bail out if we compare an object of type klass with == or != (except null checks)
+                assert !(checkUsage(cn.x(), cn.y()) && checkUsage(cn.y(), cn.x())) : "Verifcation of " + klass.getName() + " usage failed: Comparing " + cn.x() + " and" + cn.y() + " in " +
+                                graph.method() + " must use .equals() for object equality, not '==' or '!='";
+            }
+        }
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyValueUsage.java	Fri Jun 07 13:43:13 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.verify;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
-
-public class VerifyValueUsage extends VerifyPhase {
-
-    private MetaAccessProvider runtime;
-
-    public VerifyValueUsage(MetaAccessProvider runtime) {
-        this.runtime = runtime;
-    }
-
-    private boolean checkType(ValueNode node) {
-        if (node.stamp() instanceof ObjectStamp) {
-            ResolvedJavaType valueType = runtime.lookupJavaType(Value.class);
-            ResolvedJavaType nodeType = node.objectStamp().type();
-
-            if (valueType.isAssignableFrom(nodeType)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    protected boolean verify(StructuredGraph graph) {
-        for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
-            Signature signature = graph.method().getSignature();
-            if (!(graph.method().getName().equals("equals") && signature.getParameterCount(false) == 1 && signature.getParameterKind(0).equals(Kind.Object))) {
-                assert !((checkType(cn.x()) && !(cn.y() instanceof ConstantNode)) || (checkType(cn.y()) && !(cn.x() instanceof ConstantNode))) : "VerifyValueUsage: " + cn.x() + " or " + cn.y() +
-                                " in " + graph.method() + " uses object identity. Should use equals() instead.";
-            }
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,12 +22,14 @@
  */
 package com.oracle.graal.printer;
 
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.io.*;
 import java.util.*;
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.phases.*;
 
 public class DebugEnvironment {
 
@@ -35,13 +37,13 @@
         Debug.enable();
         List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
         dumpHandlers.add(new GraphPrinterDumpHandler());
-        if (GraalOptions.PrintCFG) {
-            if (GraalOptions.PrintBinaryGraphs) {
+        if (PrintCFG.getValue()) {
+            if (PrintBinaryGraphs.getValue()) {
                 TTY.println("CFG dumping slows down PrintBinaryGraphs: use -G:-PrintCFG to disable it");
             }
             dumpHandlers.add(new CFGPrinterObserver());
         }
-        GraalDebugConfig hotspotDebugConfig = new GraalDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log, dumpHandlers);
+        GraalDebugConfig hotspotDebugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), Time.getValue(), Dump.getValue(), MethodFilter.getValue(), log, dumpHandlers);
         Debug.setConfig(hotspotDebugConfig);
     }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.printer;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.io.*;
 import java.net.*;
 import java.nio.channels.*;
@@ -33,7 +35,6 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
 
 /**
@@ -60,7 +61,7 @@
                 return;
             }
             previousInlineContext.clear();
-            if (GraalOptions.PrintIdealGraphFile) {
+            if (PrintIdealGraphFile.getValue()) {
                 initializeFilePrinter();
             } else {
                 initializeNetworkPrinter();
@@ -75,7 +76,7 @@
 
     private void initializeFilePrinter() {
         String ext;
-        if (GraalOptions.PrintBinaryGraphs) {
+        if (PrintBinaryGraphs.getValue()) {
             ext = ".bgv";
         } else {
             ext = ".gv.xml";
@@ -91,7 +92,7 @@
             num = "-" + Integer.toString(++i);
         }
         try {
-            if (GraalOptions.PrintBinaryGraphs) {
+            if (PrintBinaryGraphs.getValue()) {
                 printer = new BinaryGraphPrinter(FileChannel.open(file.toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW));
             } else {
                 printer = new IdealGraphPrinter(new FileOutputStream(file));
@@ -105,10 +106,10 @@
     }
 
     private void initializeNetworkPrinter() {
-        String host = GraalOptions.PrintIdealGraphAddress;
-        int port = GraalOptions.PrintBinaryGraphs ? GraalOptions.PrintBinaryGraphPort : GraalOptions.PrintIdealGraphPort;
+        String host = PrintIdealGraphAddress.getValue();
+        int port = PrintBinaryGraphs.getValue() ? PrintBinaryGraphPort.getValue() : PrintIdealGraphPort.getValue();
         try {
-            if (GraalOptions.PrintBinaryGraphs) {
+            if (PrintBinaryGraphs.getValue()) {
                 printer = new BinaryGraphPrinter(SocketChannel.open(new InetSocketAddress(host, port)));
             } else {
                 IdealGraphPrinter xmlPrinter = new IdealGraphPrinter(new Socket(host, port).getOutputStream());
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -72,7 +72,7 @@
             try {
                 raiseException(message);
             } catch (Exception e) {
-                return message;
+                return message + e.getMessage();
             }
         }
         return null;
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -53,7 +53,7 @@
                 Debug.dump(graph, "Graph");
                 new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 Debug.dump(graph, "Graph");
-                new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
 
                 assertNotInGraph(graph, Invoke.class);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -33,6 +33,7 @@
     public void test0() {
         test("lockObjectSimple", new Object(), new Object());
         test("lockObjectSimple", new Object(), null);
+        test("lockObjectSimple", null, null);
     }
 
     @Test
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Fri Jun 07 14:15:38 2013 +0200
@@ -33,7 +33,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.*;
 import com.oracle.graal.word.*;
@@ -43,7 +42,7 @@
  */
 public class PointerTest extends GraalCompilerTest implements Snippets {
 
-    private static final LocationIdentity ID = LocationNode.createLocation("ID");
+    private static final LocationIdentity ID = new NamedLocationIdentity("ID");
     private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object};
     private final TargetDescription target;
     private final ReplacementsImpl installer;
@@ -78,7 +77,7 @@
     @Test
     public void test_read3() {
         for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
+            assertRead(parse("read" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION);
         }
     }
 
@@ -99,7 +98,7 @@
     @Test
     public void test_write3() {
         for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
+            assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION);
         }
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import java.lang.reflect.*;
@@ -36,7 +37,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
@@ -237,7 +237,7 @@
         }
     }
 
-    private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null;
+    private static final SnippetCounter.Group integerCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("Integer intrinsifications") : null;
     private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification");
 
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 
 /**
  * Method substitutions that are VM-independent.
@@ -39,7 +40,7 @@
             replacements.registerSubstitutions(clazz);
         }
 
-        if (GraalOptions.Intrinsify) {
+        if (Intrinsify.getValue()) {
             replacements.registerSubstitutions(MathSubstitutionsX86.class);
             replacements.registerSubstitutions(DoubleSubstitutions.class);
             replacements.registerSubstitutions(FloatSubstitutions.class);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -284,34 +285,8 @@
         if (newInstance instanceof ValueNode && (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) {
             StructuredGraph graph = (StructuredGraph) newInstance.graph();
             for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) {
-                for (ProxyNode vpn : checkCastNode.usages().filter(ProxyNode.class).snapshot()) {
-                    graph.replaceFloating(vpn, checkCastNode);
-                }
                 for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
-                    if (checkCastUsage instanceof ValueAnchorNode) {
-                        ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage;
-                        graph.removeFixed(valueAnchorNode);
-                    } else if (checkCastUsage instanceof UnboxNode) {
-                        UnboxNode unbox = (UnboxNode) checkCastUsage;
-                        unbox.replaceAtUsages(newInstance);
-                        graph.removeFixed(unbox);
-                    } else if (checkCastUsage instanceof MethodCallTargetNode) {
-                        MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
-                        assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(checkCastNode) +
-                                        " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " +
-                                        checkCastCallTarget.targetMethod();
-                        checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object());
-                    } else if (checkCastUsage instanceof FrameState) {
-                        checkCastUsage.replaceFirstInput(checkCastNode, null);
-                    } else if (checkCastUsage instanceof ReturnNode && checkCastNode.object().stamp() == StampFactory.forNodeIntrinsic()) {
-                        checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object());
-                    } else if (checkCastUsage instanceof IsNullNode) {
-                        assert checkCastUsage.usages().count() == 1 && checkCastUsage.usages().first().predecessor() == checkCastNode;
-                        graph.replaceFloating((FloatingNode) checkCastUsage, LogicConstantNode.contradiction(graph));
-                    } else {
-                        Debug.dump(graph, "exception");
-                        assert false : sourceLocation(checkCastUsage) + " has unexpected usage " + checkCastUsage + " of checkcast at " + sourceLocation(checkCastNode);
-                    }
+                    checkCheckCastUsage(graph, newInstance, checkCastNode, checkCastUsage);
                 }
                 FixedNode next = checkCastNode.next();
                 checkCastNode.setNext(null);
@@ -320,4 +295,47 @@
             }
         }
     }
+
+    private static void checkCheckCastUsage(StructuredGraph graph, Node intrinsifiedNode, Node input, Node usage) {
+        if (usage instanceof ValueAnchorNode) {
+            ValueAnchorNode valueAnchorNode = (ValueAnchorNode) usage;
+            valueAnchorNode.removeAnchoredNode((ValueNode) input);
+            Debug.log("%s: Removed a ValueAnchor input", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof UnboxNode) {
+            UnboxNode unbox = (UnboxNode) usage;
+            unbox.replaceAtUsages(intrinsifiedNode);
+            graph.removeFixed(unbox);
+            Debug.log("%s: Removed an UnboxNode", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof MethodCallTargetNode) {
+            MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) usage;
+            assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(input) +
+                            " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " + checkCastCallTarget.targetMethod();
+            usage.replaceFirstInput(input, intrinsifiedNode);
+            Debug.log("%s: Checkcast used in an other node intrinsic", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof FrameState) {
+            usage.replaceFirstInput(input, null);
+            Debug.log("%s: Checkcast used in a FS", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof ReturnNode && ((ValueNode) intrinsifiedNode).stamp() == StampFactory.forNodeIntrinsic()) {
+            usage.replaceFirstInput(input, intrinsifiedNode);
+            Debug.log("%s: Checkcast used in a return with forNodeIntrinsic stamp", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof IsNullNode) {
+            assert usage.usages().count() == 1 && usage.usages().first().predecessor() == input;
+            graph.replaceFloating((FloatingNode) usage, LogicConstantNode.contradiction(graph));
+            Debug.log("%s: Replaced IsNull with false", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof ProxyNode) {
+            ProxyNode proxy = (ProxyNode) usage;
+            assert proxy.type() == PhiType.Value;
+            ProxyNode newProxy = graph.unique(new ProxyNode((ValueNode) intrinsifiedNode, proxy.proxyPoint(), PhiType.Value, proxy.getIdentity()));
+            for (Node proxyUsage : usage.usages().snapshot()) {
+                checkCheckCastUsage(graph, newProxy, proxy, proxyUsage);
+            }
+        } else if (usage instanceof PiNode) {
+            for (Node piUsage : usage.usages().snapshot()) {
+                checkCheckCastUsage(graph, intrinsifiedNode, usage, piUsage);
+            }
+        } else {
+            Debug.dump(graph, "exception");
+            assert false : sourceLocation(usage) + " has unexpected usage " + usage + " of checkcast at " + sourceLocation(input);
+        }
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Jun 07 14:15:38 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -320,9 +321,9 @@
             graphBuilder.apply(graph);
 
             new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
-            if (GraalOptions.OptCanonicalizer) {
+            if (OptCanonicalizer.getValue()) {
                 new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
-                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(graph);
             }
 
             return graph;
@@ -335,9 +336,9 @@
          * @param callee the graph that was inlined into {@code caller}
          */
         protected void afterInline(StructuredGraph caller, StructuredGraph callee) {
-            if (GraalOptions.OptCanonicalizer) {
+            if (OptCanonicalizer.getValue()) {
                 new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller);
-                new CanonicalizerPhase.Instance(runtime, assumptions).apply(caller);
+                new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(caller);
             }
         }
 
@@ -350,8 +351,8 @@
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
 
             new DeadCodeEliminationPhase().apply(graph);
-            if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+            if (OptCanonicalizer.getValue()) {
+                new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(graph);
             }
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Jun 07 14:15:38 2013 +0200
@@ -34,6 +34,7 @@
 import com.oracle.graal.loop.*;
 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.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -384,7 +385,7 @@
             new NodeIntrinsificationPhase(runtime).apply(snippetCopy);
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy);
 
-            new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy);
+            new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), true, 0, null).apply(snippetCopy);
         }
         NodeIntrinsificationVerificationPhase.verify(snippetCopy);
 
@@ -440,8 +441,8 @@
                 if (loopBegin != null) {
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     int mark = snippetCopy.getMark();
-                    LoopTransformations.fullUnroll(loop, runtime, replacements.getAssumptions());
-                    new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy);
+                    LoopTransformations.fullUnroll(loop, runtime, replacements.getAssumptions(), true);
+                    new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), true, mark, null).apply(snippetCopy);
                 }
                 FixedNode explodeLoopNext = explodeLoop.next();
                 explodeLoop.clearSuccessors();
@@ -723,10 +724,14 @@
             } else {
                 returnValue = (ValueNode) duplicates.get(returnNode.result());
             }
-            assert returnValue != null || replacee.usages().isEmpty();
-            replacer.replace(replacee, returnValue);
+            Node returnDuplicate = duplicates.get(returnNode);
+            if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
+                replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor());
+            } else {
+                assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages();
+                replacer.replace(replacee, returnValue);
 
-            Node returnDuplicate = duplicates.get(returnNode);
+            }
             if (returnDuplicate.isAlive()) {
                 returnDuplicate.clearInputs();
                 returnDuplicate.replaceAndDelete(next);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -92,6 +92,9 @@
                 }
             }
             if (!couldSet) {
+                if (isSubstitutionGraph()) {
+                    return this;
+                }
                 throw new GraalInternalError("Wrong usage of branch probability injection!");
             }
             return condition;
@@ -99,6 +102,10 @@
         return this;
     }
 
+    private boolean isSubstitutionGraph() {
+        return usages().count() == 1 && usages().first() instanceof ReturnNode;
+    }
+
     /**
      * This intrinsic should only be used for the condition of an if statement. The parameter
      * condition should also only denote a simple condition and not a combined condition involving
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,9 +22,12 @@
  */
 package com.oracle.graal.replacements.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
@@ -62,8 +65,8 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph(), 1);
-        WriteNode write = graph().add(new WriteNode(object, value, location, WriteBarrierType.NONE));
+        IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, value.kind(), displacement, offset, graph(), 1);
+        WriteNode write = graph().add(new WriteNode(object, value, location, WriteBarrierType.NONE, value.kind() == Kind.Object));
         graph().replaceFixedWithFixed(this, write);
     }
 }
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Fri Jun 07 14:15:38 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -35,10 +35,101 @@
  */
 public class SPARC extends Architecture {
 
-    // SPARC: Define registers.
+    // @formatter:off
+
+    public static final RegisterCategory CPU = new RegisterCategory("CPU");
+    public static final RegisterCategory FPU = new RegisterCategory("FPU");
+
+    // General purpose registers
+    public static final Register r0  = new Register(0, 0, "r0", CPU);
+    public static final Register r1  = new Register(1, 1, "r1", CPU);
+    public static final Register r2  = new Register(2, 2, "r2", CPU);
+    public static final Register r3  = new Register(3, 3, "r3", CPU);
+    public static final Register r4  = new Register(4, 4, "r4", CPU);
+    public static final Register r5  = new Register(5, 5, "r5", CPU);
+    public static final Register r6  = new Register(6, 6, "r6", CPU);
+    public static final Register r7  = new Register(7, 7, "r7", CPU);
+    public static final Register r8  = new Register(8, 8, "r8", CPU);
+    public static final Register r9  = new Register(9, 9, "r9", CPU);
+    public static final Register r10 = new Register(10, 10, "r10", CPU);
+    public static final Register r11 = new Register(11, 11, "r11", CPU);
+    public static final Register r12 = new Register(12, 12, "r12", CPU);
+    public static final Register r13 = new Register(13, 13, "r13", CPU);
+    public static final Register r14 = new Register(14, 14, "r14", CPU);
+    public static final Register r15 = new Register(15, 15, "r15", CPU);
+    public static final Register r16 = new Register(16, 16, "r16", CPU);
+    public static final Register r17 = new Register(17, 17, "r17", CPU);
+    public static final Register r18 = new Register(18, 18, "r18", CPU);
+    public static final Register r19 = new Register(19, 19, "r19", CPU);
+    public static final Register r20 = new Register(20, 20, "r20", CPU);
+    public static final Register r21 = new Register(21, 21, "r21", CPU);
+    public static final Register r22 = new Register(22, 22, "r22", CPU);
+    public static final Register r23 = new Register(23, 23, "r23", CPU);
+    public static final Register r24 = new Register(24, 24, "r24", CPU);
+    public static final Register r25 = new Register(25, 25, "r25", CPU);
+    public static final Register r26 = new Register(26, 26, "r26", CPU);
+    public static final Register r27 = new Register(27, 27, "r27", CPU);
+    public static final Register r28 = new Register(28, 28, "r28", CPU);
+    public static final Register r29 = new Register(29, 29, "r29", CPU);
+    public static final Register r30 = new Register(30, 30, "r30", CPU);
+    public static final Register r31 = new Register(31, 31, "r31", CPU);
+
+    public static final Register g0 = r0;
+    public static final Register g1 = r1;
+    public static final Register g2 = r2;
+    public static final Register g3 = r3;
+    public static final Register g4 = r4;
+    public static final Register g5 = r5;
+    public static final Register g6 = r6;
+    public static final Register g7 = r7;
+
+    public static final Register i0 = r24;
+    public static final Register i1 = r25;
+    public static final Register i2 = r26;
+    public static final Register i3 = r27;
+    public static final Register i4 = r28;
+    public static final Register i5 = r29;
+    public static final Register i6 = r30;
+    public static final Register i7 = r31;
+
+    public static final Register o0 = r8;
+    public static final Register o1 = r9;
+    public static final Register o2 = r10;
+    public static final Register o3 = r11;
+    public static final Register o4 = r12;
+    public static final Register o5 = r13;
+    public static final Register o6 = r14;
+    public static final Register o7 = r15;
+
+    public static final Register[] gprRegisters = {
+        r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
+         r8,  r9, r10, r11, r12, r13, r14, r15,
+        r16, r17, r18, r19, r20, r21, r22, r23,
+        r24, r25, r26, r27, r28, r29, r30, r31
+    };
+
+    // Floating point registers
+    public static final Register f0 = new Register(32, 0, "f0", FPU);
+    public static final Register f1 = new Register(33, 1, "f1", FPU);
+    public static final Register f2 = new Register(34, 2, "f2", FPU);
+    public static final Register f3 = new Register(35, 3, "f3", FPU);
+    public static final Register f4 = new Register(36, 4, "f4", FPU);
+    public static final Register f5 = new Register(37, 5, "f5", FPU);
+    public static final Register f6 = new Register(38, 6, "f6", FPU);
+    public static final Register f7 = new Register(39, 7, "f7", FPU);
+
+    public static final Register[] allRegisters = {
+        // GPR
+        r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
+        r8,  r9, r10, r11, r12, r13, r14, r15,
+       r16, r17, r18, r19, r20, r21, r22, r23,
+       r24, r25, r26, r27, r28, r29, r30, r31,
+        // FPU
+        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+    };
 
     public SPARC() {
-        super("SPARC", 8, ByteOrder.LITTLE_ENDIAN, null, LOAD_STORE | STORE_STORE, 1, 0, 8);
+        super("SPARC", 8, ByteOrder.LITTLE_ENDIAN, allRegisters, LOAD_STORE | STORE_STORE, 1, 0, 8);
         // SPARC: Fix architecture parameters.
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -32,11 +30,11 @@
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
 import com.oracle.graal.nodes.virtual.*;
 
-class BlockState {
+public class BlockState {
 
-    private final IdentityHashMap<VirtualObjectNode, ObjectState> objectStates = new IdentityHashMap<>();
-    private final IdentityHashMap<ValueNode, VirtualObjectNode> objectAliases;
-    private final IdentityHashMap<ValueNode, ValueNode> scalarAliases;
+    protected final IdentityHashMap<VirtualObjectNode, ObjectState> objectStates = new IdentityHashMap<>();
+    protected final IdentityHashMap<ValueNode, VirtualObjectNode> objectAliases;
+    protected final IdentityHashMap<ValueNode, ValueNode> scalarAliases;
     final HashMap<ReadCacheEntry, ValueNode> readCache;
 
     static class ReadCacheEntry {
@@ -146,6 +144,10 @@
         return new BlockState(this);
     }
 
+    public BlockState cloneEmptyState() {
+        return new BlockState();
+    }
+
     public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, GraphEffectList materializeEffects) {
         PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment();
         List<AllocatedObjectNode> objects = new ArrayList<>(2);
@@ -159,7 +161,7 @@
 
     private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List<AllocatedObjectNode> objects, List<int[]> locks, List<ValueNode> values, List<ValueNode> otherAllocations,
                     EscapeState state) {
-        trace("materializing %s", virtual);
+        VirtualUtil.trace("materializing %s", virtual);
         ObjectState obj = getObjectState(virtual);
 
         ValueNode[] entries = obj.getEntries();
@@ -241,34 +243,14 @@
         return objectStates + " " + readCache;
     }
 
-    public static BlockState meetAliases(List<BlockState> states) {
-        BlockState newState = new BlockState();
-
-        newState.objectAliases.putAll(states.get(0).objectAliases);
+    public void meetAliases(List<? extends BlockState> states) {
+        objectAliases.putAll(states.get(0).objectAliases);
+        scalarAliases.putAll(states.get(0).scalarAliases);
         for (int i = 1; i < states.size(); i++) {
             BlockState state = states.get(i);
-            for (Map.Entry<ValueNode, VirtualObjectNode> entry : states.get(0).objectAliases.entrySet()) {
-                if (state.objectAliases.containsKey(entry.getKey())) {
-                    assert state.objectAliases.get(entry.getKey()) == entry.getValue();
-                } else {
-                    newState.objectAliases.remove(entry.getKey());
-                }
-            }
+            meetMaps(objectAliases, state.objectAliases);
+            meetMaps(scalarAliases, state.scalarAliases);
         }
-
-        newState.scalarAliases.putAll(states.get(0).scalarAliases);
-        for (int i = 1; i < states.size(); i++) {
-            BlockState state = states.get(i);
-            for (Map.Entry<ValueNode, ValueNode> entry : states.get(0).scalarAliases.entrySet()) {
-                if (state.scalarAliases.containsKey(entry.getKey())) {
-                    assert state.scalarAliases.get(entry.getKey()) == entry.getValue();
-                } else {
-                    newState.scalarAliases.remove(entry.getKey());
-                }
-            }
-        }
-
-        return newState;
     }
 
     public Map<ReadCacheEntry, ValueNode> getReadCache() {
@@ -286,14 +268,14 @@
         return objectAliasesEqual && objectStatesEqual && readCacheEqual && scalarAliasesEqual;
     }
 
-    private static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
+    protected static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
         if (left.size() != right.size()) {
             return false;
         }
         return compareMapsNoSize(left, right);
     }
 
-    private static <K, V> boolean compareMapsNoSize(Map<K, V> left, Map<K, V> right) {
+    protected static <K, V> boolean compareMapsNoSize(Map<K, V> left, Map<K, V> right) {
         if (left == right) {
             return true;
         }
@@ -309,4 +291,16 @@
         return true;
     }
 
+    protected static <U, V> void meetMaps(Map<U, V> target, Map<U, V> source) {
+        Iterator<Map.Entry<U, V>> iter = target.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<U, V> entry = iter.next();
+            if (source.containsKey(entry.getKey())) {
+                assert source.get(entry.getKey()) == entry.getValue();
+            } else {
+                iter.remove();
+            }
+        }
+    }
+
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Fri Jun 07 14:15:38 2013 +0200
@@ -215,7 +215,7 @@
                 FixedNode next = node.next();
                 node.setNext(null);
                 node.replaceAtPredecessor(next);
-                obsoleteNodes.add(node);
+                assert obsoleteNodes.add(node);
             }
         });
     }
@@ -250,7 +250,7 @@
                     FixedNode next = ((FixedWithNextNode) node).next();
                     ((FixedWithNextNode) node).setNext(null);
                     node.replaceAtPredecessor(next);
-                    obsoleteNodes.add(node);
+                    assert obsoleteNodes.add(node);
                 }
             }
         });
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -40,17 +42,19 @@
     private final GraphCache cache;
     private final OptimisticOptimizations optimisticOpts;
     private final boolean readElimination;
+    private final CanonicalizerPhase canonicalizer;
 
-    public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) {
+    public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination, CanonicalizerPhase canonicalizer) {
         this.replacements = replacements;
         this.cache = cache;
         this.plan = plan;
         this.optimisticOpts = optimisticOpts;
         this.readElimination = readElimination;
+        this.canonicalizer = canonicalizer;
     }
 
     public static final void trace(String format, Object... obj) {
-        if (GraalOptions.TraceEscapeAnalysis) {
+        if (TraceEscapeAnalysis.getValue()) {
             Debug.log(format, obj);
         }
     }
@@ -63,17 +67,17 @@
 
     private void runIterations(final StructuredGraph graph, final boolean simple, final HighTierContext context) {
         Boolean continueIteration = true;
-        for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) {
+        for (int iteration = 0; iteration < EscapeAnalysisIterations.getValue() && continueIteration; iteration++) {
             continueIteration = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
 
                 @Override
                 public Boolean call() {
                     boolean progress = false;
-                    PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination);
+                    PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination, canonicalizer);
                     boolean eaResult = ea.runAnalysis(graph, context);
                     progress |= eaResult;
 
-                    Map<Invoke, Double> hints = GraalOptions.PEAInliningHints ? PartialEscapeAnalysisPhase.getHints(graph) : null;
+                    Map<Invoke, Double> hints = PEAInliningHints.getValue() ? PartialEscapeAnalysisPhase.getHints(graph) : null;
 
                     InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, replacements, context.getAssumptions(), cache, plan, optimisticOpts);
                     inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE);
@@ -82,8 +86,8 @@
 
                     new DeadCodeEliminationPhase().apply(graph);
 
-                    if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase().apply(graph, context);
+                    if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
+                        canonicalizer.apply(graph, context);
                         new IterativeConditionalEliminationPhase().apply(graph, context);
                     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -35,47 +36,43 @@
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
 
-public class PartialEscapeAnalysisPhase extends BasePhase<HighTierContext> {
+public class PartialEscapeAnalysisPhase extends BasePhase<PhaseContext> {
+
+    public abstract static class Closure<T> extends ReentrantBlockIterator.BlockIteratorClosure<T> {
 
-    private final CustomCanonicalizer customCanonicalizer;
-    private final boolean iterative;
-    private final boolean readElimination;
+        public abstract boolean hasChanged();
 
-    public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination) {
-        this(null, iterative, readElimination);
+        public abstract void applyEffects();
     }
 
-    public PartialEscapeAnalysisPhase(CustomCanonicalizer customCanonicalizer, boolean iterative, boolean readElimination) {
-        this.customCanonicalizer = customCanonicalizer;
+    private final boolean iterative;
+    private final boolean readElimination;
+    private final CanonicalizerPhase canonicalizer;
+
+    public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination, CanonicalizerPhase canonicalizer) {
         this.iterative = iterative;
         this.readElimination = readElimination;
-    }
-
-    public static final void trace(String format, Object... obj) {
-        if (GraalOptions.TraceEscapeAnalysis) {
-            Debug.log(format, obj);
-        }
+        this.canonicalizer = canonicalizer;
     }
 
     @Override
-    protected void run(StructuredGraph graph, HighTierContext context) {
+    protected void run(StructuredGraph graph, PhaseContext context) {
         runAnalysis(graph, context);
     }
 
-    public boolean runAnalysis(final StructuredGraph graph, final HighTierContext context) {
-        if (!matches(graph, GraalOptions.EscapeAnalyzeOnly)) {
+    public boolean runAnalysis(final StructuredGraph graph, final PhaseContext context) {
+        if (!VirtualUtil.matches(graph, EscapeAnalyzeOnly.getValue())) {
             return false;
         }
 
         if (!readElimination) {
             boolean analyzableNodes = false;
             for (Node node : graph.getNodes()) {
-                if (node instanceof VirtualizableRoot) {
+                if (node instanceof VirtualizableAllocation) {
                     analyzableNodes = true;
                     break;
                 }
@@ -87,7 +84,7 @@
 
         boolean continueIteration = true;
         boolean changed = false;
-        for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) {
+        for (int iteration = 0; iteration < EscapeAnalysisIterations.getValue() && continueIteration; iteration++) {
             boolean currentChanged = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
 
                 @Override
@@ -95,23 +92,22 @@
 
                     SchedulePhase schedule = new SchedulePhase();
                     schedule.apply(graph, false);
-                    PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, context.getRuntime(), context.getAssumptions());
-                    ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null);
+                    Closure<?> closure = createAnalysisClosure(context, schedule);
+                    ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
 
                     if (!closure.hasChanged()) {
                         return false;
                     }
 
                     // apply the effects collected during the escape analysis iteration
-                    List<Node> obsoleteNodes = closure.applyEffects(graph);
+                    closure.applyEffects();
 
                     Debug.dump(graph, "after PartialEscapeAnalysis iteration");
-                    assert noObsoleteNodes(graph, obsoleteNodes);
 
                     new DeadCodeEliminationPhase().apply(graph);
 
-                    if (GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).apply(graph);
+                    if (OptCanonicalizer.getValue()) {
+                        canonicalizer.apply(graph, context);
                     }
 
                     return true;
@@ -124,85 +120,8 @@
         return changed;
     }
 
-    private static boolean matches(StructuredGraph graph, String filter) {
-        if (filter != null) {
-            if (filter.startsWith("~")) {
-                ResolvedJavaMethod method = graph.method();
-                return method == null || !MetaUtil.format("%H.%n", method).contains(filter.substring(1));
-            } else {
-                ResolvedJavaMethod method = graph.method();
-                return method != null && MetaUtil.format("%H.%n", method).contains(filter);
-            }
-        }
-        return true;
-    }
-
-    static boolean noObsoleteNodes(StructuredGraph graph, List<Node> obsoleteNodes) {
-        // helper code that determines the paths that keep obsolete nodes alive:
-
-        NodeFlood flood = graph.createNodeFlood();
-        IdentityHashMap<Node, Node> path = new IdentityHashMap<>();
-        flood.add(graph.start());
-        for (Node current : flood) {
-            if (current instanceof AbstractEndNode) {
-                AbstractEndNode end = (AbstractEndNode) current;
-                flood.add(end.merge());
-                if (!path.containsKey(end.merge())) {
-                    path.put(end.merge(), end);
-                }
-            } else {
-                for (Node successor : current.successors()) {
-                    flood.add(successor);
-                    if (!path.containsKey(successor)) {
-                        path.put(successor, current);
-                    }
-                }
-            }
-        }
-
-        for (Node node : obsoleteNodes) {
-            if (node instanceof FixedNode) {
-                assert !flood.isMarked(node) : node;
-            }
-        }
-
-        for (Node node : graph.getNodes()) {
-            if (node instanceof LocalNode) {
-                flood.add(node);
-            }
-            if (flood.isMarked(node)) {
-                for (Node input : node.inputs()) {
-                    flood.add(input);
-                    if (!path.containsKey(input)) {
-                        path.put(input, node);
-                    }
-                }
-            }
-        }
-        for (Node current : flood) {
-            for (Node input : current.inputs()) {
-                flood.add(input);
-                if (!path.containsKey(input)) {
-                    path.put(input, current);
-                }
-            }
-        }
-        boolean success = true;
-        for (Node node : obsoleteNodes) {
-            if (flood.isMarked(node)) {
-                TTY.print("offending node path:");
-                Node current = node;
-                while (current != null) {
-                    TTY.println(current.toString());
-                    current = path.get(current);
-                    if (current != null && current instanceof FixedNode && !obsoleteNodes.contains(current)) {
-                        break;
-                    }
-                }
-                success = false;
-            }
-        }
-        return success;
+    protected Closure<?> createAnalysisClosure(PhaseContext context, SchedulePhase schedule) {
+        return new PartialEscapeClosure<>(schedule, context.getRuntime(), context.getAssumptions());
     }
 
     public static Map<Invoke, Double> getHints(StructuredGraph graph) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,7 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -34,13 +35,11 @@
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
@@ -49,7 +48,7 @@
 import com.oracle.graal.virtual.phases.ea.BlockState.ReadCacheEntry;
 import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
 
-class PartialEscapeClosure extends BlockIteratorClosure<BlockState> {
+public class PartialEscapeClosure<BlockT extends BlockState> extends PartialEscapeAnalysisPhase.Closure<BlockT> {
 
     public static final DebugMetric METRIC_MATERIALIZATIONS = Debug.metric("Materializations");
     public static final DebugMetric METRIC_MATERIALIZATIONS_PHI = Debug.metric("MaterializationsPhi");
@@ -73,8 +72,8 @@
 
     private boolean changed;
 
-    public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
-        this.usages = usages;
+    public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
+        this.usages = schedule.getCFG().graph.createNodeBitMap();
         this.schedule = schedule;
         this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions);
         this.blockEffects = new BlockMap<>(schedule.getCFG());
@@ -83,14 +82,28 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    protected BlockT getInitialState() {
+        return (BlockT) new BlockState();
+    }
+
+    @Override
     public boolean hasChanged() {
         return changed;
     }
 
-    public List<Node> applyEffects(final StructuredGraph graph) {
-        final ArrayList<Node> obsoleteNodes = new ArrayList<>();
+    @Override
+    public void applyEffects() {
+        final StructuredGraph graph = schedule.getCFG().graph;
+        final ArrayList<Node> obsoleteNodes = new ArrayList<>(0);
         BlockIteratorClosure<Void> closure = new BlockIteratorClosure<Void>() {
 
+            @Override
+            protected Void getInitialState() {
+                return null;
+            }
+
             private void apply(GraphEffectList effects, Object context) {
                 if (!effects.isEmpty()) {
                     Debug.log(" ==== effects for %s", context);
@@ -126,8 +139,8 @@
                 return info.exitStates;
             }
         };
-        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), null, null);
-        return obsoleteNodes;
+        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
+        assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
     }
 
     public Map<Invoke, Double> getHints() {
@@ -135,11 +148,11 @@
     }
 
     @Override
-    protected BlockState processBlock(Block block, BlockState state) {
+    protected BlockT processBlock(Block block, BlockT state) {
         GraphEffectList effects = blockEffects.get(block);
         tool.setEffects(effects);
 
-        trace("\nBlock: %s (", block);
+        VirtualUtil.trace("\nBlock: %s (", block);
         List<ScheduledNode> nodeList = schedule.getBlockToNodesMap().get(block);
 
         FixedWithNextNode lastFixedNode = null;
@@ -147,21 +160,21 @@
             boolean deleted;
             boolean isMarked = usages.isMarked(node);
             if (isMarked || node instanceof VirtualizableRoot) {
-                trace("[[%s]] ", node);
+                VirtualUtil.trace("[[%s]] ", node);
                 FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next();
                 deleted = processNode((ValueNode) node, nextFixedNode, state, effects, isMarked);
             } else {
-                trace("%s ", node);
+                VirtualUtil.trace("%s ", node);
                 deleted = false;
             }
-            if (GraalOptions.OptEarlyReadElimination) {
+            if (OptEarlyReadElimination.getValue()) {
                 if (!deleted && node instanceof MemoryCheckpoint) {
                     METRIC_MEMORYCHECKOINT.increment();
                     MemoryCheckpoint checkpoint = (MemoryCheckpoint) node;
                     for (LocationIdentity identity : checkpoint.getLocationIdentities()) {
                         if (identity instanceof ResolvedJavaField) {
                             state.killReadCache((ResolvedJavaField) identity);
-                        } else if (identity == LocationNode.ANY_LOCATION) {
+                        } else if (identity == ANY_LOCATION) {
                             state.killReadCache();
                         }
                     }
@@ -171,11 +184,11 @@
                 lastFixedNode = (FixedWithNextNode) node;
             }
         }
-        trace(")\n    end state: %s\n", state);
+        VirtualUtil.trace(")\n    end state: %s\n", state);
         return state;
     }
 
-    private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockState state, final GraphEffectList effects, boolean isMarked) {
+    private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockT state, final GraphEffectList effects, boolean isMarked) {
         tool.reset(state, node, insertBefore);
         if (node instanceof Virtualizable) {
             ((Virtualizable) node).virtualize(tool);
@@ -268,7 +281,7 @@
                         Invoke invoke = ((MethodCallTargetNode) node).invoke();
                         hints.put(invoke, 5d);
                     }
-                    trace("replacing input %s at %s: %s", input, node, obj);
+                    VirtualUtil.trace("replacing input %s at %s: %s", input, node, obj);
                     replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED);
                 }
             }
@@ -293,9 +306,9 @@
     }
 
     @Override
-    protected BlockState merge(Block merge, List<BlockState> states) {
+    protected BlockT merge(Block merge, List<BlockT> states) {
         assert blockEffects.get(merge).isEmpty();
-        MergeProcessor processor = new MergeProcessor(merge, usages, blockEffects);
+        MergeProcessor<BlockT> processor = new MergeProcessor<>(merge, usages, blockEffects);
         processor.merge(states);
         blockEffects.get(merge).addAll(processor.mergeEffects);
         blockEffects.get(merge).addAll(processor.afterMergeEffects);
@@ -303,20 +316,22 @@
 
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    protected BlockState cloneState(BlockState oldState) {
-        return oldState.cloneState();
+    protected BlockT cloneState(BlockState oldState) {
+        return (BlockT) oldState.cloneState();
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    protected List<BlockState> processLoop(Loop loop, BlockState initialState) {
+    protected List<BlockT> processLoop(Loop loop, BlockT initialState) {
         BlockState loopEntryState = initialState;
         BlockState lastMergedState = initialState;
-        MergeProcessor mergeProcessor = new MergeProcessor(loop.header, usages, blockEffects);
+        MergeProcessor<BlockT> mergeProcessor = new MergeProcessor<>(loop.header, usages, blockEffects);
         for (int iteration = 0; iteration < 10; iteration++) {
-            LoopInfo<BlockState> info = ReentrantBlockIterator.processLoop(this, loop, lastMergedState.cloneState());
+            LoopInfo<BlockT> info = ReentrantBlockIterator.processLoop(this, loop, (BlockT) lastMergedState.cloneState());
 
-            List<BlockState> states = new ArrayList<>();
+            List<BlockT> states = new ArrayList<>();
             states.add(initialState);
             states.addAll(info.endStates);
             mergeProcessor.merge(states);
@@ -399,7 +414,7 @@
         }
     }
 
-    private static class MergeProcessor {
+    private static class MergeProcessor<BlockT extends BlockState> {
 
         private final Block mergeBlock;
         private final MergeNode merge;
@@ -412,7 +427,7 @@
         private final IdentityHashMap<VirtualObjectNode, PhiNode[]> valuePhis = new IdentityHashMap<>();
         private final IdentityHashMap<PhiNode, PhiNode[]> valueObjectMergePhis = new IdentityHashMap<>();
         private final IdentityHashMap<PhiNode, VirtualObjectNode> valueObjectVirtuals = new IdentityHashMap<>();
-        private BlockState newState;
+        private BlockT newState;
 
         public MergeProcessor(Block mergeBlock, NodeBitMap usages, BlockMap<GraphEffectList> blockEffects) {
             this.usages = usages;
@@ -459,8 +474,10 @@
             return result;
         }
 
-        private void merge(List<BlockState> states) {
-            newState = BlockState.meetAliases(states);
+        @SuppressWarnings("unchecked")
+        private void merge(List<BlockT> states) {
+            newState = (BlockT) states.get(0).cloneEmptyState();
+            newState.meetAliases(states);
 
             /*
              * Iterative processing: Merging the materialized/virtual state of virtual objects can
@@ -521,7 +538,13 @@
                             for (int i = 1; i < states.size(); i++) {
                                 ValueNode[] fields = objStates[i].getEntries();
                                 if (phis[index] == null && values[index] != fields[index]) {
-                                    phis[index] = new PhiNode(values[index].kind(), merge);
+                                    Kind kind = values[index].kind();
+                                    if (kind == Kind.Illegal) {
+                                        // Can happen if one of the values is virtual and is only
+                                        // materialized in the following loop.
+                                        kind = Kind.Object;
+                                    }
+                                    phis[index] = new PhiNode(kind, merge);
                                 }
                             }
                         }
@@ -559,7 +582,7 @@
             mergeReadCache(states);
         }
 
-        private boolean processPhi(PhiNode phi, List<BlockState> states) {
+        private boolean processPhi(PhiNode phi, List<BlockT> states) {
             assert states.size() == phi.valueCount();
             int virtualInputs = 0;
             boolean materialized = false;
@@ -643,7 +666,7 @@
             return materialized;
         }
 
-        private void mergeReadCache(List<BlockState> states) {
+        private void mergeReadCache(List<BlockT> states) {
             for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
                 ReadCacheEntry key = entry.getKey();
                 ValueNode value = entry.getValue();
@@ -682,7 +705,7 @@
             }
         }
 
-        private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List<BlockState> states) {
+        private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List<BlockT> states) {
             ValueNode[] values = new ValueNode[phi.valueCount()];
             for (int i = 0; i < phi.valueCount(); i++) {
                 ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Fri Jun 07 14:15:38 2013 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.virtual.phases.ea;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+public final class VirtualUtil {
+
+    private VirtualUtil() {
+        GraalInternalError.shouldNotReachHere();
+    }
+
+    public static boolean assertNonReachable(StructuredGraph graph, List<Node> obsoleteNodes) {
+        // helper code that determines the paths that keep obsolete nodes alive:
+
+        NodeFlood flood = graph.createNodeFlood();
+        IdentityHashMap<Node, Node> path = new IdentityHashMap<>();
+        flood.add(graph.start());
+        for (Node current : flood) {
+            if (current instanceof AbstractEndNode) {
+                AbstractEndNode end = (AbstractEndNode) current;
+                flood.add(end.merge());
+                if (!path.containsKey(end.merge())) {
+                    path.put(end.merge(), end);
+                }
+            } else {
+                for (Node successor : current.successors()) {
+                    flood.add(successor);
+                    if (!path.containsKey(successor)) {
+                        path.put(successor, current);
+                    }
+                }
+            }
+        }
+
+        for (Node node : obsoleteNodes) {
+            if (node instanceof FixedNode) {
+                assert !flood.isMarked(node) : node;
+            }
+        }
+
+        for (Node node : graph.getNodes()) {
+            if (node instanceof LocalNode) {
+                flood.add(node);
+            }
+            if (flood.isMarked(node)) {
+                for (Node input : node.inputs()) {
+                    flood.add(input);
+                    if (!path.containsKey(input)) {
+                        path.put(input, node);
+                    }
+                }
+            }
+        }
+        for (Node current : flood) {
+            for (Node input : current.inputs()) {
+                flood.add(input);
+                if (!path.containsKey(input)) {
+                    path.put(input, current);
+                }
+            }
+        }
+        boolean success = true;
+        for (Node node : obsoleteNodes) {
+            if (flood.isMarked(node)) {
+                TTY.print("offending node path:");
+                Node current = node;
+                while (current != null) {
+                    TTY.println(current.toString());
+                    current = path.get(current);
+                    if (current != null && current instanceof FixedNode && !obsoleteNodes.contains(current)) {
+                        break;
+                    }
+                }
+                success = false;
+            }
+        }
+        return success;
+    }
+
+    public static void trace(String format, Object... obj) {
+        if (TraceEscapeAnalysis.getValue()) {
+            Debug.log(format, obj);
+        }
+    }
+
+    static boolean matches(StructuredGraph graph, String filter) {
+        if (filter != null) {
+            if (filter.startsWith("~")) {
+                ResolvedJavaMethod method = graph.method();
+                return method == null || !MetaUtil.format("%H.%n", method).contains(filter.substring(1));
+            } else {
+                ResolvedJavaMethod method = graph.method();
+                return method != null && MetaUtil.format("%H.%n", method).contains(filter);
+            }
+        }
+        return true;
+    }
+
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -33,7 +33,6 @@
 import com.oracle.graal.nodes.spi.Virtualizable.State;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 
 class VirtualizerToolImpl implements VirtualizerTool {
 
@@ -91,11 +90,12 @@
         if (valueState == null) {
             obj.setEntry(index, getReplacedValue(value));
         } else {
-            if (valueState.getState() == EscapeState.Virtual) {
-                obj.setEntry(index, value);
-            } else {
-                obj.setEntry(index, valueState.getMaterializedValue());
+            ValueNode newValue = value;
+            if (valueState.getState() != EscapeState.Virtual) {
+                newValue = valueState.getMaterializedValue();
             }
+            assert obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind();
+            obj.setEntry(index, newValue);
         }
     }
 
@@ -149,7 +149,7 @@
 
     @Override
     public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, int[] locks) {
-        trace("{{%s}} ", current);
+        VirtualUtil.trace("{{%s}} ", current);
         if (virtualObject.isAlive()) {
             state.addAndMarkAlias(virtualObject, virtualObject, usages);
         } else {
@@ -165,7 +165,7 @@
 
     @Override
     public int getMaximumEntryCount() {
-        return GraalOptions.MaximumEscapeAnalysisArrayLength;
+        return MaximumEscapeAnalysisArrayLength.getValue();
     }
 
     @Override
@@ -184,14 +184,14 @@
 
     @Override
     public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value) {
-        if (GraalOptions.OptEarlyReadElimination) {
+        if (OptEarlyReadElimination.getValue()) {
             state.addReadCache(object, identity, value);
         }
     }
 
     @Override
     public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity) {
-        if (GraalOptions.OptEarlyReadElimination) {
+        if (OptEarlyReadElimination.getValue()) {
             return state.getReadCache(object, identity);
         }
         return null;
@@ -199,7 +199,7 @@
 
     @Override
     public void killReadCache(ResolvedJavaField identity) {
-        if (GraalOptions.OptEarlyReadElimination) {
+        if (OptEarlyReadElimination.getValue()) {
             state.killReadCache(identity);
         }
     }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.word;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 
 public interface Pointer extends Unsigned {
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Fri Jun 07 14:15:38 2013 +0200
@@ -27,10 +27,10 @@
 import java.lang.annotation.*;
 
 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.calc.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 
 public abstract class Word implements Signed, Unsigned, Pointer {
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Jun 07 14:15:38 2013 +0200
@@ -22,15 +22,16 @@
  */
 package com.oracle.graal.word.phases;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 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.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
@@ -164,7 +165,7 @@
                         Kind readKind = asKind(callTargetNode.returnType());
                         LocationNode location;
                         if (arguments.size() == 2) {
-                            location = makeLocation(graph, arguments.get(1), readKind, LocationNode.ANY_LOCATION);
+                            location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
                         } else {
                             location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
                         }
@@ -176,7 +177,7 @@
                         Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass()));
                         LocationNode location;
                         if (arguments.size() == 3) {
-                            location = makeLocation(graph, arguments.get(1), writeKind, LocationNode.ANY_LOCATION);
+                            location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION);
                         } else {
                             location = makeLocation(graph, arguments.get(1), writeKind, arguments.get(3));
                         }
@@ -309,7 +310,7 @@
     }
 
     private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location) {
-        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp()));
+        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), WriteBarrierType.NONE, false));
         graph.addBeforeFixed(invoke.asNode(), read);
         // The read must not float outside its block otherwise it may float above an explicit zero
         // check on its base address
@@ -318,7 +319,7 @@
     }
 
     private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location) {
-        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE));
+        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE, false));
         write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.asNode(), write);
         return write;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Fri Jun 07 14:15:38 2013 +0200
@@ -123,4 +123,58 @@
         return String.format("%s:%d", source.getName(), startLine);
     }
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + charIndex;
+        result = prime * result + charLength;
+        result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
+        result = prime * result + ((source == null) ? 0 : source.hashCode());
+        result = prime * result + startColumn;
+        result = prime * result + startLine;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof SourceSection)) {
+            return false;
+        }
+        SourceSection other = (SourceSection) obj;
+        if (charIndex != other.charIndex) {
+            return false;
+        }
+        if (charLength != other.charLength) {
+            return false;
+        }
+        if (identifier == null) {
+            if (other.identifier != null) {
+                return false;
+            }
+        } else if (!identifier.equals(other.identifier)) {
+            return false;
+        }
+        if (source == null) {
+            if (other.source != null) {
+                return false;
+            }
+        } else if (!source.equals(other.source)) {
+            return false;
+        }
+        if (startColumn != other.startColumn) {
+            return false;
+        }
+        if (startLine != other.startLine) {
+            return false;
+        }
+        return true;
+    }
+
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Fri Jun 07 14:15:38 2013 +0200
@@ -149,6 +149,7 @@
             // Pass on the source section to the new node.
             newNode.assignSourceSection(sourceSection);
         }
+        onReplace(newNode, reason);
         return (T) this.getParent().replaceChild(this, newNode);
     }
 
@@ -170,6 +171,16 @@
     }
 
     /**
+     * Intended to be implemented by subclasses of {@link Node} to receive a notification when the
+     * node is rewritten. This method is invoked before the actual replace has happened.
+     * 
+     * @param newNode the replacement node
+     * @param reason the reason the replace supplied
+     */
+    protected void onReplace(Node newNode, String reason) {
+    }
+
+    /**
      * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all
      * child nodes.
      * 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Fri Jun 07 14:15:38 2013 +0200
@@ -37,4 +37,11 @@
      * @return the short name
      */
     String shortName() default "";
+
+    Kind kind() default Kind.SPECIALIZED;
+
+    public enum Kind {
+        UNINITIALIZED, SPECIALIZED, GENERIC
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,7 +26,7 @@
 
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
-import javax.tools.Diagnostic.*;
+import javax.tools.Diagnostic.Kind;
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
@@ -47,6 +47,8 @@
     private final TypeMirror invalidAssumption;
     private final DeclaredType childAnnotation;
     private final DeclaredType childrenAnnotation;
+    private final DeclaredType nodeInfoAnnotation;
+    private final DeclaredType nodeInfoKind;
     private final TypeMirror compilerDirectives;
     private final TypeMirror compilerAsserts;
 
@@ -63,6 +65,12 @@
         compilerAsserts = getRequired(context, CompilerAsserts.class);
         assumption = getRequired(context, Assumption.class);
         invalidAssumption = getRequired(context, InvalidAssumptionException.class);
+        nodeInfoAnnotation = getRequired(context, NodeInfo.class);
+        nodeInfoKind = getRequired(context, NodeInfo.Kind.class);
+    }
+
+    public DeclaredType getNodeInfoAnnotation() {
+        return nodeInfoAnnotation;
     }
 
     public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) {
@@ -77,6 +85,10 @@
         return false;
     }
 
+    public DeclaredType getNodeInfoKind() {
+        return nodeInfoKind;
+    }
+
     private DeclaredType getRequired(ProcessorContext context, Class clazz) {
         TypeMirror type = context.getType(clazz);
         if (type == null) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Fri Jun 07 14:15:38 2013 +0200
@@ -40,6 +40,26 @@
  */
 public class Utils {
 
+    public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    public static VariableElement findVariableElement(DeclaredType type, String name) {
+        List<? extends VariableElement> elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements());
+        for (VariableElement variableElement : elements) {
+            if (variableElement.getSimpleName().toString().equals(name)) {
+                return variableElement;
+            }
+        }
+        return null;
+    }
+
     public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
         if (method instanceof CodeExecutableElement) {
             return ((CodeExecutableElement) method).getBody();
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java	Fri Jun 07 14:15:38 2013 +0200
@@ -26,8 +26,8 @@
 
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
-import javax.lang.model.util.*;
 
+import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.api.element.*;
 
 public class CodeAnnotationMirror implements WritableAnnotationMirror {
@@ -60,13 +60,7 @@
     }
 
     public ExecutableElement findExecutableElement(String name) {
-        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(annotationType.asElement().getEnclosedElements());
-        for (ExecutableElement executableElement : elements) {
-            if (executableElement.getSimpleName().toString().equals(name)) {
-                return executableElement;
-            }
-        }
-        return null;
+        return Utils.findExecutableElement(annotationType, name);
     }
 
     public static CodeAnnotationMirror clone(AnnotationMirror mirror) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Fri Jun 07 14:15:38 2013 +0200
@@ -246,23 +246,7 @@
     }
 
     public CodeTreeBuilder doubleQuote(String s) {
-        return startGroup().string("\"").string(s).string("\"").end();
-    }
-
-    public CodeTreeBuilder startDoubleQuote() {
-        startGroup().string("\"");
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string("\"");
-            }
-        });
-        return this;
+        return startGroup().string("\"" + s + "\"").end();
     }
 
     public CodeTreeBuilder string(String chunk1) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java	Fri Jun 07 14:15:38 2013 +0200
@@ -75,23 +75,6 @@
         return count;
     }
 
-    public boolean startsWithSignature(TemplateMethod method) {
-        for (ActualParameter param : getParameters()) {
-            if (!param.getSpecification().isSignature()) {
-                continue;
-            }
-            ActualParameter foundParam = method.findParameter(param.getLocalName());
-            if (foundParam != null) {
-                TypeData actualType = param.getTypeSystemType();
-                TypeData foundType = foundParam.getTypeSystemType();
-                if (actualType == null || foundType == null || !actualType.equalsType(foundType)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
     public boolean hasGenericSignature() {
         List<TypeData> types = getSignature();
         for (TypeData typeData : types) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Fri Jun 07 14:15:38 2013 +0200
@@ -44,8 +44,15 @@
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null);
+        List<ParameterSpec> requiredSpecs = new ArrayList<>(spec.getRequired());
+        spec.getRequired().clear();
+
+        for (ParameterSpec originalSpec : requiredSpecs) {
+            spec.addRequired(new ParameterSpec(originalSpec, Arrays.asList(getNode().getTypeSystem().getGenericType())));
+        }
+
         spec.setVariableRequiredArguments(true);
-        ParameterSpec other = new ParameterSpec("other", nodeTypeMirrors(getNode()));
+        ParameterSpec other = new ParameterSpec("other", Arrays.asList(getNode().getTypeSystem().getGenericType()));
         other.setCardinality(Cardinality.MANY);
         other.setSignature(true);
         other.setIndexed(true);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri Jun 07 14:15:38 2013 +0200
@@ -766,10 +766,55 @@
                 }
                 builder.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
                 prefix = null;
+
+                builder.startStatement().string("StringBuilder message = new StringBuilder(reason)").end();
+                builder.startStatement().startCall("message", "append").doubleQuote(" (").end().end();
+
+                String sep = null;
+                for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) {
+                    if (!parameter.getSpecification().isSignature()) {
+                        continue;
+                    }
+
+                    builder.startStatement();
+                    builder.string("message");
+                    if (sep != null) {
+                        builder.startCall(".append").doubleQuote(sep).end();
+                    }
+                    builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
+                    builder.startCall(".append").doubleQuote(" = ").end();
+                    builder.startCall(".append").string(parameter.getLocalName()).end();
+                    builder.end();
+
+                    if (!Utils.isPrimitive(parameter.getType())) {
+                        builder.startIf().string(parameter.getLocalName() + " != null").end();
+                        builder.startBlock();
+                    }
+                    builder.startStatement();
+                    if (Utils.isPrimitive(parameter.getType())) {
+                        builder.startCall("message.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end();
+                    } else {
+                        builder.startCall("message.append").doubleQuote(" (").end();
+                        builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
+                        builder.startCall(".append").doubleQuote(")").end();
+                    }
+                    builder.end();
+                    if (!Utils.isPrimitive(parameter.getType())) {
+                        builder.end();
+                    }
+
+                    sep = ", ";
+                }
+
+                builder.startStatement().startCall("message", "append").doubleQuote(")").end().end();
             }
 
             addInternalValueParameters(method, node.getGenericSpecialization(), true);
 
+            if (specialize) {
+                method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
+            }
+
             List<SpecializationData> specializations = node.getSpecializations();
             if (!specialize && !node.getGenericSpecialization().isUseSpecializationsForGeneric()) {
                 specializations = Arrays.asList(node.getGenericSpecialization());
@@ -864,6 +909,7 @@
 
                 builder.startStatement().startCall("super", "replace");
                 builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end();
+                builder.string("message.toString()");
                 builder.end().end();
 
                 if (current.getReturnSignature().isVoid()) {
@@ -1336,6 +1382,27 @@
                 baseType = nodeGen.asType();
             }
             CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
+
+            String shortName = specialization.getNode().getShortName();
+            CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
+            if (shortName != null) {
+                nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
+            }
+
+            DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind();
+            VariableElement kind;
+            if (specialization.isGeneric()) {
+                kind = Utils.findVariableElement(nodeinfoKind, "GENERIC");
+            } else if (specialization.isUninitialized()) {
+                kind = Utils.findVariableElement(nodeinfoKind, "UNINITIALIZED");
+            } else {
+                kind = Utils.findVariableElement(nodeinfoKind, "SPECIALIZED");
+            }
+
+            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(kind));
+
+            clazz.getAnnotationMirrors().add(nodeInfoMirror);
+
             return clazz;
         }
 
@@ -1373,12 +1440,13 @@
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
-            ExecutableTypeData foundEvaluatedPrimaryType = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
+            List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
 
-            if (execType == foundEvaluatedPrimaryType || foundEvaluatedPrimaryType == null) {
+            if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
                 builder.tree(createFunctionalExecute(builder, specialization, execType));
             } else if (needsCastingExecuteMethod(execType, primaryType)) {
-                builder.tree(createCastingExecute(builder, specialization, execType, foundEvaluatedPrimaryType));
+                assert !primaryExecutes.isEmpty();
+                builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
             } else {
                 return null;
             }
@@ -1420,7 +1488,7 @@
             return false;
         }
 
-        private ExecutableTypeData findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
+        private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
             TypeData primaryType = specialization.getReturnType().getTypeSystemType();
             List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
 
@@ -1432,19 +1500,24 @@
                 filteredTypes.add(compareType);
             }
 
-            for (ExecutableTypeData compareType : filteredTypes) {
-                if (compareType.startsWithSignature(specialization)) {
-                    return compareType;
+            // no direct matches found use generic where the type is Object
+            if (filteredTypes.isEmpty()) {
+                for (ExecutableTypeData compareType : otherTypes) {
+                    if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
+                        filteredTypes.add(compareType);
+                    }
                 }
             }
 
-            for (ExecutableTypeData compareType : otherTypes) {
-                if (compareType.startsWithSignature(specialization)) {
-                    return compareType;
+            if (filteredTypes.isEmpty()) {
+                for (ExecutableTypeData compareType : otherTypes) {
+                    if (compareType.getType().isGeneric()) {
+                        filteredTypes.add(compareType);
+                    }
                 }
             }
 
-            return null;
+            return filteredTypes;
         }
 
         private CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
@@ -1558,7 +1631,7 @@
             if (next != null) {
                 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
                 returnBuilder.tree(createDeoptimize(builder));
-                returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null));
+                returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed"));
                 returnSpecialized = returnBuilder.getRoot();
             }
             builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false));
@@ -1592,6 +1665,7 @@
                 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
                 returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
                 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
+                returnBuilder.doubleQuote("Uninitialized");
                 returnBuilder.end();
             } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
                 emitEncounteredSynthetic(builder);
@@ -1623,13 +1697,13 @@
                 for (SpecializationThrowsData exception : specialization.getExceptions()) {
                     builder.end().startCatchBlock(exception.getJavaClass(), "ex");
                     builder.tree(createDeoptimize(builder));
-                    builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null));
+                    builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
                 }
                 builder.end();
             }
             if (!specialization.getAssumptions().isEmpty()) {
                 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
-                builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null));
+                builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed"));
                 builder.end();
             }
 
@@ -1734,7 +1808,8 @@
                 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
                 builder.tree(createDeoptimize(builder));
                 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false));
-                builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param));
+                builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param,
+                                "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType())));
                 builder.end(); // catch block
             }
 
@@ -1768,19 +1843,29 @@
 
             builder.startCall(execType.getMethodName());
 
-            List<ActualParameter> signatureParameters = getModel().getSignatureParameters();
             int index = 0;
             for (ActualParameter parameter : execType.getParameters()) {
 
                 if (!parameter.getSpecification().isSignature()) {
                     builder.string(parameter.getLocalName());
                 } else {
-                    if (index < signatureParameters.size()) {
-                        ActualParameter specializationParam = signatureParameters.get(index);
+                    if (index < targetField.getExecuteWith().size()) {
+                        NodeChildData child = targetField.getExecuteWith().get(index);
+
+                        ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
+                        List<ActualParameter> specializationParams = getModel().findParameters(spec);
+
+                        if (specializationParams.isEmpty()) {
+                            builder.defaultValue(parameter.getType());
+                            continue;
+                        }
+
+                        ActualParameter specializationParam = specializationParams.get(0);
 
                         TypeData targetType = parameter.getTypeSystemType();
                         TypeData sourceType = specializationParam.getTypeSystemType();
                         String localName = specializationParam.getLocalName();
+
                         if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
                             localName = "ex.getResult()";
                             sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
@@ -1850,13 +1935,14 @@
             return builder.getRoot();
         }
 
-        private CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam) {
+        private CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) {
 
             SpecializationData generic = nextSpecialization.getNode().getGenericSpecialization();
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
             specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
             specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class");
             addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true);
+            specializeCall.doubleQuote(reason);
             specializeCall.end().end();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Fri Jun 07 14:15:38 2013 +0200
@@ -51,6 +51,8 @@
     private List<ShortCircuitData> shortCircuits;
     private List<String> assumptions;
 
+    private String shortName;
+
     public NodeData(TypeElement type, String id) {
         super(type, null, null);
         this.nodeId = id;
@@ -72,6 +74,14 @@
         this.assumptions = splitSource.assumptions;
     }
 
+    void setShortName(String shortName) {
+        this.shortName = shortName;
+    }
+
+    public String getShortName() {
+        return shortName;
+    }
+
     public boolean isSplitByMethodName() {
         return splitByMethodName;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Fri Jun 07 14:15:38 2013 +0200
@@ -32,6 +32,7 @@
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.api.codegen.NodeClass.InheritNode;
+import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality;
 import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind;
@@ -577,6 +578,11 @@
                 }
             }
         }
+        AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class);
+        if (nodeInfoMirror != null) {
+            nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"));
+        }
+
         nodeData.setAssumptions(new ArrayList<>(assumptionsList));
         nodeData.setNodeType(nodeType);
         nodeData.setSplitByMethodName(splitByMethodName);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Fri Jun 07 14:15:38 2013 +0200
@@ -55,6 +55,16 @@
         this.allowedTypes = allowedTypes;
     }
 
+    public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes) {
+        this.name = o.name;
+        this.cardinality = o.cardinality;
+        this.signature = o.signature;
+        this.indexed = o.indexed;
+        this.local = o.local;
+        this.typeDefinition = o.typeDefinition;
+        this.allowedTypes = allowedTypes;
+    }
+
     void setTypeDefinition(TypeDef typeDefinition) {
         this.typeDefinition = typeDefinition;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Fri Jun 07 14:15:38 2013 +0200
@@ -133,6 +133,16 @@
         return parameters;
     }
 
+    public List<ActualParameter> findParameters(ParameterSpec spec) {
+        List<ActualParameter> foundParameters = new ArrayList<>();
+        for (ActualParameter param : getReturnTypeAndParameters()) {
+            if (param.getSpecification().equals(spec)) {
+                foundParameters.add(param);
+            }
+        }
+        return foundParameters;
+    }
+
     public ActualParameter findParameter(String valueName) {
         for (ActualParameter param : getReturnTypeAndParameters()) {
             if (param.getLocalName().equals(valueName)) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Fri Jun 07 14:15:38 2013 +0200
@@ -38,4 +38,9 @@
         return specialization;
     }
 
+    @Override
+    public String toString() {
+        return getMethodName();
+    }
+
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionDefinitionNode.java	Fri Jun 07 13:43:13 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionDefinitionNode.java	Fri Jun 07 14:15:38 2013 +0200
@@ -61,6 +61,6 @@
 
     @Override
     public String toString() {
-        return "Function " + name + "@" + Integer.toHexString(hashCode());
+        return "Function " + name;
     }
 }
--- a/make/build-graal.xml	Fri Jun 07 13:43:13 2013 +0200
+++ b/make/build-graal.xml	Fri Jun 07 14:15:38 2013 +0200
@@ -39,6 +39,7 @@
       <src path="${src.dir}/com.oracle.graal.debug"/>
       <src path="${src.dir}/com.oracle.graal.api.replacements"/>
       <src path="${src.dir}/com.oracle.graal.nodes"/>
+      <src path="${src.dir}/com.oracle.graal.options"/>
       <src path="${src.dir}/com.oracle.graal.phases"/>
       <src path="${src.dir}/com.oracle.graal.phases.common"/>
       <src path="${src.dir}/com.oracle.graal.virtual"/>
@@ -80,9 +81,21 @@
         <provider classname="com.oracle.graal.hotspot.replacements.HotSpotNmethodIntrinsics"/>
         <provider classname="com.oracle.graal.replacements.GraalMethodSubstitutions"/>
       </service>
+      <service type="com.oracle.graal.options.Options">
+        <provider classname="com.oracle.graal.compiler.GraalCompiler_Options"/>
+        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Options"/>
+        <provider classname="com.oracle.graal.hotspot.HotSpotGraalRuntime_Options"/>
+        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_Options"/>
+        <provider classname="com.oracle.graal.phases.GraalOptions_Options"/>
+        <provider classname="com.oracle.graal.phases.common.InliningPhase_Options"/>
+        <provider classname="com.oracle.graal.phases.tiers.Suites_Options"/>
+      </service>
       <service type="com.oracle.graal.phases.tiers.CompilerConfiguration">
         <provider classname="com.oracle.graal.compiler.phases.BasicCompilerConfiguration"/>
       </service>
+      <service type="javax.annotation.processing.Processor">
+        <provider classname="com.oracle.graal.options.OptionProcessor"/>
+      </service>
     </jar>
   </target>
   <target name="cleanclasses">
--- a/mx/commands.py	Fri Jun 07 13:43:13 2013 +0200
+++ b/mx/commands.py	Fri Jun 07 14:15:38 2013 +0200
@@ -825,7 +825,7 @@
     def harness(projectscp, vmArgs):
         if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
             subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource])
-        if _vm == 'original' or _vm.endswith('nograal'):
+        if not isGraalEnabled(_vm):
             prefixArgs = ['-esa', '-ea']
         else:
             prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea']
@@ -973,6 +973,11 @@
         clean(cleanArgs)
         tasks.append(t.stop())
 
+        t = Task('IDEConfigCheck')
+        mx.ideclean([])
+        mx.ideinit([])
+        tasks.append(t.stop())
+
         eclipse_exe = os.environ.get('ECLIPSE_EXE')
         if eclipse_exe is not None:
             t = Task('CodeFormatCheck')
@@ -1333,6 +1338,9 @@
         mx.abort('jacocoreport takes only one argument : an output directory')
     mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out])
 
+def isGraalEnabled(vm):
+    return vm != 'original' and not vm.endswith('nograal')
+
 def site(args):
     """create a website containing javadoc and the project dependency graph"""
 
--- a/mx/projects	Fri Jun 07 13:43:13 2013 +0200
+++ b/mx/projects	Fri Jun 07 14:15:38 2013 +0200
@@ -100,7 +100,7 @@
 project@com.oracle.graal.hotspot@sourceDirs=src
 project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.printer
 project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier, com.oracle.graal.service.processor
+project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor
 project@com.oracle.graal.hotspot@javaCompliance=1.7
 
 # graal.hotspot.amd64
@@ -113,7 +113,7 @@
 # graal.hotspot.sparc
 project@com.oracle.graal.hotspot.sparc@subDir=graal
 project@com.oracle.graal.hotspot.sparc@sourceDirs=src
-project@com.oracle.graal.hotspot.sparc@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.sparc
+project@com.oracle.graal.hotspot.sparc@dependencies=com.oracle.graal.compiler.sparc
 project@com.oracle.graal.hotspot.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.sparc@javaCompliance=1.7
 
@@ -138,6 +138,13 @@
 project@com.oracle.graal.hotspot.amd64.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.7
 
+# graal.options
+project@com.oracle.graal.options@subDir=graal
+project@com.oracle.graal.options@sourceDirs=src
+project@com.oracle.graal.options@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.options@javaCompliance=1.7
+project@com.oracle.graal.options@annotationProcessorForDependents=true
+
 # graal.graph
 project@com.oracle.graal.graph@subDir=graal
 project@com.oracle.graal.graph@sourceDirs=src
@@ -188,7 +195,7 @@
 # graal.lir.sparc
 project@com.oracle.graal.lir.sparc@subDir=graal
 project@com.oracle.graal.lir.sparc@sourceDirs=src
-project@com.oracle.graal.lir.sparc@dependencies=com.oracle.graal.lir,com.oracle.graal.asm.sparc
+project@com.oracle.graal.lir.sparc@dependencies=com.oracle.graal.asm.sparc
 project@com.oracle.graal.lir.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir.sparc@javaCompliance=1.7
 
@@ -245,7 +252,7 @@
 # graal.phases
 project@com.oracle.graal.phases@subDir=graal
 project@com.oracle.graal.phases@sourceDirs=src
-project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes
+project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes,com.oracle.graal.options
 project@com.oracle.graal.phases@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.phases@javaCompliance=1.7
 
@@ -309,10 +316,17 @@
 # graal.compiler.sparc
 project@com.oracle.graal.compiler.sparc@subDir=graal
 project@com.oracle.graal.compiler.sparc@sourceDirs=src
-project@com.oracle.graal.compiler.sparc@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.sparc
+project@com.oracle.graal.compiler.sparc@dependencies=com.oracle.graal.lir.sparc
 project@com.oracle.graal.compiler.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.sparc@javaCompliance=1.7
 
+# graal.compiler.sparc.test
+project@com.oracle.graal.compiler.sparc.test@subDir=graal
+project@com.oracle.graal.compiler.sparc.test@sourceDirs=src
+project@com.oracle.graal.compiler.sparc.test@dependencies=com.oracle.graal.compiler.sparc,com.oracle.graal.compiler.test
+project@com.oracle.graal.compiler.sparc.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.compiler.sparc.test@javaCompliance=1.7
+
 # graal.bytecode
 project@com.oracle.graal.bytecode@subDir=graal
 project@com.oracle.graal.bytecode@sourceDirs=src
@@ -392,7 +406,7 @@
 # graal.asm.sparc
 project@com.oracle.graal.asm.sparc@subDir=graal
 project@com.oracle.graal.asm.sparc@sourceDirs=src
-project@com.oracle.graal.asm.sparc@dependencies=com.oracle.graal.asm,com.oracle.graal.sparc
+project@com.oracle.graal.asm.sparc@dependencies=com.oracle.graal.hotspot,com.oracle.graal.sparc
 project@com.oracle.graal.asm.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.sparc@javaCompliance=1.7
 
--- a/mx/sanitycheck.py	Fri Jun 07 13:43:13 2013 +0200
+++ b/mx/sanitycheck.py	Fri Jun 07 14:15:38 2013 +0200
@@ -235,15 +235,15 @@
 
     
     args = ['-XX:+CompileTheWorld', '-Xbootclasspath/p:' + rtjar]
-    if not vm.endswith('-nograal'):
+    if commands.isGraalEnabled(vm):
         args += ['-XX:+BootstrapGraal', '-G:-Debug']
     if mode >= CTWMode.NoInline:
-        if vm.endswith('-nograal'):
+        if not commands.isGraalEnabled(vm):
             args.append('-XX:-Inline')
         else:
             args.append('-G:-Inline')
     if mode >= CTWMode.NoComplex:
-        if not vm.endswith('-nograal'):
+        if commands.isGraalEnabled(vm):
             args += ['-G:-OptLoopTransform', '-G:-OptTailDuplication', '-G:-FullUnroll', '-G:-MemoryAwareScheduling', '-G:-PartialEscapeAnalysis']
         
     return Test("CompileTheWorld", args, successREs=[time], scoreMatchers=[scoreMatcher], benchmarkCompilationRate=False)
--- a/mxtool/mx	Fri Jun 07 13:43:13 2013 +0200
+++ b/mxtool/mx	Fri Jun 07 14:15:38 2013 +0200
@@ -43,7 +43,7 @@
     python_exe=python2.7
 else
     type python2 > /dev/null 2>&1
-    if [ $? -eq 0]; then
+    if [ $? -eq 0 ]; then
         python_exe=python2
     else
         python_exe=python
--- a/mxtool/mx.py	Fri Jun 07 13:43:13 2013 +0200
+++ b/mxtool/mx.py	Fri Jun 07 14:15:38 2013 +0200
@@ -133,6 +133,7 @@
 """
 
 import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile
+import xml.parsers.expat
 import shutil, re, xml.dom.minidom
 from collections import Callable
 from threading import Thread
@@ -145,6 +146,7 @@
 _libs = dict()
 _dists = dict()
 _suites = dict()
+_annotationProcessors = None
 _mainSuite = None
 _opts = None
 _java = None
@@ -218,8 +220,8 @@
         libraries if 'includeLibs' is true, to the 'deps' list.
         """
         childDeps = list(self.deps)
-        if includeAnnotationProcessors and hasattr(self, 'annotationProcessors') and len(self.annotationProcessors) > 0:
-            childDeps = self.annotationProcessors + childDeps
+        if includeAnnotationProcessors and len(self.annotation_processors()) > 0:
+            childDeps = self.annotation_processors() + childDeps
         if self in deps:
             return deps
         for name in childDeps:
@@ -407,6 +409,19 @@
         self._init_packages_and_imports()
         return self._imported_java_packages
 
+    def annotation_processors(self):
+        if not hasattr(self, '_annotationProcessors'):
+            ap = set()
+            if hasattr(self, '_declaredAnnotationProcessors'):
+                ap = set(self._declaredAnnotationProcessors)
+
+            # find dependencies that auto-inject themselves as annotation processors to all dependents                
+            allDeps = self.all_deps([], includeLibs=False, includeSelf=False, includeAnnotationProcessors=False)
+            for p in allDeps:
+                if hasattr(p, 'annotationProcessorForDependents') and p.annotationProcessorForDependents.lower() == 'true':
+                    ap.add(p.name)
+            self._annotationProcessors = list(ap)
+        return self._annotationProcessors
 
 class Library(Dependency):
     def __init__(self, suite, name, path, mustExist, urls, sourcePath, sourceUrls):
@@ -526,7 +541,7 @@
             if not p.native and p.javaCompliance is None:
                 abort('javaCompliance property required for non-native project ' + name)
             if len(ap) > 0:
-                p.annotationProcessors = ap
+                p._declaredAnnotationProcessors = ap
             p.__dict__.update(attrs)
             self.projects.append(p)
 
@@ -730,6 +745,18 @@
     """
     return _projects.values()
 
+def annotation_processors():
+    """
+    Get the list of all loaded projects that define an annotation processor.
+    """
+    global _annotationProcessors
+    if _annotationProcessors is None:
+        ap = set()
+        for p in projects():
+            ap.update(p.annotation_processors())
+        _annotationProcessors = list(ap)
+    return _annotationProcessors
+
 def distribution(name, fatalIfMissing=True):
     """
     Get the distribution for a given name. This will abort if the named distribution does
@@ -1514,8 +1541,9 @@
         if java().debug_port is not None:
             javacArgs += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
 
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
-            processorPath = classpath(p.annotationProcessors, resolve=True)
+        ap = p.annotation_processors()
+        if len(ap) > 0:
+            processorPath = classpath(ap, resolve=True)
             genDir = p.source_gen_dir();
             if exists(genDir):
                 shutil.rmtree(genDir)
@@ -1671,16 +1699,16 @@
     return 0
 
 def processorjars():
-    projects = set()
     
+    projs = set()
     for p in sorted_deps():
         if _isAnnotationProcessorDependency(p):
-            projects.add(p)
+            projs.add(p)
             
-    if len(projects) <= 0:
+    if len(projs) < 0:
         return
     
-    pnames = [p.name for p in projects]
+    pnames = [p.name for p in projs]
     build(['--projects', ",".join(pnames)])
     archive(pnames)
 
@@ -1699,6 +1727,11 @@
             try:
                 zf = zipfile.ZipFile(tmp, 'w')
                 for p in sorted_deps(d.deps):
+                    # skip a  Java project if its Java compliance level is "higher" than the configured JDK
+                    if java().javaCompliance < p.javaCompliance:
+                        log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, d.path))
+                        continue
+
                     outputDir = p.output_dir()
                     for root, _, files in os.walk(outputDir):
                         relpath = root[len(outputDir) + 1:]
@@ -1908,19 +1941,30 @@
                     batch = javafilelist[:i]
                     javafilelist = javafilelist[i:]
                     try:
-                        run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-c', config, '-o', auditfileName] + batch)
+                        run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + batch)
                     finally:
                         if exists(auditfileName):
-                            with open(auditfileName) as f:
-                                warnings = [line.strip() for line in f if 'warning:' in line]
-                                if len(warnings) != 0:
-                                    map(log, warnings)
-                                    return 1
+                            errors = []
+                            source = None
+                            def start_element(name, attrs):
+                                if name == 'file':
+                                    global source
+                                    source = attrs['name']
+                                elif name == 'error':
+                                    errors.append('{}:{}: {}'.format(source, attrs['line'], attrs['message']))
+
+                            p = xml.parsers.expat.ParserCreate()
+                            p.StartElementHandler = start_element
+                            with open(auditfileName) as fp:
+                                p.ParseFile(fp)
+                            if len(errors) != 0:
+                                map(log, errors)
+                                return len(errors)
+                            else:
+                                if exists(timestampFile):
+                                    os.utime(timestampFile, None)
                                 else:
-                                    if exists(timestampFile):
-                                        os.utime(timestampFile, None)
-                                    else:
-                                        file(timestampFile, 'a')
+                                    file(timestampFile, 'a')
             finally:
                 if exists(auditfileName):
                     os.unlink(auditfileName)
@@ -2155,7 +2199,7 @@
                 os.mkdir(srcDir)
             out.element('classpathentry', {'kind' : 'src', 'path' : src})
 
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+        if len(p.annotation_processors()) > 0:
             genDir = p.source_gen_dir();
             if not exists(genDir):
                 os.mkdir(genDir)
@@ -2279,22 +2323,22 @@
         eclipseSettingsDir = join(suite.dir, 'mx', 'eclipse-settings')
         if exists(eclipseSettingsDir):
             for name in os.listdir(eclipseSettingsDir):
-                if name == "org.eclipse.jdt.apt.core.prefs" and not (hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0):
+                if name == "org.eclipse.jdt.apt.core.prefs" and not len(p.annotation_processors()) > 0:
                     continue
                 path = join(eclipseSettingsDir, name)
                 if isfile(path):
                     with open(join(eclipseSettingsDir, name)) as f:
                         content = f.read()
                     content = content.replace('${javaCompliance}', str(p.javaCompliance))
-                    if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+                    if len(p.annotation_processors()) > 0:
                         content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled')
                     update_file(join(settingsDir, name), content)
         
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+        if len(p.annotation_processors()) > 0:
             out = XMLDoc()
             out.open('factorypath')
             out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'})
-            for ap in p.annotationProcessors:
+            for ap in p.annotation_processors():
                 apProject = project(ap)
                 for dep in apProject.all_deps([], True):
                     if dep.isLibrary():
@@ -2319,22 +2363,7 @@
     """
     Determines if a given project is part of an annotation processor.
     """
-    processors = set()
-    
-    for otherProject in projects():
-        if hasattr(otherProject, 'annotationProcessors') and len(otherProject.annotationProcessors) > 0:
-            for processorName in otherProject.annotationProcessors:
-                processors.add(project(processorName, fatalIfMissing=True))
-                 
-    if p in processors:
-        return True
-    
-    for otherProject in processors:
-        deps = otherProject.all_deps([], True)
-        if p in deps:
-            return True
-    
-    return False
+    return p in sorted_deps(annotation_processors())
 
 def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False, xmlIndent='\t', xmlStandalone=None):
     launchOut = XMLDoc();
@@ -2429,7 +2458,7 @@
         out.element('explicit-platform', {'explicit-source-supported' : 'true'})
         out.open('source-roots')
         out.element('root', {'id' : 'src.dir'})
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+        if len(p.annotation_processors()) > 0:
             out.element('root', {'id' : 'src.ap-source-output.dir'})
         out.close('source-roots')
         out.open('test-roots')
@@ -2469,7 +2498,7 @@
         annotationProcessorEnabled = "false"
         annotationProcessorReferences = ""
         annotationProcessorSrcFolder = ""
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+        if len(p.annotation_processors()) > 0:
             annotationProcessorEnabled = "true"
             annotationProcessorSrcFolder = "src.ap-source-output.dir=${build.generated.sources.dir}/ap-source-output"
 
@@ -2561,8 +2590,8 @@
         
         deps = p.all_deps([], True)
         annotationProcessorOnlyDeps = []
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
-            for ap in p.annotationProcessors:
+        if len(p.annotation_processors()) > 0:
+            for ap in p.annotation_processors():
                 apProject = project(ap)
                 if not apProject in deps:
                     deps.append(apProject)
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Jun 07 14:15:38 2013 +0200
@@ -186,6 +186,7 @@
   do_klass(BitSet_klass,                          java_util_BitSet,                                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompiledCode_klass,             com_oracle_graal_hotspot_HotSpotCompiledCode,                 Opt) \
+  do_klass(HotSpotCompiledCode_Comment_klass,     com_oracle_graal_hotspot_HotSpotCompiledCode_Comment,         Opt) \
   do_klass(HotSpotCompiledNmethod_klass,          com_oracle_graal_hotspot_HotSpotCompiledNmethod,              Opt) \
   do_klass(HotSpotCompiledRuntimeStub_klass,      com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub,          Opt) \
   do_klass(HotSpotForeignCallLinkage_klass,       com_oracle_graal_hotspot_HotSpotForeignCallLinkage,           Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Jun 07 14:15:38 2013 +0200
@@ -297,6 +297,7 @@
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
   template(com_oracle_graal_hotspot_HotSpotOptions,                  "com/oracle/graal/hotspot/HotSpotOptions")                       \
   template(com_oracle_graal_hotspot_HotSpotCompiledCode,             "com/oracle/graal/hotspot/HotSpotCompiledCode")                  \
+  template(com_oracle_graal_hotspot_HotSpotCompiledCode_Comment,     "com/oracle/graal/hotspot/HotSpotCompiledCode$Comment")          \
   template(com_oracle_graal_hotspot_HotSpotCompiledNmethod,          "com/oracle/graal/hotspot/HotSpotCompiledNmethod")               \
   template(com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub,      "com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub")           \
   template(com_oracle_graal_hotspot_HotSpotForeignCallLinkage,       "com/oracle/graal/hotspot/HotSpotForeignCallLinkage")            \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Fri Jun 07 14:15:38 2013 +0200
@@ -256,7 +256,13 @@
     arrayOop values = (arrayOop) VirtualObject::values(value);
     for (jint i = 0; i < values->length(); i++) {
       ScopeValue* cur_second = NULL;
-      ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second, oop_recorder);
+      oop object;
+      if(UseCompressedOops) {
+        object=oopDesc::decode_heap_oop(((narrowOop*) values->base(T_OBJECT))[i]);
+      } else {
+        object=((oop*) (values->base(T_OBJECT)))[i];
+      }
+      ScopeValue* value = get_hotspot_value(object, total_frame_size, objects, cur_second, oop_recorder);
 
       if (isLongArray && cur_second == NULL) {
         // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations.
@@ -410,6 +416,9 @@
 
   // (very) conservative estimate: each site needs a constant section entry
   _constants_size = _sites->length() * (BytesPerLong*2);
+#ifndef PRODUCT
+  _comments = (arrayOop) HotSpotCompiledCode::comments(compiled_code);
+#endif
 
   _next_call_type = MARK_INVOKE_INVALID;
 }
@@ -434,9 +443,13 @@
   memcpy(_instructions->start(), _code->base(T_BYTE), _code_size);
   _instructions->set_end(_instructions->start() + _code_size);
 
-  oop* sites = (oop*) _sites->base(T_OBJECT);
+  oop site;
   for (int i = 0; i < _sites->length(); i++) {
-    oop site = sites[i];
+    if(UseCompressedOops) {
+      site=oopDesc::decode_heap_oop(((narrowOop*) _sites->base(T_OBJECT))[i]);
+    } else {
+      site=((oop*) (_sites->base(T_OBJECT)))[i];
+    }
     jint pc_offset = CompilationResult_Site::pcOffset(site);
 
     if (site->is_a(CompilationResult_Call::klass())) {
@@ -463,6 +476,23 @@
       fatal("unexpected Site subclass");
     }
   }
+
+#ifndef PRODUCT
+  if (_comments != NULL) {
+    oop comment;
+    for (int i = 0; i < _comments->length(); i++) {
+      if(UseCompressedOops) {
+        comment=oopDesc::decode_heap_oop(((narrowOop*) _comments->base(T_OBJECT))[i]);
+      } else {
+        comment=((oop*) (_comments->base(T_OBJECT)))[i];
+      }
+      assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce");
+      jint offset = HotSpotCompiledCode_Comment::pcOffset(comment);
+      char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment));
+      buffer.block_comment(offset, text);
+    }
+  }
+#endif
 }
 
 void CodeInstaller::assumption_MethodContents(Handle assumption) {
@@ -517,7 +547,12 @@
   if (_exception_handlers != NULL) {
     oop* exception_handlers = (oop*) _exception_handlers->base(T_OBJECT);
     for (int i = 0; i < _exception_handlers->length(); i++) {
-      oop exc = exception_handlers[i];
+      oop exc;
+      if(UseCompressedOops) {
+        exc=oopDesc::decode_heap_oop(((narrowOop*) _exception_handlers->base(T_OBJECT))[i]);
+      } else {
+        exc=((oop*) (_exception_handlers->base(T_OBJECT)))[i];
+      }
       jint pc_offset = CompilationResult_Site::pcOffset(exc);
       jint handler_offset = CompilationResult_ExceptionHandler::handlerPos(exc);
 
@@ -589,8 +624,12 @@
 
   for (jint i = 0; i < values->length(); i++) {
     ScopeValue* second = NULL;
-    oop value = ((oop*) values->base(T_OBJECT))[i];
-
+    oop value;
+    if(UseCompressedOops) {
+      value=oopDesc::decode_heap_oop(((narrowOop*) values->base(T_OBJECT))[i]);
+    } else {
+      value = ((oop*) values->base(T_OBJECT))[i];
+    }
     if (i < local_count) {
       ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second, _oop_recorder);
       if (second != NULL) {
@@ -609,10 +648,15 @@
     if (second != NULL) {
       i++;
       assert(i < values->length(), "double-slot value not followed by Value.ILLEGAL");
-      assert(((oop*) values->base(T_OBJECT))[i] == Value::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL");
+      if(UseCompressedOops) {
+        assert(oopDesc::decode_heap_oop(((narrowOop*) values->base(T_OBJECT))[i]) == Value::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL");
+      } else {
+        assert(((oop*) values->base(T_OBJECT))[i] == Value::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL");
+      }
     }
   }
 
+
   _debug_recorder->dump_object_pool(objects);
 
   DebugToken* locals_token = _debug_recorder->create_scope_values(locals);
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Fri Jun 07 14:15:38 2013 +0200
@@ -60,6 +60,9 @@
   jint          _custom_stack_area_offset;
   jint          _parameter_count;
   jint          _constants_size;
+#ifndef PRODUCT
+  arrayOop      _comments;
+#endif
 
   MarkId        _next_call_type;
   address       _invoke_mark_pc;
--- a/src/share/vm/graal/graalCompiler.cpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Fri Jun 07 14:15:38 2013 +0200
@@ -85,6 +85,7 @@
   {
     GRAAL_VM_ENTRY_MARK;
     HandleMark hm;
+    VMToCompiler::initOptions();
     for (int i = 0; i < Arguments::num_graal_args(); ++i) {
       const char* arg = Arguments::graal_args_array()[i];
       Handle option = java_lang_String::create_from_str(arg, THREAD);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Fri Jun 07 14:15:38 2013 +0200
@@ -795,6 +795,7 @@
   set_address("logObjectAddress", GraalRuntime::log_object);
   set_address("logPrintfAddress", GraalRuntime::log_printf);
   set_address("vmErrorAddress", GraalRuntime::vm_error);
+  set_address("loadAndClearExceptionAddress", GraalRuntime::load_and_clear_exception);
   set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre);
   set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post);
   set_address("javaTimeMillisAddress", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
@@ -830,6 +831,12 @@
   set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial);
   set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface);
 
+  set_boolean("useCompressedOops", UseCompressedOops);
+  set_boolean("useCompressedKlassPointers", UseCompressedKlassPointers);
+  set_address("narrowOopBase", Universe::narrow_oop_base());
+  set_int("narrowOopShift", Universe::narrow_oop_shift());
+  set_int("logMinObjAlignment", LogMinObjAlignmentInBytes);
+
   set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()));
   set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()));
   set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes);
--- a/src/share/vm/graal/graalCompilerToVM.hpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.hpp	Fri Jun 07 14:15:38 2013 +0200
@@ -54,7 +54,12 @@
 
   oop next_arg(BasicType expectedType) {
     assert(_index < _args->length(), "out of bounds");
-    oop arg = ((oop*) _args->base(T_OBJECT))[_index++];
+    oop arg;
+    if(UseCompressedOops) {
+      arg = oopDesc::decode_heap_oop(((narrowOop*) _args->base(T_OBJECT))[_index++]);
+    } else {
+      arg = ((oop*) _args->base(T_OBJECT))[_index++];
+    }
     assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
     return arg;
   }
--- a/src/share/vm/graal/graalJavaAccess.hpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Fri Jun 07 14:15:38 2013 +0200
@@ -87,6 +87,11 @@
     oop_field(HotSpotCompiledCode, comp, "Lcom/oracle/graal/api/code/CompilationResult;")                                                                      \
     oop_field(HotSpotCompiledCode, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;")                                                               \
     oop_field(HotSpotCompiledCode, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;")                                       \
+    oop_field(HotSpotCompiledCode, comments, "[Lcom/oracle/graal/hotspot/HotSpotCompiledCode$Comment;")                                                        \
+  end_class                                                                                                                                                    \
+  start_class(HotSpotCompiledCode_Comment)                                                                                                                     \
+    oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;")                                                                                         \
+    int_field(HotSpotCompiledCode_Comment, pcOffset)                                                                                                           \
   end_class                                                                                                                                                    \
   start_class(HotSpotCompiledNmethod)                                                                                                                          \
     oop_field(HotSpotCompiledNmethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;")                                                     \
@@ -95,8 +100,8 @@
   start_class(HotSpotCompiledRuntimeStub)                                                                                                                      \
     oop_field(HotSpotCompiledRuntimeStub, stubName, "Ljava/lang/String;")                                                                                      \
   end_class                                                                                                                                                    \
-  start_class(HotSpotForeignCallLinkage)                                                                                                                        \
-    long_field(HotSpotForeignCallLinkage, address)                                                                                                              \
+  start_class(HotSpotForeignCallLinkage)                                                                                                                       \
+    long_field(HotSpotForeignCallLinkage, address)                                                                                                             \
   end_class                                                                                                                                                    \
   start_class(ExceptionHandler)                                                                                                                                \
     int_field(ExceptionHandler, startBCI)                                                                                                                      \
@@ -139,7 +144,7 @@
     int_field(CompilationResult_Site, pcOffset)                                                                                                                \
   end_class                                                                                                                                                    \
   start_class(CompilationResult_Call)                                                                                                                          \
-    oop_field(CompilationResult_Call, target, "Lcom/oracle/graal/api/meta/InvokeTarget;")                                                                                            \
+    oop_field(CompilationResult_Call, target, "Lcom/oracle/graal/api/meta/InvokeTarget;")                                                                      \
     oop_field(CompilationResult_Call, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                      \
   end_class                                                                                                                                                    \
   start_class(CompilationResult_DataPatch)                                                                                                                     \
@@ -228,10 +233,10 @@
     oop_field(VirtualObject, type, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                                             \
     oop_field(VirtualObject, values, "[Lcom/oracle/graal/api/meta/Value;")                                                                                     \
   end_class                                                                                                                                                    \
-  start_class(HotSpotMonitorValue)                                                                                                                               \
-    oop_field(HotSpotMonitorValue, owner, "Lcom/oracle/graal/api/meta/Value;")                                                                                   \
-    oop_field(HotSpotMonitorValue, slot, "Lcom/oracle/graal/api/code/StackSlot;")                                                                                \
-    boolean_field(HotSpotMonitorValue, eliminated)                                                                                                               \
+  start_class(HotSpotMonitorValue)                                                                                                                             \
+    oop_field(HotSpotMonitorValue, owner, "Lcom/oracle/graal/api/meta/Value;")                                                                                 \
+    oop_field(HotSpotMonitorValue, slot, "Lcom/oracle/graal/api/code/StackSlot;")                                                                              \
+    boolean_field(HotSpotMonitorValue, eliminated)                                                                                                             \
   end_class                                                                                                                                                    \
   /* end*/
 
--- a/src/share/vm/graal/graalRuntime.cpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Fri Jun 07 14:15:38 2013 +0200
@@ -380,6 +380,13 @@
   report_vm_error(__FILE__, __LINE__, error_msg, detail_msg);
 JRT_END
 
+JRT_LEAF(oop, GraalRuntime::load_and_clear_exception(JavaThread* thread))
+  oop exception = thread->exception_oop();
+  assert(exception != NULL, "npe");
+  thread->set_exception_oop(NULL);
+  thread->set_exception_pc(0);
+  return exception;
+JRT_END
 
 JRT_LEAF(void, GraalRuntime::log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3))
   ResourceMark rm;
--- a/src/share/vm/graal/graalRuntime.hpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Fri Jun 07 14:15:38 2013 +0200
@@ -42,6 +42,7 @@
   static void create_null_exception(JavaThread* thread);
   static void create_out_of_bounds_exception(JavaThread* thread, jint index);
   static void vm_error(JavaThread* thread, oop where, oop format, jlong value);
+  static oop load_and_clear_exception(JavaThread* thread);
   static void log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3);
   static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
   // Note: Must be kept in sync with constants in com.oracle.graal.replacements.Log
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Fri Jun 07 14:15:38 2013 +0200
@@ -75,6 +75,13 @@
   return Handle(JNIHandles::resolve_non_null(_vmToCompilerPermObject));
 }
 
+void VMToCompiler::initOptions() {
+  KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
+  Thread* THREAD = Thread::current();
+  compilerKlass->initialize(THREAD);
+  check_pending_exception("Error while calling initOptions");
+}
+
 jboolean VMToCompiler::setOption(Handle option) {
   assert(!option.is_null(), "");
   KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Fri Jun 07 14:15:38 2013 +0200
@@ -50,6 +50,9 @@
     return _graalRuntimePermObject;
   }
 
+  // public static boolean HotSpotOptions.<clinit>();
+  static void initOptions();
+
   // public static boolean HotSpotOptions.setOption(String option);
   static jboolean setOption(Handle option);
 
--- a/src/share/vm/oops/klass.hpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/oops/klass.hpp	Fri Jun 07 14:15:38 2013 +0200
@@ -148,10 +148,7 @@
   Klass*      _primary_supers[_primary_super_limit];
   // java/lang/Class instance mirroring this class
   oop       _java_mirror;
-#ifdef GRAAL
-  // com/oracle/graal/hotspot/HotSpotResolvedObjectType mirroring this class
-  oop       _graal_mirror;
-#endif
+
   // Superclass
   Klass*      _super;
   // First subclass (NULL if none); _subklass->next_sibling() is next one
@@ -252,12 +249,6 @@
   oop java_mirror() const              { return _java_mirror; }
   void set_java_mirror(oop m) { klass_oop_store(&_java_mirror, m); }
 
-#ifdef GRAAL
-  // Graal mirror
-  oop graal_mirror() const               { return _graal_mirror; }
-  void set_graal_mirror(oop m)           { oop_store((oop*) &_graal_mirror, m); }
-#endif
-
   // modifier flags
   jint modifier_flags() const          { return _modifier_flags; }
   void set_modifier_flags(jint flags)  { _modifier_flags = flags; }
@@ -317,7 +308,6 @@
   static ByteSize layout_helper_offset()         { return in_ByteSize(offset_of(Klass, _layout_helper)); }
   static ByteSize access_flags_offset()          { return in_ByteSize(offset_of(Klass, _access_flags)); }
 #ifdef GRAAL
-  static ByteSize graal_mirror_offset()          { return in_ByteSize(offset_of(Klass, _graal_mirror)); }
   static ByteSize next_sibling_offset()          { return in_ByteSize(offset_of(Klass, _next_sibling)); }
   static ByteSize subklass_offset()              { return in_ByteSize(offset_of(Klass, _subklass)); }
 #endif
--- a/src/share/vm/prims/unsafe.cpp	Fri Jun 07 13:43:13 2013 +0200
+++ b/src/share/vm/prims/unsafe.cpp	Fri Jun 07 14:15:38 2013 +0200
@@ -174,17 +174,27 @@
   OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x);
 
 // Macros for oops that check UseCompressedOops
-
+#ifndef GRAAL
 #define GET_OOP_FIELD(obj, offset, v) \
-  oop p = JNIHandles::resolve(obj);   \
-  oop v;                              \
-  if (UseCompressedOops) {            \
+  oop p = JNIHandles::resolve(obj); \
+  oop v; \
+  if (UseCompressedOops) { \
     narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); \
-    v = oopDesc::decode_heap_oop(n);                                \
-  } else {                            \
-    v = *(oop*)index_oop_from_field_offset_long(p, offset);                 \
+    v = oopDesc::decode_heap_oop(n); \
+  } else { \
+    v = *(oop*)index_oop_from_field_offset_long(p, offset); \
   }
-
+#else
+#define GET_OOP_FIELD(obj, offset, v) \
+   oop p = JNIHandles::resolve(obj); \
+   oop v; \
+   if (UseCompressedOops && p!=NULL && offset>=oopDesc::header_size()) { \
+     narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); \
+     v = oopDesc::decode_heap_oop(n); \
+   } else { \
+     v = *(oop*)index_oop_from_field_offset_long(p, offset); \
+   }
+#endif
 
 // Get/SetObject must be special-cased, since it works with handles.