changeset 12597:ce8dd5fa8d54

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 22 Oct 2013 11:43:37 +0200
parents 3ee8ae69d676 (current diff) bddf5ae62522 (diff)
children cf6cfa79593d
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java
diffstat 111 files changed, 2102 insertions(+), 933 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ExternalCompilationResult.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ExternalCompilationResult.java	Tue Oct 22 11:43:37 2013 +0200
@@ -23,12 +23,12 @@
 package com.oracle.graal.api.code;
 
 /**
- * Represents the output from compiling a method generated by graal, but executing 
- * in a memory and computational subsystem outside the graal host system.
+ * Represents the output from compiling a method generated by Graal, but executing in a memory and
+ * computational subsystem outside the Graal host system.
  * 
- * Output may include the compiled machine code, associated
- * data and references, relocation information, deoptimization information,
- * as this result is generated from a structure graph on the graal host system.
+ * Output may include the compiled machine code, associated data and references, relocation
+ * information, deoptimization information, as this result is generated from a structure graph on
+ * the Graal host system.
  */
 public class ExternalCompilationResult extends CompilationResult {
 
@@ -45,7 +45,8 @@
 
     /**
      * Set the address for the point of entry to the external compilation result.
-     * @param addr    The address of the entry point.
+     * 
+     * @param addr the address of the entry point
      */
     public void setEntryPoint(long addr) {
         entryPoint = addr;
@@ -53,9 +54,10 @@
 
     /**
      * Return the address for the point of entry to the external compilation result.
+     * 
      * @return address value
      */
     public long getEntryPoint() {
-      return entryPoint;
+        return entryPoint;
     }
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java	Tue Oct 22 11:43:37 2013 +0200
@@ -27,10 +27,11 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.runtime.*;
 
 class NameAndSignature {
 
-    public static final MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class);
+    public static final MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess();
 
     final String name;
     final Class returnType;
@@ -71,14 +72,14 @@
     public boolean signatureEquals(ResolvedJavaMethod m) {
         Signature s = m.getSignature();
         ResolvedJavaType declaringClass = m.getDeclaringClass();
-        if (!s.getReturnType(declaringClass).resolve(declaringClass).equals(runtime.lookupJavaType(returnType))) {
+        if (!s.getReturnType(declaringClass).resolve(declaringClass).equals(metaAccess.lookupJavaType(returnType))) {
             return false;
         }
         if (s.getParameterCount(false) != parameterTypes.length) {
             return false;
         }
         for (int i = 0; i < parameterTypes.length; i++) {
-            if (!s.getParameterType(i, declaringClass).resolve(declaringClass).equals(runtime.lookupJavaType(parameterTypes[i]))) {
+            if (!s.getParameterType(i, declaringClass).resolve(declaringClass).equals(metaAccess.lookupJavaType(parameterTypes[i]))) {
                 return false;
             }
         }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java	Tue Oct 22 11:43:37 2013 +0200
@@ -25,7 +25,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.java.*;
 
 /**
  * Tests for {@link BytecodeDisassemblerProvider}.
@@ -40,7 +40,7 @@
      */
     @Test
     public void disassembleTest() {
-        BytecodeDisassemblerProvider dis = Graal.getRuntime().getCapability(BytecodeDisassemblerProvider.class);
+        BytecodeDisassemblerProvider dis = new BytecodeDisassembler();
         if (dis != null) {
             int count = 0;
             for (ResolvedJavaMethod m : methods.values()) {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java	Tue Oct 22 11:43:37 2013 +0200
@@ -33,6 +33,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.runtime.*;
 
 /**
  * Context for type related api.meta tests.
@@ -40,13 +42,17 @@
 public class TypeUniverse {
 
     public final Unsafe unsafe;
-    public final MetaAccessProvider metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class);
-    public final ConstantReflectionProvider constantReflection = Graal.getRequiredCapability(ConstantReflectionProvider.class);
+
+    public final MetaAccessProvider metaAccess;
+    public final ConstantReflectionProvider constantReflection;
     public final Collection<Class<?>> classes = new HashSet<>();
     public final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
     public final List<Constant> constants = new ArrayList<>();
 
     public TypeUniverse() {
+        Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders();
+        metaAccess = providers.getMetaAccess();
+        constantReflection = providers.getConstantReflection();
         Unsafe theUnsafe = null;
         try {
             theUnsafe = Unsafe.getUnsafe();
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Tue Oct 22 11:43:37 2013 +0200
@@ -73,4 +73,8 @@
      * @return the encoded value as an integer
      */
     Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason);
+
+    DeoptimizationReason decodeDeoptReason(Constant constant);
+
+    DeoptimizationAction decodeDeoptAction(Constant constant);
 }
--- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Graal.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Graal.java	Tue Oct 22 11:43:37 2013 +0200
@@ -69,10 +69,5 @@
         public <T> T getCapability(Class<T> clazz) {
             return null;
         }
-
-        @Override
-        public <T> T getCapability(Class<T> clazz, String selector) {
-            return null;
-        }
     }
 }
--- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/GraalRuntime.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/GraalRuntime.java	Tue Oct 22 11:43:37 2013 +0200
@@ -27,14 +27,4 @@
     String getName();
 
     <T> T getCapability(Class<T> clazz);
-
-    /**
-     * Requests a capability represented by a given class.
-     * 
-     * @param selector a value the runtime will use to refine the capability returned (if any). An
-     *            example may be the name of an architecture when asking for a capability
-     *            representing a compiler backend.
-     */
-    <T> T getCapability(Class<T> clazz, String selector);
-
 }
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Tue Oct 22 11:43:37 2013 +0200
@@ -918,9 +918,8 @@
         public void emit(PTXAssembler asm) {
 
             if (booleanOperator != null) {
-                asm.emitString("setp." + operator.getOperator() + "." + booleanOperator.getOperator() + typeForKind(kind) + " %p" + predicate + emitValue(first) + emitValue(second) + ", %r;"); // Predicates
-// need to be objects
-
+                // Predicates need to be objects
+                asm.emitString("setp." + operator.getOperator() + "." + booleanOperator.getOperator() + typeForKind(kind) + " %p" + predicate + emitValue(first) + emitValue(second) + ", %r;");
             } else {
                 asm.emitString("setp." + operator.getOperator() + "." + typeForKind(kind) + " %p" + predicate + emitValue(first) + emitValue(second) + ";");
             }
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -30,6 +30,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.test.*;
 
 public abstract class AssemblerTest extends GraalTest {
@@ -43,8 +45,9 @@
     }
 
     public AssemblerTest() {
-        this.metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class);
-        this.codeCache = Graal.getRequiredCapability(CodeCacheProvider.class);
+        Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders();
+        this.metaAccess = providers.getMetaAccess();
+        this.codeCache = providers.getCodeCache();
     }
 
     public MetaAccessProvider getMetaAccess() {
@@ -62,7 +65,7 @@
 
         InstalledCode code = codeCache.addMethod(method, compResult);
 
-        DisassemblerProvider dis = Graal.getRuntime().getCapability(DisassemblerProvider.class);
+        DisassemblerProvider dis = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getDisassembler();
         if (dis != null) {
             String disasm = dis.disassemble(code);
             Assert.assertTrue(code.toString(), disasm == null || disasm.length() > 0);
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.hotspot.hsail.*;
+import com.oracle.graal.hsail.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -34,7 +35,7 @@
 public class BasicHSAILTest extends GraalCompilerTest {
 
     public BasicHSAILTest() {
-        super("HSAIL");
+        super(HSAIL.class);
     }
 
     public void testAdd() {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayPTXTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayPTXTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -35,15 +35,9 @@
 
     @Test
     public void testArray() {
-        int[] array1 = {
-            1, 2, 3, 4, 5, 6, 7, 8, 9
-        };
-        int[] array2 = {
-            1, 2, 3, 4, 5, 6, 7, 8, 9
-        };
-        int[] array3 = {
-            1, 2, 3, 4, 5, 6, 7, 8, 9
-        };
+        int[] array1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+        int[] array2 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+        int[] array3 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
 
         invoke(compile("testStoreArray1I"), array1, 2);
         printReport("testStoreArray1I: " + Arrays.toString(array1));
@@ -60,17 +54,14 @@
         array[i] = 42;
     }
 
-    public static void testStoreArrayWarp0(int[] array,
-                                           @Warp(dimension = X) int i) {
+    public static void testStoreArrayWarp0(int[] array, @Warp(dimension = X) int i) {
         array[i] = 42;
     }
 
-    public static void testStoreArrayWarp1I(@ParallelOver(dimension = X) int[] array,
-                                            @Warp(dimension = X) int i) {
+    public static void testStoreArrayWarp1I(@ParallelOver(dimension = X) int[] array, @Warp(dimension = X) int i) {
         array[i] = 42;
     }
 
-
     public static void main(String[] args) {
         ArrayPTXTest test = new ArrayPTXTest();
         for (Method m : ArrayPTXTest.class.getMethods()) {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -60,12 +60,10 @@
         } else {
             printReport("testIfElse2I: no VALUE");
         }
-        Boolean bret = (Boolean) invoke(compile("testIntegerTestBranch2I"),
-                                        0xff00, 0x00ff);
+        Boolean bret = (Boolean) invoke(compile("testIntegerTestBranch2I"), 0xff00, 0x00ff);
         if (bret != null) {
             printReport("testIntegerTestBranch2I: " + bret);
-            printReport("testIntegerTestBranch2I: actual: " +
-                                testIntegerTestBranch2I(0xff00, 0x00ff));
+            printReport("testIntegerTestBranch2I: actual: " + testIntegerTestBranch2I(0xff00, 0x00ff));
         } else {
             printReport("testIntegerTestBranch2I: no VALUE");
         }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -31,6 +31,7 @@
     @Test
     public void testAdd() {
 
+        // @formatter:off
         /* Integer r4 = (Integer) invoke(compile("testAdd2B"), (byte) 6, (byte) 4);
         if (r4 == null) {
             printReport("testAdd2B FAILED");
@@ -39,6 +40,7 @@
         } else {
             printReport("testAdd2B FAILED");
         } */
+        // @formatter:on
 
         Integer r4 = (Integer) invoke(compile("testAdd2I"), 18, 24);
         if (r4 == null) {
@@ -346,7 +348,6 @@
         return (int) a;
     }
 
-
     public static void main(String[] args) {
         IntegerPTXTest test = new IntegerPTXTest();
         for (Method m : IntegerPTXTest.class.getMethods()) {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Tue Oct 22 11:43:37 2013 +0200
@@ -42,6 +42,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.ptx.*;
 
 public abstract class PTXTestBase extends GraalCompilerTest {
 
@@ -55,7 +56,7 @@
     }
 
     public PTXTestBase() {
-        super("PTX");
+        super(PTX.class);
     }
 
     protected CompilationResult compile(String test) {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Oct 22 11:43:37 2013 +0200
@@ -242,14 +242,14 @@
             case Object:
                 append(new BranchOp(finalCondition, label, kind));
                 break;
-// case Float:
-// append(new CompareOp(FCMP, x, y));
-// append(new BranchOp(condition, label));
-// break;
-// case Double:
-// append(new CompareOp(DCMP, x, y));
-// append(new BranchOp(condition, label));
-// break;
+            // case Float:
+            // append(new CompareOp(FCMP, x, y));
+            // append(new BranchOp(condition, label));
+            // break;
+            // case Double:
+            // append(new CompareOp(DCMP, x, y));
+            // append(new BranchOp(condition, label));
+            // break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
         }
@@ -631,7 +631,7 @@
 
     @Override
     public Value emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
-// LIRFrameState state = state(deopting);
+        // LIRFrameState state = state(deopting);
         switch (a.getKind().getStackKind()) {
             case Int:
                 // emitDivRem(IUDIV, a, b, state);
@@ -646,7 +646,7 @@
 
     @Override
     public Value emitURem(Value a, Value b, DeoptimizingNode deopting) {
-// LIRFrameState state = state(deopting);
+        // LIRFrameState state = state(deopting);
         switch (a.getKind().getStackKind()) {
             case Int:
                 // emitDivRem(IUREM, a, b, state);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -54,6 +54,7 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.printer.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.test.*;
 
 /**
@@ -82,9 +83,9 @@
     private final Suites suites;
 
     public GraalCompilerTest() {
-        this.backend = Graal.getRequiredCapability(Backend.class);
+        this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
         this.providers = getBackend().getProviders();
-        this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
+        this.suites = backend.getSuites().createSuites();
     }
 
     /**
@@ -93,16 +94,17 @@
      * 
      * @param arch the name of the desired backend architecture
      */
-    public GraalCompilerTest(String arch) {
-        Backend b = Graal.getRuntime().getCapability(Backend.class, arch);
+    public GraalCompilerTest(Class<? extends Architecture> arch) {
+        RuntimeProvider runtime = Graal.getRequiredCapability(RuntimeProvider.class);
+        Backend b = runtime.getBackend(arch);
         if (b != null) {
             this.backend = b;
         } else {
             // Fall back to the default/host backend
-            this.backend = Graal.getRuntime().getCapability(Backend.class);
+            this.backend = runtime.getHostBackend();
         }
         this.providers = backend.getProviders();
-        this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
+        this.suites = backend.getSuites().createSuites();
     }
 
     @BeforeClass
@@ -530,7 +532,7 @@
                             Debug.dump(new Object[]{compResult, code}, "After code installation");
                         }
                         if (Debug.isLogEnabled()) {
-                            DisassemblerProvider dis = Graal.getRuntime().getCapability(DisassemblerProvider.class);
+                            DisassemblerProvider dis = backend.getDisassembler();
                             if (dis != null) {
                                 String text = dis.disassemble(code);
                                 if (text != null) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -553,8 +553,7 @@
             @Override
             public SchedulePhase call() throws Exception {
                 Assumptions assumptions = new Assumptions(false);
-                HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(),
-                                OptimisticOptimizations.ALL);
+                HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
                 new CanonicalizerPhase(true).apply(graph, context);
                 if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
@@ -576,8 +575,7 @@
                 new FloatingReadPhase().apply(graph);
                 new RemoveValueProxyPhase().apply(graph);
 
-                MidTierContext midContext = new MidTierContext(getProviders(), assumptions, getCodeCache().getTarget(),
-                                OptimisticOptimizations.ALL);
+                MidTierContext midContext = new MidTierContext(getProviders(), assumptions, getCodeCache().getTarget(), OptimisticOptimizations.ALL);
                 new GuardLoweringPhase().apply(graph, midContext);
                 new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext);
                 new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -86,7 +86,7 @@
                 PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false));
                 new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new FloatingReadPhase().apply(graph);
-                new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph);
+                new OptimizeGuardAnchors().apply(graph);
                 new ReadEliminationPhase().apply(graph);
                 new CanonicalizerPhase(true).apply(graph, context);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
-import java.util.concurrent.*;
-
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
@@ -32,12 +30,14 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
@@ -223,31 +223,97 @@
         testEscapeAnalysis("testNewNodeSnippet", null, false);
     }
 
-    private ReturnNode testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) {
-        ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(snippet));
-        final StructuredGraph graph = new StructuredGraph(method);
+    private static final TestObject2 staticObj = new TestObject2(null);
+
+    public static Object testFullyUnrolledLoopSnippet() {
+        /*
+         * This tests a case that can appear if PEA is performed both before and after loop
+         * unrolling/peeling: If the VirtualInstanceNode is not anchored correctly to stay within
+         * the loop, it will not be duplicated, and therefore the resulting object will reference
+         * itself, and not a second (different) object.
+         */
+        TestObject2 obj = staticObj;
+        for (int i = 0; i < 2; i++) {
+            obj = new TestObject2(obj);
+        }
+        return obj.o;
+    }
 
-        return Debug.scope("GraalCompiler", new Object[]{graph, method, getCodeCache()}, new Callable<ReturnNode>() {
+    @Test
+    public void testFullyUnrolledLoop() {
+        testEscapeAnalysisUnrolled("testFullyUnrolledLoopSnippet");
+    }
+
+    private static Object staticField;
+
+    private static TestObject2 inlinedPart(TestObject2 obj) {
+        TestObject2 ret = new TestObject2(obj);
+        staticField = null;
+        return ret;
+    }
+
+    public static Object testPeeledLoopSnippet() {
+        TestObject2 obj = staticObj;
+        int i = 0;
+        do {
+            obj = inlinedPart(obj);
+        } while (i++ < 10);
+        staticField = obj;
+        return obj.o;
+    }
 
-            public ReturnNode call() {
-                new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+    @Test
+    public void testPeeledLoop() {
+        testEscapeAnalysisPeeled("testPeeledLoopSnippet");
+    }
+
+    private StructuredGraph graph;
+    private HighTierContext context;
+    private ReturnNode returnNode;
+
+    private void testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) {
+        prepareGraph(snippet, iterativeEscapeAnalysis);
+        if (expectedConstantResult != null) {
+            Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
+            Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+        }
+        int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() +
+                        graph.getNodes().filter(CommitAllocationNode.class).count();
+        Assert.assertEquals(0, newInstanceCount);
+    }
 
+    private void testEscapeAnalysisUnrolled(String snippet) {
+        prepareGraph(snippet, false);
+        new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
+        Assert.assertTrue(returnNode.result() instanceof AllocatedObjectNode);
+        CommitAllocationNode commit = ((AllocatedObjectNode) returnNode.result()).getCommit();
+        Assert.assertEquals(1, commit.getValues().size());
+        Assert.assertEquals(1, commit.getVirtualObjects().size());
+        Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0));
+    }
+
+    private void testEscapeAnalysisPeeled(String snippet) {
+        prepareGraph(snippet, false);
+        new LoopTransformHighPhase().apply(graph);
+        new LoopTransformLowPhase().apply(graph);
+        new SchedulePhase().apply(graph);
+    }
+
+    private void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) {
+        graph = new StructuredGraph(getMetaAccess().lookupJavaMethod(getMethod(snippet)));
+        Debug.scope("GraalCompiler", new Object[]{graph, getMetaAccess().lookupJavaMethod(getMethod(snippet)), getCodeCache()}, new Runnable() {
+
+            public void run() {
+                new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
                 Assumptions assumptions = new Assumptions(false);
-                HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
+                context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
                 new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
                 new CanonicalizerPhase(true).apply(graph, context);
                 new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context);
                 Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-                ReturnNode returnNode = graph.getNodes().filter(ReturnNode.class).first();
-                if (expectedConstantResult != null) {
-                    Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
-                    Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
-                }
-                int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() +
-                                graph.getNodes().filter(CommitAllocationNode.class).count();
-                Assert.assertEquals(0, newInstanceCount);
-                return returnNode;
+                returnNode = graph.getNodes().filter(ReturnNode.class).first();
             }
         });
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Oct 22 11:43:37 2013 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.alloc.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
@@ -133,9 +132,9 @@
      *            argument can be null.
      * @return the result of the compilation
      */
-    public static CompilationResult compileGraph(final StructuredGraph graph, final CallingConvention cc, final ResolvedJavaMethod installedCodeOwner, final Providers providers,
+    public static <T extends CompilationResult> T compileGraph(final StructuredGraph graph, final CallingConvention cc, final ResolvedJavaMethod installedCodeOwner, final Providers providers,
                     final Backend backend, final TargetDescription target, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts,
-                    final SpeculationLog speculationLog, final Suites suites, final CompilationResult compilationResult) {
+                    final SpeculationLog speculationLog, final Suites suites, final T compilationResult) {
         Debug.scope("GraalCompiler", new Object[]{graph, providers.getCodeCache()}, new Runnable() {
 
             public void run() {
@@ -290,17 +289,4 @@
 
         Debug.dump(result, "After code generation");
     }
-
-    /**
-     * Creates a set of providers via {@link Graal#getRequiredCapability(Class)}.
-     */
-    public static Providers getGraalProviders() {
-        MetaAccessProvider metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class);
-        CodeCacheProvider codeCache = Graal.getRequiredCapability(CodeCacheProvider.class);
-        ConstantReflectionProvider constantReflection = Graal.getRequiredCapability(ConstantReflectionProvider.class);
-        ForeignCallsProvider foreignCalls = Graal.getRequiredCapability(ForeignCallsProvider.class);
-        LoweringProvider lowerer = Graal.getRequiredCapability(LoweringProvider.class);
-        Replacements replacements = Graal.getRequiredCapability(Replacements.class);
-        return new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements);
-    }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Oct 22 11:43:37 2013 +0200
@@ -52,6 +52,8 @@
                    "Complete - aggregate by qualified name%n" +
                    "Thread - aggregate by qualified name and thread")
     public static final OptionValue<String> DebugValueSummary = new OptionValue<>("Name");
+    @Option(help = "Omit reporting 0-value metrics")
+    public static final OptionValue<Boolean> SuppressZeroDebugValues = 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")
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Oct 22 11:43:37 2013 +0200
@@ -64,7 +64,7 @@
         }
 
         if (OptEliminatePartiallyRedundantGuards.getValue()) {
-            appendPhase(new EliminatePartiallyRedundantGuardsPhase(false, true));
+            appendPhase(new OptimizeGuardAnchors());
         }
 
         if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
@@ -72,7 +72,7 @@
         }
 
         if (OptEliminatePartiallyRedundantGuards.getValue()) {
-            appendPhase(new EliminatePartiallyRedundantGuardsPhase(true, true));
+            appendPhase(new OptimizeGuardAnchors());
         }
 
         if (OptCanonicalizer.getValue()) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Tue Oct 22 11:43:37 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -54,6 +55,10 @@
         return providers.getForeignCalls();
     }
 
+    public abstract SuitesProvider getSuites();
+
+    public abstract DisassemblerProvider getDisassembler();
+
     public TargetDescription getTarget() {
         return providers.getCodeCache().getTarget();
     }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java	Tue Oct 22 11:43:37 2013 +0200
@@ -28,6 +28,8 @@
 
     public MetricImpl(String name, boolean conditional) {
         super(name, conditional);
+        // Allows for zero-count metrics to be shown
+        getCurrentValue();
     }
 
     public void increment() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Oct 22 11:43:37 2013 +0200
@@ -125,7 +125,8 @@
         return registry.make(key);
     }
 
-    static final int NOT_ITERABLE = -1;
+    public static final int NOT_ITERABLE = -1;
+    public static final int NODE_LIST = -2;
 
     private static final Class<?> NODE_CLASS = Node.class;
     private static final Class<?> INPUT_LIST_CLASS = NodeInputList.class;
@@ -817,6 +818,12 @@
         }
     }
 
+    public NodeList<?> getNodeList(Node node, Position pos) {
+        long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index];
+        assert pos.subIndex == NODE_LIST;
+        return getNodeList(node, offset);
+    }
+
     public String getName(Position pos) {
         return fieldNames.get(pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]);
     }
@@ -1175,20 +1182,64 @@
         return false;
     }
 
-    public List<Position> getFirstLevelInputPositions() {
-        List<Position> positions = new ArrayList<>(inputOffsets.length);
-        for (int i = 0; i < inputOffsets.length; i++) {
-            positions.add(new Position(true, i, NOT_ITERABLE));
-        }
-        return positions;
+    public Collection<Position> getFirstLevelInputPositions() {
+        return new AbstractCollection<Position>() {
+            @Override
+            public Iterator<Position> iterator() {
+                return new Iterator<NodeClass.Position>() {
+                    int i = 0;
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public Position next() {
+                        Position pos = new Position(true, i, i >= directInputCount ? 0 : NOT_ITERABLE);
+                        i++;
+                        return pos;
+                    }
+
+                    public boolean hasNext() {
+                        return i < inputOffsets.length;
+                    }
+                };
+            }
+
+            @Override
+            public int size() {
+                return inputOffsets.length;
+            }
+        };
     }
 
-    public List<Position> getFirstLevelSuccessorPositions() {
-        List<Position> positions = new ArrayList<>(successorOffsets.length);
-        for (int i = 0; i < successorOffsets.length; i++) {
-            positions.add(new Position(false, i, NOT_ITERABLE));
-        }
-        return positions;
+    public Collection<Position> getFirstLevelSuccessorPositions() {
+        return new AbstractCollection<Position>() {
+            @Override
+            public Iterator<Position> iterator() {
+                return new Iterator<NodeClass.Position>() {
+                    int i = 0;
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public Position next() {
+                        Position pos = new Position(false, i, i >= directSuccessorCount ? 0 : NOT_ITERABLE);
+                        i++;
+                        return pos;
+                    }
+
+                    public boolean hasNext() {
+                        return i < successorOffsets.length;
+                    }
+                };
+            }
+
+            @Override
+            public int size() {
+                return successorOffsets.length;
+            }
+        };
     }
 
     public Class<?> getJavaClass() {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Oct 22 11:43:37 2013 +0200
@@ -39,6 +39,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -239,6 +240,19 @@
         Label verifiedStub = new Label();
 
         // Emit the prefix
+        emitCodePrefix(installedCodeOwner, tasm, asm, regConfig, config, verifiedStub);
+
+        // Emit code for the LIR
+        emitCodeBody(installedCodeOwner, tasm, lirGen);
+
+        // Emit the suffix
+        emitCodeSuffix(installedCodeOwner, tasm, lirGen, asm, frameMap);
+    }
+
+    /**
+     * @param installedCodeOwner see {@link Backend#emitCode}
+     */
+    protected void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) {
         HotSpotProviders providers = getProviders();
         if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) {
             tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
@@ -263,10 +277,20 @@
         tasm.recordMark(Marks.MARK_OSR_ENTRY);
         asm.bind(verifiedStub);
         tasm.recordMark(Marks.MARK_VERIFIED_ENTRY);
+    }
 
-        // Emit code for the LIR
+    /**
+     * @param installedCodeOwner see {@link Backend#emitCode}
+     */
+    protected void emitCodeBody(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen) {
         lirGen.lir.emitCode(tasm);
+    }
 
+    /**
+     * @param installedCodeOwner see {@link Backend#emitCode}
+     */
+    protected void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen, AMD64MacroAssembler asm, FrameMap frameMap) {
+        HotSpotProviders providers = getProviders();
         HotSpotFrameContext frameContext = (HotSpotFrameContext) tasm.frameContext;
         if (frameContext != null && !frameContext.isStub) {
             HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls();
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Oct 22 11:43:37 2013 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
 
 @ServiceProvider(HotSpotBackendFactory.class)
@@ -51,26 +52,67 @@
         assert host == null;
         TargetDescription target = createTarget(runtime.getConfig());
 
-        HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
-        HotSpotCodeCacheProvider codeCache = new AMD64HotSpotCodeCacheProvider(runtime, target);
-        HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
+        HotSpotMetaAccessProvider metaAccess = createMetaAccess(runtime);
+        HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target);
+        HotSpotConstantReflectionProvider constantReflection = createConstantReflection(runtime);
         Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig());
-        HotSpotForeignCallsProvider foreignCalls = new AMD64HotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters);
-        HotSpotLoweringProvider lowerer = new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls);
+        HotSpotForeignCallsProvider foreignCalls = createForeignCalls(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters);
+        HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls);
         // Replacements cannot have speculative optimizations since they have
         // to be valid for the entire run of the VM.
         Assumptions assumptions = new Assumptions(false);
         Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null);
-        HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, runtime.getConfig(), assumptions);
-        HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime);
-        HotSpotSuitesProvider suites = new HotSpotSuitesProvider(runtime);
-        HotSpotRegisters registers = new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp);
+        Replacements replacements = createReplacements(runtime, assumptions, p);
+        HotSpotDisassemblerProvider disassembler = createDisassembler(runtime);
+        HotSpotSuitesProvider suites = createSuites(runtime);
+        HotSpotRegisters registers = createRegisters();
         HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
 
+        return createBackend(runtime, providers);
+    }
+
+    protected AMD64HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
         return new AMD64HotSpotBackend(runtime, providers);
     }
 
-    private static Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) {
+    protected HotSpotRegisters createRegisters() {
+        return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp);
+    }
+
+    protected HotSpotDisassemblerProvider createDisassembler(HotSpotGraalRuntime runtime) {
+        return new HotSpotDisassemblerProvider(runtime);
+    }
+
+    protected Replacements createReplacements(HotSpotGraalRuntime runtime, Assumptions assumptions, Providers p) {
+        return new HotSpotReplacementsImpl(p, runtime.getConfig(), assumptions);
+    }
+
+    protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache,
+                    Value[] nativeABICallerSaveRegisters) {
+        return new AMD64HotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters);
+    }
+
+    protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotGraalRuntime runtime) {
+        return new HotSpotConstantReflectionProvider(runtime);
+    }
+
+    protected AMD64HotSpotCodeCacheProvider createCodeCache(HotSpotGraalRuntime runtime, TargetDescription target) {
+        return new AMD64HotSpotCodeCacheProvider(runtime, target);
+    }
+
+    protected HotSpotMetaAccessProvider createMetaAccess(HotSpotGraalRuntime runtime) {
+        return new HotSpotMetaAccessProvider(runtime);
+    }
+
+    protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntime runtime) {
+        return new HotSpotSuitesProvider(runtime);
+    }
+
+    protected AMD64HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls) {
+        return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls);
+    }
+
+    protected Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) {
         List<Register> callerSave = new ArrayList<>(Arrays.asList(regConfig.getAllocatableRegisters()));
         if (config.windowsOs) {
             // http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Tue Oct 22 11:43:37 2013 +0200
@@ -81,7 +81,7 @@
         if (hsailCompResult != null) {
             hsailCompResult.dumpCompilationResult();
         }
-        return hsailCompResult.getCompilationResult();
+        return hsailCompResult;
     }
 
     // Implementations of the CompileAndDispatch interface.
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java	Tue Oct 22 11:43:37 2013 +0200
@@ -33,10 +33,10 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hsail.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
@@ -44,13 +44,15 @@
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
+import com.oracle.graal.runtime.*;
 
 /**
  * Class that represents a HSAIL compilation result. Includes the compiled HSAIL code.
  */
-public class HSAILCompilationResult {
+public class HSAILCompilationResult extends CompilationResult {
 
-    private CompilationResult compResult;
+    private static final long serialVersionUID = -4178700465275724625L;
+
     private static final String propPkgName = HSAILCompilationResult.class.getPackage().getName();
     private static Level logLevel;
     private static ConsoleHandler consoleHandler;
@@ -78,7 +80,8 @@
     static final HSAILHotSpotBackend backend;
     static {
         // Look for installed HSAIL backend
-        HSAILHotSpotBackend b = (HSAILHotSpotBackend) Graal.getRuntime().getCapability(Backend.class, "HSAIL");
+        RuntimeProvider runtime = Graal.getRequiredCapability(RuntimeProvider.class);
+        HSAILHotSpotBackend b = (HSAILHotSpotBackend) runtime.getBackend(HSAIL.class);
         if (b == null) {
             // Fall back to a new instance
             b = new HSAILHotSpotBackendFactory().createBackend(runtime(), runtime().getHostBackend());
@@ -137,11 +140,11 @@
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new HSAILPhase());
         new HSAILPhase().apply(graph);
         CallingConvention cc = getHSAILCallingConvention(Type.JavaCallee, target, graph.method(), false);
-        SuitesProvider suitesProvider = Graal.getRequiredCapability(SuitesProvider.class);
+        SuitesProvider suitesProvider = backend.getSuites();
         try {
-            CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, graph.method(), providers, backend, target, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(),
-                            suitesProvider.getDefaultSuites(), new CompilationResult());
-            return new HSAILCompilationResult(compResult);
+            HSAILCompilationResult compResult = GraalCompiler.compileGraph(graph, cc, graph.method(), providers, backend, target, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(),
+                            suitesProvider.getDefaultSuites(), new HSAILCompilationResult());
+            return compResult;
         } catch (GraalInternalError e) {
             String partialCode = backend.getPartialCodeString();
             if (partialCode != null && !partialCode.equals("")) {
@@ -165,20 +168,15 @@
         }
     }
 
-    protected HSAILCompilationResult(CompilationResult compResultInput) {
-        compResult = compResultInput;
-    }
-
-    public CompilationResult getCompilationResult() {
-        return compResult;
+    protected HSAILCompilationResult() {
     }
 
     public String getHSAILCode() {
-        return new String(compResult.getTargetCode(), 0, compResult.getTargetCodeSize());
+        return new String(getTargetCode(), 0, getTargetCodeSize());
     }
 
     public void dumpCompilationResult() {
-        logger.fine("targetCodeSize=" + compResult.getTargetCodeSize());
+        logger.fine("targetCodeSize=" + getTargetCodeSize());
         logger.fine(getHSAILCode());
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java	Tue Oct 22 11:43:37 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.hsail;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -35,6 +37,12 @@
     }
 
     @Override
+    public String disassemble(CompilationResult compResult, InstalledCode installedCode) {
+        byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode();
+        return new String(code);
+    }
+
+    @Override
     protected RegisterConfig createRegisterConfig() {
         return new HSAILRegisterConfig();
     }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Tue Oct 22 11:43:37 2013 +0200
@@ -55,10 +55,7 @@
     private final Register[] nativeGeneralParameterRegisters;
 
     private static Register[] initAllocatable() {
-        Register[] registers = new Register[] {
-            r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
-            r8,  r9,  r10, r11, r12, r13, r14, r15,
-        };
+        Register[] registers = new Register[]{r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15};
 
         return registers;
     }
@@ -94,9 +91,8 @@
         throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getRegisterForRole()");
     }
 
-    private static CallingConvention callingConvention(@SuppressWarnings("unused") Register[] generalParameterRegisters,
-                                                JavaType returnType, JavaType[] parameterTypes,
-                                                Type type, TargetDescription target, boolean stackOnly) {
+    private static CallingConvention callingConvention(@SuppressWarnings("unused") Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type,
+                    TargetDescription target, boolean stackOnly) {
 
         assert stackOnly == false;
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Tue Oct 22 11:43:37 2013 +0200
@@ -41,13 +41,13 @@
     @Override
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         // TODO the patched call address looks odd (and is invalid) compared to other runtime calls:
-// 0xffffffff749bb5fc: call 0xffffffff415a720c ; {runtime_call}
-// [Exception Handler]
-// 0xffffffff749bb604: call 0xffffffff749bb220 ; {runtime_call}
-// 0xffffffff749bb608: nop
-// [Deopt Handler Code]
-// 0xffffffff749bb60c: call 0xffffffff748da540 ; {runtime_call}
-// 0xffffffff749bb610: nop
+        // 0xffffffff749bb5fc: call 0xffffffff415a720c ; {runtime_call}
+        // [Exception Handler]
+        // 0xffffffff749bb604: call 0xffffffff749bb220 ; {runtime_call}
+        // 0xffffffff749bb608: nop
+        // [Deopt Handler Code]
+        // 0xffffffff749bb60c: call 0xffffffff748da540 ; {runtime_call}
+        // 0xffffffff749bb610: nop
         SPARCCall.directCall(tasm, masm, tasm.foreignCalls.lookupForeignCall(UNCOMMON_TRAP), null, false, info);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Tue Oct 22 11:43:37 2013 +0200
@@ -41,14 +41,14 @@
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         leaveFrame(tasm);
 
-// SPARCHotSpotBackend backend = (SPARCHotSpotBackend)
-// HotSpotGraalRuntime.runtime().getBackend();
-// final boolean isStub = true;
-// HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub);
-// frameContext.enter(tasm);
+        // SPARCHotSpotBackend backend = (SPARCHotSpotBackend)
+        // HotSpotGraalRuntime.runtime().getBackend();
+        // final boolean isStub = true;
+        // HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub);
+        // frameContext.enter(tasm);
         Register scratch = g3;
         SPARCCall.indirectJmp(tasm, masm, scratch, tasm.foreignCalls.lookupForeignCall(UNCOMMON_TRAP));
 
-// frameContext.leave(tasm);
+        // frameContext.leave(tasm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Oct 22 11:43:37 2013 +0200
@@ -154,7 +154,7 @@
 
     @Override
     public void emitTailcall(Value[] args, Value address) {
-// append(new AMD64TailcallOp(args, address));
+        // append(new AMD64TailcallOp(args, address));
         throw GraalInternalError.unimplemented();
     }
 
@@ -242,14 +242,16 @@
         assert access == null || access instanceof HeapAccess;
         if (isCompressCandidate(access)) {
             if (config.useCompressedOops && kind == Kind.Object) {
-// append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) :
-// null, config.narrowOopBase, config.narrowOopShift,
-// config.logMinObjAlignment));
+                // append(new LoadCompressedPointer(kind, result, loadAddress, access != null ?
+                // state(access) :
+                // null, config.narrowOopBase, config.narrowOopShift,
+                // config.logMinObjAlignment));
                 throw GraalInternalError.unimplemented();
             } else if (config.useCompressedClassPointers && kind == Kind.Long) {
-// append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) :
-// null, config.narrowKlassBase, config.narrowKlassShift,
-// config.logKlassAlignment));
+                // append(new LoadCompressedPointer(kind, result, loadAddress, access != null ?
+                // state(access) :
+                // null, config.narrowKlassBase, config.narrowKlassShift,
+                // config.logKlassAlignment));
                 throw GraalInternalError.unimplemented();
             } else {
                 append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
@@ -280,21 +282,21 @@
         Variable input = load(inputVal);
         if (isCompressCandidate(access)) {
             if (config.useCompressedOops && kind == Kind.Object) {
-// if (input.getKind() == Kind.Object) {
-// Variable scratch = newVariable(Kind.Long);
-// append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state,
-// config.narrowOopBase, config.narrowOopShift,
-// config.logMinObjAlignment));
-// } else {
-// // the input oop is already compressed
-// append(new StoreOp(input.getKind(), storeAddress, input, state));
-// }
+                // if (input.getKind() == Kind.Object) {
+                // Variable scratch = newVariable(Kind.Long);
+                // append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state,
+                // config.narrowOopBase, config.narrowOopShift,
+                // config.logMinObjAlignment));
+                // } else {
+                // // the input oop is already compressed
+                // append(new StoreOp(input.getKind(), storeAddress, input, state));
+                // }
                 throw GraalInternalError.unimplemented();
             } else if (config.useCompressedClassPointers && kind == Kind.Long) {
-// Variable scratch = newVariable(Kind.Long);
-// append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state,
-// config.narrowKlassBase, config.narrowKlassShift,
-// config.logKlassAlignment));
+                // Variable scratch = newVariable(Kind.Long);
+                // append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state,
+                // config.narrowKlassBase, config.narrowKlassShift,
+                // config.logKlassAlignment));
                 throw GraalInternalError.unimplemented();
             } else {
                 append(new StoreOp(kind, storeAddress, input, state));
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -41,6 +41,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.runtime.*;
 
 /**
  * use
@@ -204,7 +205,7 @@
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
         // create suites everytime, as we modify options for the compiler
-        final Suites suitesLocal = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
+        final Suites suitesLocal = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites();
         final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
                         new SpeculationLog(), suitesLocal, new CompilationResult());
         addMethod(method, compResult);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.runtime.*;
 
 /**
  * The following tests perform object/array equality and assignments in various ways. The selected
@@ -43,7 +44,7 @@
     private final MetaAccessProvider metaAccess;
 
     public CompressedOopTest() {
-        this.metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class);
+        this.metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess();
     }
 
     private HotSpotInstalledCode getInstalledCode(String name) throws Exception {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.runtime.*;
 
 public class InstalledCodeExecuteHelperTest extends GraalCompilerTest {
 
@@ -43,7 +44,7 @@
     Object[] argsToBind;
 
     public InstalledCodeExecuteHelperTest() {
-        this.metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class);
+        this.metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess();
     }
 
     @Test
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -43,6 +43,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.runtime.*;
 
 /**
  * The following unit tests assert the presence of write barriers for both Serial and G1 GCs.
@@ -58,7 +59,7 @@
     private final MetaAccessProvider metaAccess;
 
     public WriteBarrierAdditionTest() {
-        this.metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class);
+        this.metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess();
     }
 
     public static class Container {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Oct 22 11:43:37 2013 +0200
@@ -140,7 +140,11 @@
 
                     @Override
                     public CompilationResult call() throws Exception {
-                        backend.getRuntime().evictDeoptedGraphs();
+                        GraphCache graphCache = backend.getRuntime().getGraphCache();
+                        if (graphCache != null) {
+                            graphCache.removeStaleGraphs();
+                        }
+
                         HotSpotProviders providers = backend.getProviders();
                         Replacements replacements = providers.getReplacements();
                         graph = replacements.getMethodSubstitution(method);
@@ -153,8 +157,8 @@
                         InliningUtil.InlinedBytecodes.add(method.getCodeSize());
                         CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
                         Suites suites = providers.getSuites().getDefaultSuites();
-                        return GraalCompiler.compileGraph(graph, cc, method, providers, backend, backend.getTarget(), backend.getRuntime().getCache(), plan, optimisticOpts,
-                                        method.getSpeculationLog(), suites, new CompilationResult());
+                        return GraalCompiler.compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, plan, optimisticOpts, method.getSpeculationLog(), suites,
+                                        new CompilationResult());
                     }
                 });
             } finally {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Tue Oct 22 11:43:37 2013 +0200
@@ -22,12 +22,14 @@
  */
 package com.oracle.graal.hotspot;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -82,4 +84,14 @@
     public HotSpotProviders getProviders() {
         return (HotSpotProviders) super.getProviders();
     }
+
+    @Override
+    public SuitesProvider getSuites() {
+        return getProviders().getSuites();
+    }
+
+    @Override
+    public DisassemblerProvider getDisassembler() {
+        return getProviders().getDisassembler();
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Oct 22 11:43:37 2013 +0200
@@ -38,15 +38,14 @@
 import com.oracle.graal.hotspot.bridge.*;
 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 com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.runtime.*;
 
 /**
  * Singleton class holding the instance of the {@link GraalRuntime}.
  */
-public final class HotSpotGraalRuntime implements GraalRuntime {
+public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider {
 
     private static final HotSpotGraalRuntime instance = new HotSpotGraalRuntime();
     static {
@@ -106,11 +105,11 @@
         for (HotSpotBackendFactory factory : ServiceLoader.loadInstalled(HotSpotBackendFactory.class)) {
             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
                 if (factory.getGraalRuntimeName().equals(GraalRuntime.getValue())) {
-                    assert selected == null;
+                    assert selected == null || checkFactoryOverriding(selected, factory);
                     selected = factory;
                 }
                 if (factory.getGraalRuntimeName().equals("basic")) {
-                    assert basic == null;
+                    assert basic == null || checkFactoryOverriding(basic, factory);
                     basic = factory;
                 } else {
                     nonBasic = factory;
@@ -136,6 +135,18 @@
     }
 
     /**
+     * Checks that a factory overriding is valid. A factory B can only override/replace a factory A
+     * if the B.getClass() is a subclass of A.getClass(). This models the assumption that B is
+     * extends the behavior of A and has therefore understood the behavior expected of A.
+     * 
+     * @param baseFactory
+     * @param overridingFactory
+     */
+    private static boolean checkFactoryOverriding(HotSpotBackendFactory baseFactory, HotSpotBackendFactory overridingFactory) {
+        return baseFactory.getClass().isAssignableFrom(overridingFactory.getClass());
+    }
+
+    /**
      * Gets the kind of a word value on the {@linkplain #getHostBackend() host} backend.
      */
     public static Kind getHostWordKind() {
@@ -173,15 +184,13 @@
     protected/* final */CompilerToGPU compilerToGpu;
     protected/* final */VMToCompiler vmToCompiler;
 
-    protected final HotSpotProviders hostProviders;
-
     private HotSpotRuntimeInterpreterInterface runtimeInterpreterInterface;
     private volatile HotSpotGraphCache cache;
 
     protected final HotSpotVMConfig config;
     private final HotSpotBackend hostBackend;
 
-    private final Map<String, HotSpotBackend> backends = new HashMap<>();
+    private final Map<Class<? extends Architecture>, HotSpotBackend> backends = new HashMap<>();
 
     private HotSpotGraalRuntime() {
         CompilerToVM toVM = new CompilerToVMImpl();
@@ -210,31 +219,36 @@
             printConfig(config);
         }
 
-        String hostArchitecture = getHostArchitecture();
-        hostBackend = findFactory(hostArchitecture).createBackend(this, null);
-        hostProviders = hostBackend.getProviders();
-        backends.put(hostArchitecture, hostBackend);
+        String hostArchitecture = getHostArchitectureName();
+        hostBackend = registerBackend(findFactory(hostArchitecture).createBackend(this, null));
 
-        String[] gpuArchitectures = getGPUArchitectures();
+        String[] gpuArchitectures = getGPUArchitectureNames();
         for (String arch : gpuArchitectures) {
             HotSpotBackendFactory factory = findFactory(arch);
             if (factory == null) {
                 throw new GraalInternalError("No backend available for specified GPU architecture \"%s\"", arch);
             }
-            backends.put(factory.getArchitecture(), factory.createBackend(this, hostBackend));
+            registerBackend(factory.createBackend(this, hostBackend));
         }
 
         GraalOptions.StackShadowPages.setValue(config.stackShadowPages);
         if (GraalOptions.CacheGraphs.getValue()) {
-            cache = new HotSpotGraphCache();
+            cache = new HotSpotGraphCache(compilerToVm);
         }
     }
 
+    private HotSpotBackend registerBackend(HotSpotBackend backend) {
+        Class<? extends Architecture> arch = backend.getTarget().arch.getClass();
+        HotSpotBackend oldValue = backends.put(arch, backend);
+        assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName();
+        return backend;
+    }
+
     /**
      * Gets the host architecture name for the purpose of finding the corresponding
      * {@linkplain HotSpotBackendFactory backend}.
      */
-    private static String getHostArchitecture() {
+    private static String getHostArchitectureName() {
         String arch = System.getProperty("os.arch");
         switch (arch) {
             case "x86_64":
@@ -250,16 +264,17 @@
     /**
      * Gets the names of the supported GPU architectures for the purpose of finding the
      * corresponding {@linkplain HotSpotBackendFactory backend} objects. This method first looks for
-     * a comma separated list of names in the {@value #GRAAL_GPU_ISALIST_PROPERTY_NAME} system
-     * property. If this property is not set, then the GPU native support code is queried.
+     * a comma or {@link java.io.File#pathSeparatorChar} separated list of names in the
+     * {@value #GRAAL_GPU_ISALIST_PROPERTY_NAME} system property. If this property is not set, then
+     * the GPU native support code is queried.
      */
-    private String[] getGPUArchitectures() {
+    private static String[] getGPUArchitectureNames() {
         String gpuList = System.getProperty(GRAAL_GPU_ISALIST_PROPERTY_NAME);
-        if (gpuList != null) {
-            String[] gpus = gpuList.split(",");
+        if (gpuList != null && !gpuList.isEmpty()) {
+            String[] gpus = gpuList.split("[,:]");
             return gpus;
         }
-        return compilerToGpu.getAvailableGPUArchitectures();
+        return new String[0];
     }
 
     private static void printConfig(HotSpotVMConfig config) {
@@ -285,7 +300,7 @@
         return hostBackend.getTarget();
     }
 
-    public HotSpotGraphCache getCache() {
+    public HotSpotGraphCache getGraphCache() {
         return cache;
     }
 
@@ -335,26 +350,13 @@
 
     public HotSpotRuntimeInterpreterInterface getRuntimeInterpreterInterface() {
         if (runtimeInterpreterInterface == null) {
-            runtimeInterpreterInterface = new HotSpotRuntimeInterpreterInterface(hostProviders.getMetaAccess());
+            runtimeInterpreterInterface = new HotSpotRuntimeInterpreterInterface(getHostProviders().getMetaAccess());
         }
         return runtimeInterpreterInterface;
     }
 
     public HotSpotProviders getHostProviders() {
-        return hostProviders;
-    }
-
-    public void evictDeoptedGraphs() {
-        if (cache != null) {
-            long[] deoptedGraphs = getCompilerToVM().getDeoptedLeafGraphIds();
-            if (deoptedGraphs != null) {
-                if (deoptedGraphs.length == 0) {
-                    cache.clear();
-                } else {
-                    cache.removeGraphs(deoptedGraphs);
-                }
-            }
-        }
+        return getHostBackend().getProviders();
     }
 
     @Override
@@ -363,60 +365,24 @@
     }
 
     @SuppressWarnings("unchecked")
-    public static <T> T getCapability(HotSpotBackend backend, Class<T> clazz) {
-        HotSpotProviders providers = backend.getProviders();
-        if (clazz == LoweringProvider.class) {
-            return (T) providers.getLowerer();
-        }
-        if (clazz == CodeCacheProvider.class) {
-            return (T) providers.getCodeCache();
-        }
-        if (clazz == MetaAccessProvider.class) {
-            return (T) providers.getMetaAccess();
-        }
-        if (clazz == ConstantReflectionProvider.class) {
-            return (T) providers.getConstantReflection();
-        }
-        if (clazz == ForeignCallsProvider.class) {
-            return (T) providers.getForeignCalls();
-        }
-        if (clazz == DisassemblerProvider.class) {
-            return (T) providers.getDisassembler();
-        }
-        if (clazz == BytecodeDisassemblerProvider.class) {
-            return (T) providers.getBytecodeDisassembler();
-        }
-        if (clazz == SuitesProvider.class) {
-            return (T) providers.getSuites();
-        }
-        if (clazz == Replacements.class) {
-            return (T) providers.getReplacements();
-        }
-        if (clazz == HotSpotRegistersProvider.class) {
-            return (T) providers.getRegisters();
-        }
-        if (clazz == Backend.class) {
-            return (T) backend;
+    @Override
+    public <T> T getCapability(Class<T> clazz) {
+        if (clazz == RuntimeProvider.class) {
+            return (T) this;
         }
         return null;
     }
 
-    @Override
-    public <T> T getCapability(Class<T> clazz) {
-        return getCapability(clazz, null);
-    }
-
-    @Override
-    public <T> T getCapability(Class<T> clazz, String selector) {
-        HotSpotBackend backend = selector == null ? hostBackend : backends.get(selector);
-        return backend == null ? null : getCapability(backend, clazz);
-    }
-
     public HotSpotBackend getHostBackend() {
         return hostBackend;
     }
 
-    public Map<String, HotSpotBackend> getBackends() {
+    public <T extends Architecture> Backend getBackend(Class<T> arch) {
+        assert arch != Architecture.class;
+        return backends.get(arch);
+    }
+
+    public Map<Class<? extends Architecture>, HotSpotBackend> getBackends() {
         return Collections.unmodifiableMap(backends);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java	Tue Oct 22 11:43:37 2013 +0200
@@ -48,11 +48,6 @@
     int availableProcessors();
 
     /**
-     * Gets the architecture names of the available GPUs.
-     */
-    String[] getAvailableGPUArchitectures();
-
-    /**
      * Attempts to generate and return a bound function to the loaded method kernel on the GPU.
      * 
      * @param code the text or binary values for a method kernel
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java	Tue Oct 22 11:43:37 2013 +0200
@@ -39,8 +39,6 @@
 
     public native int availableProcessors();
 
-    public native String[] getAvailableGPUArchitectures();
-
     public native Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
     public native Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Oct 22 11:43:37 2013 +0200
@@ -193,7 +193,7 @@
                     List<LoweringProvider> initializedLowerers = new ArrayList<>();
                     List<ForeignCallsProvider> initializedForeignCalls = new ArrayList<>();
 
-                    for (Map.Entry<String, HotSpotBackend> e : runtime.getBackends().entrySet()) {
+                    for (Map.Entry<?, HotSpotBackend> e : runtime.getBackends().entrySet()) {
                         HotSpotBackend backend = e.getValue();
                         HotSpotProviders providers = backend.getProviders();
 
@@ -361,8 +361,8 @@
         bootstrapRunning = false;
 
         TTY.println(" in %d ms (compiled %d methods)", System.currentTimeMillis() - startTime, compileQueue.getCompletedTaskCount());
-        if (runtime.getCache() != null) {
-            runtime.getCache().clear();
+        if (runtime.getGraphCache() != null) {
+            runtime.getGraphCache().clear();
         }
         System.gc();
         phaseTransition("bootstrap2");
@@ -533,7 +533,7 @@
 
         for (DebugValue value : debugValues) {
             long l = scope.map.getCurrentValue(value.getIndex());
-            if (l != 0) {
+            if (l != 0 || !SuppressZeroDebugValues.getValue()) {
                 scope.print();
                 printIndent(scope.level + 1);
                 TTY.println(value.getName() + "=" + value.toString(l));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Tue Oct 22 11:43:37 2013 +0200
@@ -30,6 +30,7 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -96,7 +97,8 @@
 
     private final Map<Long, WeakReference<ResolvedJavaMethod>> cachedGraphIds = Collections.synchronizedMap(new LRUCache());
 
-    public HotSpotGraphCache() {
+    public HotSpotGraphCache(CompilerToVM compilerToVM) {
+        this.compilerToVM = compilerToVM;
         if (PrintGraphCache.getValue()) {
             Runtime.getRuntime().addShutdownHook(new Thread() {
 
@@ -127,7 +129,7 @@
     }
 
     @Override
-    public void put(StructuredGraph graph, boolean hasMatureProfilingInfo) {
+    public boolean put(StructuredGraph graph, boolean hasMatureProfilingInfo) {
         assert graph.method() != null;
         if (hasMatureProfilingInfo) {
             cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method()));
@@ -136,7 +138,9 @@
             if (PrintGraphCache.getValue()) {
                 putCounter++;
             }
+            return true;
         }
+        return false;
     }
 
     public void clear() {
@@ -174,4 +178,17 @@
             }
         }
     }
+
+    private final CompilerToVM compilerToVM;
+
+    public void removeStaleGraphs() {
+        long[] deoptedGraphs = compilerToVM.getDeoptedLeafGraphIds();
+        if (deoptedGraphs != null) {
+            if (deoptedGraphs.length == 0) {
+                clear();
+            } else {
+                removeGraphs(deoptedGraphs);
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Tue Oct 22 11:43:37 2013 +0200
@@ -79,14 +79,29 @@
         return runtime.getCompilerToVM().getJavaField(reflectionField);
     }
 
+    private static final int ACTION_SHIFT = 0;
+    private static final int ACTION_MASK = 0x07;
+    private static final int REASON_SHIFT = 3;
+    private static final int REASON_MASK = 0x1f;
+
     @Override
     public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
-        final int actionShift = 0;
-        final int reasonShift = 3;
-
         int actionValue = convertDeoptAction(action);
         int reasonValue = convertDeoptReason(reason);
-        return Constant.forInt(~(((reasonValue) << reasonShift) + ((actionValue) << actionShift)));
+        Constant c = Constant.forInt(~(((reasonValue) << REASON_SHIFT) + ((actionValue) << ACTION_SHIFT)));
+        return c;
+    }
+
+    public DeoptimizationReason decodeDeoptReason(Constant constant) {
+        int reasonValue = ((~constant.asInt()) >> REASON_SHIFT) & REASON_MASK;
+        DeoptimizationReason reason = convertDeoptReason(reasonValue);
+        return reason;
+    }
+
+    public DeoptimizationAction decodeDeoptAction(Constant constant) {
+        int actionValue = ((~constant.asInt()) >> ACTION_SHIFT) & ACTION_MASK;
+        DeoptimizationAction action = convertDeoptAction(actionValue);
+        return action;
     }
 
     public int convertDeoptAction(DeoptimizationAction action) {
@@ -106,6 +121,22 @@
         }
     }
 
+    public DeoptimizationAction convertDeoptAction(int action) {
+        if (action == runtime.getConfig().deoptActionNone) {
+            return DeoptimizationAction.None;
+        } else if (action == runtime.getConfig().deoptActionMaybeRecompile) {
+            return DeoptimizationAction.RecompileIfTooManyDeopts;
+        } else if (action == runtime.getConfig().deoptActionReinterpret) {
+            return DeoptimizationAction.InvalidateReprofile;
+        } else if (action == runtime.getConfig().deoptActionMakeNotEntrant) {
+            return DeoptimizationAction.InvalidateRecompile;
+        } else if (action == runtime.getConfig().deoptActionMakeNotCompilable) {
+            return DeoptimizationAction.InvalidateStopCompiling;
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     public int convertDeoptReason(DeoptimizationReason reason) {
         switch (reason) {
             case None:
@@ -140,4 +171,38 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
+
+    public DeoptimizationReason convertDeoptReason(int reason) {
+        if (reason == runtime.getConfig().deoptReasonNone) {
+            return DeoptimizationReason.None;
+        } else if (reason == runtime.getConfig().deoptReasonNullCheck) {
+            return DeoptimizationReason.NullCheckException;
+        } else if (reason == runtime.getConfig().deoptReasonRangeCheck) {
+            return DeoptimizationReason.BoundsCheckException;
+        } else if (reason == runtime.getConfig().deoptReasonClassCheck) {
+            return DeoptimizationReason.ClassCastException;
+        } else if (reason == runtime.getConfig().deoptReasonArrayCheck) {
+            return DeoptimizationReason.ArrayStoreException;
+        } else if (reason == runtime.getConfig().deoptReasonUnreached0) {
+            return DeoptimizationReason.UnreachedCode;
+        } else if (reason == runtime.getConfig().deoptReasonTypeCheckInlining) {
+            return DeoptimizationReason.TypeCheckedInliningViolated;
+        } else if (reason == runtime.getConfig().deoptReasonOptimizedTypeCheck) {
+            return DeoptimizationReason.OptimizedTypeCheckViolated;
+        } else if (reason == runtime.getConfig().deoptReasonNotCompiledExceptionHandler) {
+            return DeoptimizationReason.NotCompiledExceptionHandler;
+        } else if (reason == runtime.getConfig().deoptReasonUnresolved) {
+            return DeoptimizationReason.Unresolved;
+        } else if (reason == runtime.getConfig().deoptReasonJsrMismatch) {
+            return DeoptimizationReason.JavaSubroutineMismatch;
+        } else if (reason == runtime.getConfig().deoptReasonDiv0Check) {
+            return DeoptimizationReason.ArithmeticException;
+        } else if (reason == runtime.getConfig().deoptReasonConstraint) {
+            return DeoptimizationReason.RuntimeConstraint;
+        } else if (reason == runtime.getConfig().deoptReasonLoopLimitCheck) {
+            return DeoptimizationReason.LoopLimitCheck;
+        } else {
+            throw GraalInternalError.shouldNotReachHere(Integer.toHexString(reason));
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Tue Oct 22 11:43:37 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.meta;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
 
@@ -59,10 +58,6 @@
         return disassembler;
     }
 
-    public BytecodeDisassemblerProvider getBytecodeDisassembler() {
-        return new BytecodeDisassembler();
-    }
-
     @Override
     public HotSpotForeignCallsProvider getForeignCalls() {
         return (HotSpotForeignCallsProvider) super.getForeignCalls();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -93,7 +93,8 @@
         }
         // the canonicalization before loop unrolling is needed to propagate the length into
         // additions, etc.
-        PhaseContext context = new PhaseContext(tool.getMetaAccess(), tool.getCodeCache(), tool.getConstantReflection(), tool.getForeignCalls(), tool.getLowerer(), tool.assumptions(), tool.getReplacements());
+        PhaseContext context = new PhaseContext(tool.getMetaAccess(), tool.getCodeCache(), tool.getConstantReflection(), tool.getForeignCalls(), tool.getLowerer(), tool.assumptions(),
+                        tool.getReplacements());
         new CanonicalizerPhase(true).apply(snippetGraph, context);
         new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(snippetGraph, context);
         new CanonicalizerPhase(true).apply(snippetGraph, context);
--- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java	Tue Oct 22 11:43:37 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.java.decompiler.test.example.*;
 import com.oracle.graal.printer.*;
+import com.oracle.graal.runtime.*;
 
 public class Test {
 
@@ -38,7 +39,7 @@
      */
     public static void main(String[] args) throws NoSuchMethodException, SecurityException {
         DebugEnvironment.initialize(System.out);
-        MetaAccessProvider metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class);
+        MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess();
         Method method = Example.class.getDeclaredMethod("loop7", new Class[]{int.class, int.class});
         final ResolvedJavaMethod javaMethod = metaAccess.lookupJavaMethod(method);
         TestUtil.compileMethod(javaMethod);
--- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java	Tue Oct 22 11:43:37 2013 +0200
@@ -36,12 +36,15 @@
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
+import com.oracle.graal.runtime.*;
 
 public class TestUtil {
 
     public static void compileMethod(ResolvedJavaMethod method) {
-        Providers providers = GraalCompiler.getGraalProviders();
-        Suites suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
+        Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
+        Providers providers = backend.getProviders();
+        SuitesProvider suitesProvider = backend.getSuites();
+        Suites suites = suitesProvider.createSuites();
         StructuredGraph graph = new StructuredGraph(method);
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         ForeignCallsProvider foreignCalls = providers.getForeignCalls();
@@ -50,7 +53,6 @@
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
-        Backend backend = Graal.getRequiredCapability(Backend.class);
         GraalCompiler.compileGraph(graph, cc, method, providers, backend, providers.getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog(), suites,
                         new CompilationResult());
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Oct 22 11:43:37 2013 +0200
@@ -795,7 +795,7 @@
         eagerResolvingForSnippets(cpi, opcode);
         JavaMethod result = constantPool.lookupMethod(cpi, opcode);
         // assert !graphBuilderConfig.unresolvedIsError() || ((result instanceof ResolvedJavaMethod)
-// && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result;
+        // && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result;
         return result;
     }
 
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Tue Oct 22 11:43:37 2013 +0200
@@ -53,7 +53,6 @@
         }
     }
 
-
     public static class ForeignCallNoArgOp extends HSAILLIRInstruction {
 
         @Def({REG}) protected Value out;
@@ -80,7 +79,6 @@
         }
     }
 
-
     public static class CompareBranchOp extends HSAILLIRInstruction implements StandardOp.BranchOp {
 
         @Opcode protected final HSAILCompare opcode;
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Tue Oct 22 11:43:37 2013 +0200
@@ -129,7 +129,6 @@
         }
     }
 
-
     public abstract static class MemOp extends HSAILLIRInstruction {
 
         protected final Kind kind;
@@ -268,8 +267,6 @@
         masm.emitCompressedOopDecode(result, narrowOopBase, narrowOopShift);
     }
 
-
-
     public static class LeaOp extends HSAILLIRInstruction {
 
         @Def({REG}) protected AllocatableValue result;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Tue Oct 22 11:43:37 2013 +0200
@@ -67,8 +67,7 @@
         }
     }
 
-    public static void emit(PTXAssembler masm, PTXCompare opcode,
-                            Condition condition, Value x, Value y, int p) {
+    public static void emit(PTXAssembler masm, PTXCompare opcode, Condition condition, Value x, Value y, int p) {
         if (isConstant(x)) {
             new Setp(condition, x, y, p).emit(masm);
         } else if (isConstant(y)) {
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Tue Oct 22 11:43:37 2013 +0200
@@ -43,8 +43,7 @@
         @Use({COMPOSITE}) protected PTXAddressValue address;
         @State protected LIRFrameState state;
 
-        public LoadOp(Kind kind, Variable result, PTXAddressValue address,
-                      LIRFrameState state) {
+        public LoadOp(Kind kind, Variable result, PTXAddressValue address, LIRFrameState state) {
             this.kind = kind;
             this.result = result;
             this.address = address;
@@ -63,8 +62,7 @@
                 case Float:
                 case Double:
                 case Object:
-                    new Ld(Global, result, addr.getBase(),
-                           Constant.forLong(addr.getDisplacement())).emit(masm);
+                    new Ld(Global, result, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -99,8 +97,7 @@
                 case Float:
                 case Double:
                 case Object:
-                    new St(Global, input, addr.getBase(),
-                           Constant.forLong(addr.getDisplacement())).emit(masm);
+                    new St(Global, input, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
@@ -117,8 +114,7 @@
         @Use({COMPOSITE}) protected PTXAddressValue address;
         @State protected LIRFrameState state;
 
-        public LoadParamOp(Kind kind, Variable result, PTXAddressValue address,
-                           LIRFrameState state) {
+        public LoadParamOp(Kind kind, Variable result, PTXAddressValue address, LIRFrameState state) {
             this.kind = kind;
             this.result = result;
             this.address = address;
@@ -137,8 +133,7 @@
                 case Float:
                 case Double:
                 case Object:
-                    new Ld(Parameter, result, addr.getBase(),
-                           Constant.forLong(addr.getDisplacement())).emit(masm);
+                    new Ld(Parameter, result, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -156,8 +151,7 @@
         @Use({COMPOSITE}) protected PTXAddressValue address;
         @State protected LIRFrameState state;
 
-        public LoadReturnAddrOp(Kind kind, Variable result,
-                                PTXAddressValue address, LIRFrameState state) {
+        public LoadReturnAddrOp(Kind kind, Variable result, PTXAddressValue address, LIRFrameState state) {
             this.kind = kind;
             this.result = result;
             this.address = address;
@@ -172,8 +166,7 @@
                 case Long:
                 case Float:
                 case Double:
-                    new Ld(Parameter, result, addr.getBase(),
-                           Constant.forLong(addr.getDisplacement())).emit(masm);
+                    new Ld(Parameter, result, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -190,8 +183,7 @@
         @Use({REG}) protected Variable input;
         @State protected LIRFrameState state;
 
-        public StoreReturnValOp(Kind kind, PTXAddressValue address,
-                                Variable input, LIRFrameState state) {
+        public StoreReturnValOp(Kind kind, PTXAddressValue address, Variable input, LIRFrameState state) {
             this.kind = kind;
             this.address = address;
             this.input = input;
@@ -210,8 +202,7 @@
                 case Float:
                 case Double:
                 case Object:
-                    new St(Global, input, addr.getBase(),
-                           Constant.forLong(addr.getDisplacement())).emit(masm);
+                    new St(Global, input, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ParallelOver.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ParallelOver.java	Tue Oct 22 11:43:37 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.lir.ptx.ThreadDimension.*;
 
 import java.lang.annotation.*;
+
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.PARAMETER})
 public @interface ParallelOver {
@@ -33,4 +34,3 @@
 
     ThreadDimension dimension() default X;
 }
-
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ThreadDimension.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ThreadDimension.java	Tue Oct 22 11:43:37 2013 +0200
@@ -23,8 +23,5 @@
 package com.oracle.graal.lir.ptx;
 
 public enum ThreadDimension {
-X,
-Y,
-Z
+    X, Y, Z
 }
-
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/Warp.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/Warp.java	Tue Oct 22 11:43:37 2013 +0200
@@ -34,4 +34,3 @@
 
     ThreadDimension dimension() default X;
 }
-
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Tue Oct 22 11:43:37 2013 +0200
@@ -143,45 +143,45 @@
             }
         } else {
             throw GraalInternalError.shouldNotReachHere();
-// SPARCAddress src = (SPARCAddress) tasm.asAddress(input);
-// switch (opcode) {
-// case IPOPCNT:
-// new Ldsw(src, tmp).emit(masm);
-// // clear upper word for 64 bit POPC
-// new Srl(tmp, g0, dst).emit(masm);
-// new Popc(tmp, dst).emit(masm);
-// break;
-// case LPOPCNT:
-// new Ldx(src, tmp).emit(masm);
-// new Popc(tmp, dst).emit(masm);
-// break;
-// case BSF:
-// assert input.getKind() == Kind.Int;
-// new Ldsw(src, tmp).emit(masm);
-// new Srl(tmp, 1, tmp).emit(masm);
-// new Srl(tmp, 0, dst).emit(masm);
-// new Or(tmp, tmp, dst).emit(masm);
-// new Srl(dst, 2, tmp).emit(masm);
-// new Or(dst, tmp, dst).emit(masm);
-// new Srl(dst, 4, tmp).emit(masm);
-// new Or(dst, tmp, dst).emit(masm);
-// new Srl(dst, 8, tmp).emit(masm);
-// new Or(dst, tmp, dst).emit(masm);
-// new Srl(dst, 16, tmp).emit(masm);
-// new Or(dst, tmp, dst).emit(masm);
-// new Popc(dst, dst).emit(masm);
-// new Mov(Kind.Int.getBitCount(), tmp).emit(masm);
-// new Sub(tmp, dst, dst).emit(masm);
-// break;
-// case IBSR:
-// // masm.bsrl(dst, src);
-// // countLeadingZerosI_bsr masm.bsrq(dst, src);
-// // masm.bsrl(dst, src);
-// case LBSR:
-// // masm.bsrq(dst, src);
-// default:
-// throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
-// }
+            // SPARCAddress src = (SPARCAddress) tasm.asAddress(input);
+            // switch (opcode) {
+            // case IPOPCNT:
+            // new Ldsw(src, tmp).emit(masm);
+            // // clear upper word for 64 bit POPC
+            // new Srl(tmp, g0, dst).emit(masm);
+            // new Popc(tmp, dst).emit(masm);
+            // break;
+            // case LPOPCNT:
+            // new Ldx(src, tmp).emit(masm);
+            // new Popc(tmp, dst).emit(masm);
+            // break;
+            // case BSF:
+            // assert input.getKind() == Kind.Int;
+            // new Ldsw(src, tmp).emit(masm);
+            // new Srl(tmp, 1, tmp).emit(masm);
+            // new Srl(tmp, 0, dst).emit(masm);
+            // new Or(tmp, tmp, dst).emit(masm);
+            // new Srl(dst, 2, tmp).emit(masm);
+            // new Or(dst, tmp, dst).emit(masm);
+            // new Srl(dst, 4, tmp).emit(masm);
+            // new Or(dst, tmp, dst).emit(masm);
+            // new Srl(dst, 8, tmp).emit(masm);
+            // new Or(dst, tmp, dst).emit(masm);
+            // new Srl(dst, 16, tmp).emit(masm);
+            // new Or(dst, tmp, dst).emit(masm);
+            // new Popc(dst, dst).emit(masm);
+            // new Mov(Kind.Int.getBitCount(), tmp).emit(masm);
+            // new Sub(tmp, dst, dst).emit(masm);
+            // break;
+            // case IBSR:
+            // // masm.bsrl(dst, src);
+            // // countLeadingZerosI_bsr masm.bsrq(dst, src);
+            // // masm.bsrl(dst, src);
+            // case LBSR:
+            // // masm.bsrq(dst, src);
+            // default:
+            // throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+            // }
         }
     }
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Oct 22 11:43:37 2013 +0200
@@ -446,8 +446,8 @@
         }
 
         // Load jump table entry into scratch and jump to it
-// masm.movslq(value, new AMD64Address(scratch, value, Scale.Times4, 0));
-// masm.addq(scratch, value);
+        // masm.movslq(value, new AMD64Address(scratch, value, Scale.Times4, 0));
+        // masm.addq(scratch, value);
         new Jmp(new SPARCAddress(scratch, 0)).emit(masm);
         new Nop().emit(masm);  // delay slot
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Oct 22 11:43:37 2013 +0200
@@ -213,7 +213,7 @@
     @Opcode("CAS")
     public static class CompareAndSwapOp extends SPARCLIRInstruction {
 
-// @Def protected AllocatableValue result;
+        // @Def protected AllocatableValue result;
         @Use protected AllocatableValue address;
         @Use protected AllocatableValue cmpValue;
         @Use protected AllocatableValue newValue;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Tue Oct 22 11:43:37 2013 +0200
@@ -107,8 +107,7 @@
 
         private static boolean verifyFlags(Field field, Class<?> type, EnumSet<OperandFlag> flags) {
             if (flags.contains(REG)) {
-                assert type.isAssignableFrom(REGISTER_VALUE_CLASS) ||
-                       type.isAssignableFrom(VARIABLE_CLASS) : "Cannot assign RegisterValue / Variable to field with REG flag:" + field;
+                assert type.isAssignableFrom(REGISTER_VALUE_CLASS) || type.isAssignableFrom(VARIABLE_CLASS) : "Cannot assign RegisterValue / Variable to field with REG flag:" + field;
             }
             if (flags.contains(STACK)) {
                 assert type.isAssignableFrom(STACK_SLOT_CLASS) : "Cannot assign StackSlot to field with STACK flag:" + field;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Tue Oct 22 11:43:37 2013 +0200
@@ -63,7 +63,8 @@
 
     private List<ExceptionInfo> exceptionInfoList;
 
-    public TargetMethodAssembler(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, CompilationResult compilationResult) {
+    public TargetMethodAssembler(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext,
+                    CompilationResult compilationResult) {
         this.target = codeCache.getTarget();
         this.codeCache = codeCache;
         this.foreignCalls = foreignCalls;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Oct 22 11:43:37 2013 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.VirtualState.VirtualClosure;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.virtual.*;
 
 public abstract class LoopFragment {
 
@@ -181,10 +182,16 @@
         final NodeBitMap notloopNodes = graph.createNodeBitMap(true);
         for (AbstractBeginNode b : blocks) {
             for (Node n : b.getBlockNodes()) {
+                if (n instanceof CommitAllocationNode) {
+                    for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
+                        markFloating(obj, nodes, notloopNodes);
+                    }
+                }
                 for (Node usage : n.usages()) {
                     markFloating(usage, nodes, notloopNodes);
                 }
             }
+
         }
 
         return nodes;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -25,9 +25,11 @@
 import com.oracle.graal.nodes.type.*;
 
 /**
- * Base class for {@link AbstractBeginNode}s that are associated with a frame state. TODO (dnsimon) this not
- * needed until {@link AbstractBeginNode} no longer implements {@link StateSplit} which is not possible
- * until loop peeling works without requiring begin nodes to have frames states
+ * Base class for {@link AbstractBeginNode}s that are associated with a frame state.
+ * 
+ * TODO (dnsimon) this not needed until {@link AbstractBeginNode} no longer implements
+ * {@link StateSplit} which is not possible until loop peeling works without requiring begin nodes
+ * to have frames states.
  */
 public abstract class BeginStateSplitNode extends AbstractBeginNode implements StateSplit {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ControlSplitNode} is a base class for all instructions that split the control flow
  * (ie. have more than one successor).
  */
-public abstract class ControlSplitNode extends FixedNode {
+public abstract class ControlSplitNode extends FixedNode implements IterableNodeType {
 
     public ControlSplitNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -33,6 +33,8 @@
     private final DeoptimizationReason reason;
 
     public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) {
+        assert action != null;
+        assert reason != null;
         this.action = action;
         this.reason = reason;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -23,9 +23,11 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.spi.*;
 
-public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable {
+public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Canonicalizable {
     @Input private ValueNode actionAndReason;
 
     public DynamicDeoptimizeNode(ValueNode actionAndReason) {
@@ -44,4 +46,15 @@
     public void generate(LIRGeneratorTool generator) {
         generator.emitDeoptimize(generator.operand(actionAndReason), this);
     }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        if (actionAndReason.isConstant()) {
+            Constant constant = actionAndReason.asConstant();
+            DeoptimizeNode newDeopt = graph().add(new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant)));
+            newDeopt.setDeoptimizationState(getDeoptimizationState());
+            return newDeopt;
+        }
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -358,9 +358,9 @@
                         if (trueValue.kind() != Kind.Int && trueValue.kind() != Kind.Long) {
                             return false;
                         }
-                        if (trueValue.isConstant() && falseValue.isConstant()) {
-                            ConditionalNode materialize = graph().unique(new ConditionalNode(condition(), trueValue, falseValue));
-                            graph().replaceFloating(singlePhi, materialize);
+                        ConditionalNode conditional = canonicalizeConditionalCascade(trueValue, falseValue);
+                        if (conditional != null) {
+                            graph().replaceFloating(singlePhi, conditional);
                             removeEmptyIf(tool);
                             return true;
                         }
@@ -371,6 +371,44 @@
         return false;
     }
 
+    private ConditionalNode canonicalizeConditionalCascade(ValueNode trueValue, ValueNode falseValue) {
+        if (trueValue.isConstant() && falseValue.isConstant()) {
+            return graph().unique(new ConditionalNode(condition(), trueValue, falseValue));
+        } else {
+            ConditionalNode conditional = null;
+            ValueNode constant = null;
+            boolean negateCondition;
+            if (trueValue instanceof ConditionalNode && falseValue.isConstant()) {
+                conditional = (ConditionalNode) trueValue;
+                constant = falseValue;
+                negateCondition = true;
+            } else if (falseValue instanceof ConditionalNode && trueValue.isConstant()) {
+                conditional = (ConditionalNode) falseValue;
+                constant = trueValue;
+                negateCondition = false;
+            } else {
+                return null;
+            }
+            boolean negateConditionalCondition;
+            ValueNode otherValue;
+            if (constant == conditional.x()) {
+                otherValue = conditional.y();
+                negateConditionalCondition = false;
+            } else if (constant == conditional.y()) {
+                otherValue = conditional.x();
+                negateConditionalCondition = true;
+            } else {
+                return null;
+            }
+            if (otherValue.isConstant()) {
+                double shortCutProbability = probability(trueSuccessor());
+                LogicNode newCondition = LogicNode.or(condition(), negateCondition, conditional.condition(), negateConditionalCondition, shortCutProbability);
+                return graph().unique(new ConditionalNode(newCondition, constant, otherValue));
+            }
+        }
+        return null;
+    }
+
     /**
      * Tries to connect code that initializes a variable directly with the successors of an if
      * construct that switches on the variable. For example, the pseudo code below:
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -32,7 +32,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}")
-public class InvokeWithExceptionNode extends ControlSplitNode implements IterableNodeType, Invoke, MemoryCheckpoint.Single, LIRLowerable {
+public class InvokeWithExceptionNode extends ControlSplitNode implements Invoke, MemoryCheckpoint.Single, LIRLowerable {
 
     private static final double EXCEPTION_PROBA = 1e-5;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -91,9 +91,7 @@
     @Override
     public boolean verify() {
         Node lla = lastLocationAccess();
-        if (lla != null && !(isMemoryCheckPoint(lla) || isMemoryPhi(lla) || isMemoryProxy(lla))) {
-            assert false : "lastLocationAccess of " + this + " should be a MemoryCheckpoint, but is " + lla;
-        }
+        assert lla == null || isMemoryCheckPoint(lla) || isMemoryPhi(lla) || isMemoryProxy(lla) : "lastLocationAccess of " + this + " should be a MemoryCheckpoint, but is " + lla;
         return super.verify();
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java	Tue Oct 22 11:43:37 2013 +0200
@@ -25,10 +25,32 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 
+/**
+ * A cache for graphs associated with {@linkplain StructuredGraph#method() methods}.
+ */
 public interface GraphCache {
 
-    void put(StructuredGraph graph, boolean hasMatureProfilingInfo);
+    /**
+     * Requests that a graph be added to this cache.
+     * 
+     * @param hasMatureProfilingInfo indicates that the caller has
+     *            {@linkplain ProfilingInfo#isMature() mature} profiling info for the method
+     *            associated with the graph
+     * @return true if {@code graph} was added to this cache, false otherwise
+     */
+    boolean put(StructuredGraph graph, boolean hasMatureProfilingInfo);
 
+    /**
+     * Gets the graph from this cache associated with a given method.
+     * 
+     * @param method a method for which a cached graph is requested
+     * @return the graph cached for {@code method} or null if it does not exist
+     */
     StructuredGraph get(ResolvedJavaMethod method);
 
+    /**
+     * The cache will remove graphs it considers stale. For example, graphs associated with
+     * installed code that has subsequently be deoptimized might be considered stale.
+     */
+    void removeStaleGraphs();
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Tue Oct 22 11:43:37 2013 +0200
@@ -296,39 +296,39 @@
                         graph.replaceFloating((FloatingNode) node, canonical);
                     }
                 } else {
-                    assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
-                    FixedWithNextNode fixedWithNext = (FixedWithNextNode) node;
-
+                    assert node instanceof FixedNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
+                    FixedNode fixed = (FixedNode) node;
                     if (canonical instanceof ControlSinkNode) {
                         // case 7
                         FixedWithNextNode pred = (FixedWithNextNode) node.predecessor();
-                        GraphUtil.killCFG(fixedWithNext);
+                        GraphUtil.killCFG(fixed);
                         pred.setNext((FixedNode) canonical);
                         return true;
-                    }
-
-                    // When removing a fixed node, new canonicalization
-                    // opportunities for its successor may arise
-                    assert fixedWithNext.next() != null;
-                    tool.addToWorkList(fixedWithNext.next());
-
-                    if (canonical == null) {
-                        // case 3
-                        graph.removeFixed(fixedWithNext);
-                    } else if (canonical instanceof FloatingNode) {
-                        // case 4
-                        graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical);
                     } else {
-                        assert canonical instanceof FixedNode;
-                        if (canonical.predecessor() == null) {
-                            assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
-                            // case 5
-                            graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical);
+                        assert fixed instanceof FixedWithNextNode;
+                        FixedWithNextNode fixedWithNext = (FixedWithNextNode) fixed;
+                        // When removing a fixed node, new canonicalization
+                        // opportunities for its successor may arise
+                        assert fixedWithNext.next() != null;
+                        tool.addToWorkList(fixedWithNext.next());
+                        if (canonical == null) {
+                            // case 3
+                            graph.removeFixed(fixedWithNext);
+                        } else if (canonical instanceof FloatingNode) {
+                            // case 4
+                            graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical);
                         } else {
-                            assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
-                            // case 6
-                            node.replaceAtUsages(canonical);
-                            graph.removeFixed(fixedWithNext);
+                            assert canonical instanceof FixedNode;
+                            if (canonical.predecessor() == null) {
+                                assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
+                                // case 5
+                                graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical);
+                            } else {
+                                assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
+                                // case 6
+                                node.replaceAtUsages(canonical);
+                                graph.removeFixed(fixedWithNext);
+                            }
                         }
                     }
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Oct 22 11:43:37 2013 +0200
@@ -318,44 +318,43 @@
                 ShortCircuitOrNode disjunction = (ShortCircuitOrNode) condition;
                 registerCondition(disjunction.isXNegated(), disjunction.getX(), anchor);
                 registerCondition(disjunction.isYNegated(), disjunction.getY(), anchor);
-            } else {
-                state.addCondition(isTrue, condition, anchor);
+            }
+            state.addCondition(isTrue, condition, anchor);
 
-                if (isTrue && condition instanceof InstanceOfNode) {
-                    InstanceOfNode instanceOf = (InstanceOfNode) condition;
-                    ValueNode object = instanceOf.object();
-                    state.addNullness(false, object);
-                    state.addType(instanceOf.type(), object);
-                } else if (condition instanceof IsNullNode) {
-                    IsNullNode nullCheck = (IsNullNode) condition;
-                    state.addNullness(isTrue, nullCheck.object());
-                } else if (condition instanceof ObjectEqualsNode) {
-                    ObjectEqualsNode equals = (ObjectEqualsNode) condition;
-                    ValueNode x = equals.x();
-                    ValueNode y = equals.y();
-                    if (isTrue) {
-                        if (state.isNull(x) && !state.isNull(y)) {
-                            metricObjectEqualsRegistered.increment();
-                            state.addNullness(true, y);
-                        } else if (!state.isNull(x) && state.isNull(y)) {
-                            metricObjectEqualsRegistered.increment();
-                            state.addNullness(true, x);
-                        }
-                        if (state.isNonNull(x) && !state.isNonNull(y)) {
-                            metricObjectEqualsRegistered.increment();
-                            state.addNullness(false, y);
-                        } else if (!state.isNonNull(x) && state.isNonNull(y)) {
-                            metricObjectEqualsRegistered.increment();
-                            state.addNullness(false, x);
-                        }
-                    } else {
-                        if (state.isNull(x) && !state.isNonNull(y)) {
-                            metricObjectEqualsRegistered.increment();
-                            state.addNullness(false, y);
-                        } else if (!state.isNonNull(x) && state.isNull(y)) {
-                            metricObjectEqualsRegistered.increment();
-                            state.addNullness(false, x);
-                        }
+            if (isTrue && condition instanceof InstanceOfNode) {
+                InstanceOfNode instanceOf = (InstanceOfNode) condition;
+                ValueNode object = instanceOf.object();
+                state.addNullness(false, object);
+                state.addType(instanceOf.type(), object);
+            } else if (condition instanceof IsNullNode) {
+                IsNullNode nullCheck = (IsNullNode) condition;
+                state.addNullness(isTrue, nullCheck.object());
+            } else if (condition instanceof ObjectEqualsNode) {
+                ObjectEqualsNode equals = (ObjectEqualsNode) condition;
+                ValueNode x = equals.x();
+                ValueNode y = equals.y();
+                if (isTrue) {
+                    if (state.isNull(x) && !state.isNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(true, y);
+                    } else if (!state.isNull(x) && state.isNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(true, x);
+                    }
+                    if (state.isNonNull(x) && !state.isNonNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(false, y);
+                    } else if (!state.isNonNull(x) && state.isNonNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(false, x);
+                    }
+                } else {
+                    if (state.isNull(x) && !state.isNonNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(false, y);
+                    } else if (!state.isNonNull(x) && state.isNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(false, x);
                     }
                 }
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java	Tue Oct 22 11:42:10 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common;
-
-import java.util.*;
-import java.util.Map.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
-import com.oracle.graal.phases.*;
-
-public class EliminatePartiallyRedundantGuardsPhase extends Phase {
-
-    private static final DebugMetric metricPRGuardsEliminatedAtMerge = Debug.metric("PRGuardsEliminatedAtMerge");
-    private static final DebugMetric metricPRGuardsEliminatedAtSplit = Debug.metric("PRGuardsEliminatedAtSplit");
-
-    private final boolean eliminateAtSplit;
-    private final boolean eliminateAtMerge;
-
-    public EliminatePartiallyRedundantGuardsPhase(boolean eliminateAtSplit, boolean eliminateAtMerge) {
-        assert eliminateAtMerge || eliminateAtSplit;
-        this.eliminateAtSplit = eliminateAtSplit;
-        this.eliminateAtMerge = eliminateAtMerge;
-    }
-
-    private static class Condition {
-
-        final LogicNode conditionNode;
-        final boolean negated;
-
-        public Condition(LogicNode conditionNode, boolean negated) {
-            this.conditionNode = conditionNode;
-            this.negated = negated;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((conditionNode == null) ? 0 : conditionNode.hashCode());
-            result = prime * result + (negated ? 1231 : 1237);
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            Condition other = (Condition) obj;
-            if (conditionNode == null) {
-                if (other.conditionNode != null) {
-                    return false;
-                }
-            } else if (!conditionNode.equals(other.conditionNode)) {
-                return false;
-            }
-            if (negated != other.negated) {
-                return false;
-            }
-            return true;
-        }
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        boolean hits;
-        do {
-            hits = false;
-            if (eliminateAtMerge) {
-                for (MergeNode merge : graph.getNodes(MergeNode.class)) {
-                    hits |= eliminateAtMerge(merge);
-                }
-            }
-            if (eliminateAtSplit) {
-                for (ControlSplitNode controlSplit : graph.getNodes().filter(ControlSplitNode.class)) {
-                    hits |= eliminateAtControlSplit(controlSplit);
-                }
-            }
-        } while (hits);
-    }
-
-    private static boolean eliminateAtMerge(MergeNode merge) {
-        if (merge.forwardEndCount() < 2) {
-            return false;
-        }
-        Collection<GuardNode> hits = new LinkedList<>();
-        for (GuardNode guard : merge.guards()) {
-            for (AbstractEndNode end : merge.forwardEnds()) {
-                AbstractBeginNode begin = AbstractBeginNode.prevBegin(end);
-                boolean found = false;
-                for (GuardNode predecessorGuard : begin.guards()) {
-                    if (guard.condition() == predecessorGuard.condition() && guard.negated() == predecessorGuard.negated()) {
-                        hits.add(guard);
-                        found = true;
-                        break;
-                    }
-                }
-                if (found) {
-                    break;
-                }
-            }
-        }
-        Graph graph = merge.graph();
-        for (GuardNode guard : hits) {
-            PhiNode phi = graph.addWithoutUnique(new PhiNode(PhiType.Guard, merge, null));
-            for (AbstractEndNode otherEnd : merge.forwardEnds()) {
-                phi.addInput(graph.unique(new GuardNode(guard.condition(), AbstractBeginNode.prevBegin(otherEnd), guard.reason(), guard.action(), guard.negated())));
-            }
-            guard.replaceAndDelete(phi);
-            metricPRGuardsEliminatedAtMerge.increment();
-        }
-        return !hits.isEmpty();
-    }
-
-    private static boolean eliminateAtControlSplit(ControlSplitNode controlSplit) {
-        Map<Condition, Collection<GuardNode>> conditionToGuard = new HashMap<>();
-        for (Node successor : controlSplit.successors()) {
-            AbstractBeginNode begin = (AbstractBeginNode) successor;
-            for (GuardNode guard : begin.guards()) {
-                Condition condition = new Condition(guard.condition(), guard.negated());
-                Collection<GuardNode> guards = conditionToGuard.get(condition);
-                if (guards == null) {
-                    guards = new LinkedList<>();
-                    conditionToGuard.put(condition, guards);
-                }
-                guards.add(guard);
-            }
-        }
-
-        boolean hits = false;
-        for (Entry<Condition, Collection<GuardNode>> entry : conditionToGuard.entrySet()) {
-            Collection<GuardNode> guards = entry.getValue();
-            if (guards.size() < 2) {
-                continue;
-            }
-            DeoptimizationReason reason = null;
-            DeoptimizationAction action = DeoptimizationAction.None;
-            Set<AbstractBeginNode> begins = new HashSet<>(3);
-            for (GuardNode guard : guards) {
-                AbstractBeginNode begin = (AbstractBeginNode) guard.getGuard();
-                begins.add(begin);
-                if (guard.action().ordinal() > action.ordinal()) {
-                    action = guard.action();
-                }
-                if (reason == null) {
-                    reason = guard.reason();
-                } else if (reason != guard.reason()) {
-                    reason = DeoptimizationReason.None;
-                }
-            }
-            if (begins.size() == controlSplit.successors().count()) {
-                hits = true;
-                Condition condition = entry.getKey();
-                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(condition.conditionNode, AbstractBeginNode.prevBegin(controlSplit), reason, action, condition.negated));
-                for (GuardNode guard : guards) {
-                    guard.replaceAndDelete(newGuard);
-                    metricPRGuardsEliminatedAtSplit.increment();
-                }
-            }
-        }
-        return hits;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java	Tue Oct 22 11:43:37 2013 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013, 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.common;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.phases.*;
+
+public class OptimizeGuardAnchors extends Phase {
+    private static final DebugMetric metricGuardsAnchorOptimized = Debug.metric("GuardsAnchorOptimized");
+    private static final DebugMetric metricGuardsOptimizedAtSplit = Debug.metric("GuardsOptimizedAtSplit");
+
+    private static class LazyCFG {
+        private ControlFlowGraph cfg;
+        private StructuredGraph graph;
+
+        public LazyCFG(StructuredGraph graph) {
+            this.graph = graph;
+        }
+
+        public ControlFlowGraph get() {
+            if (cfg == null) {
+                cfg = ControlFlowGraph.compute(graph, true, false, true, true);
+            }
+            return cfg;
+        }
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        LazyCFG cfg = new LazyCFG(graph);
+        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
+            if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) {
+                NodeIterable<GuardNode> guards = begin.guards();
+                if (guards.isNotEmpty()) {
+                    AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin);
+                    // newAnchor == begin is possible because postdominator computation assumes that
+                    // loops never end
+                    if (newAnchor != begin) {
+                        for (GuardNode guard : guards.snapshot()) {
+                            guard.setGuard(newAnchor);
+                        }
+                        metricGuardsAnchorOptimized.increment();
+                    }
+                }
+            }
+        }
+        for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) {
+            otpimizeAtControlSplit(controlSplit, cfg);
+        }
+    }
+
+    private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) {
+        Block anchor = cfg.blockFor(begin);
+        while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) {
+            anchor = anchor.getDominator();
+        }
+        return anchor.getBeginNode();
+    }
+
+    private static void otpimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) {
+        AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit);
+        int successorCount = controlSplit.successors().count();
+        List<GuardNode> otherGuards = new ArrayList<>(successorCount - 1);
+        for (GuardNode guard : successor.guards().snapshot()) {
+            if (guard.condition().usages().count() < successorCount) {
+                continue;
+            }
+
+            for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) {
+                if (conditonGuard != guard) {
+                    GuardingNode conditonGuardAnchor = conditonGuard.getGuard();
+                    if (conditonGuardAnchor.asNode().predecessor() == controlSplit && compatibleGuards(guard, conditonGuard)) {
+                        otherGuards.add(conditonGuard);
+                    }
+                }
+            }
+
+            if (otherGuards.size() == successorCount - 1) {
+                AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit));
+                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated()));
+                for (GuardNode otherGuard : otherGuards) {
+                    otherGuard.replaceAndDelete(newGuard);
+                }
+                guard.replaceAndDelete(newGuard);
+                metricGuardsOptimizedAtSplit.increment();
+            }
+            otherGuards.clear();
+        }
+    }
+
+    private static boolean compatibleGuards(GuardNode guard, GuardNode conditonGuard) {
+        return conditonGuard.negated() == guard.negated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason();
+    }
+
+    private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
+        NodeClassIterator successors = controlSplit.successors().iterator();
+        AbstractBeginNode min = (AbstractBeginNode) successors.next();
+        int minUsages = min.usages().count();
+        while (successors.hasNext()) {
+            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
+            int count = successor.usages().count();
+            if (count < minUsages) {
+                minUsages = count;
+                min = successor;
+            }
+        }
+        return min;
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Tue Oct 22 11:43:37 2013 +0200
@@ -32,7 +32,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -42,7 +41,7 @@
 
 public class BinaryGraphPrinter implements GraphPrinter {
 
-    private static final int CONSTANT_POOL_MAX_SIZE = 2000;
+    private static final int CONSTANT_POOL_MAX_SIZE = 8000;
 
     private static final int BEGIN_GROUP = 0x00;
     private static final int BEGIN_GRAPH = 0x01;
@@ -71,10 +70,10 @@
     private static final int KLASS = 0x00;
     private static final int ENUM_KLASS = 0x01;
 
-    private static final class ConstantPool extends LinkedHashMap<Object, Integer> {
+    private static final class ConstantPool extends LinkedHashMap<Object, Character> {
 
-        private final LinkedList<Integer> availableIds;
-        private int nextId;
+        private final LinkedList<Character> availableIds;
+        private char nextId;
         private static final long serialVersionUID = -2676889957907285681L;
 
         public ConstantPool() {
@@ -83,7 +82,7 @@
         }
 
         @Override
-        protected boolean removeEldestEntry(java.util.Map.Entry<Object, Integer> eldest) {
+        protected boolean removeEldestEntry(java.util.Map.Entry<Object, Character> eldest) {
             if (size() > CONSTANT_POOL_MAX_SIZE) {
                 availableIds.addFirst(eldest.getValue());
                 return true;
@@ -91,15 +90,15 @@
             return false;
         }
 
-        private Integer nextAvailableId() {
+        private Character nextAvailableId() {
             if (!availableIds.isEmpty()) {
                 return availableIds.removeFirst();
             }
             return nextId++;
         }
 
-        public int add(Object obj) {
-            Integer id = nextAvailableId();
+        public char add(Object obj) {
+            Character id = nextAvailableId();
             put(obj, id);
             return id;
         }
@@ -149,6 +148,7 @@
     }
 
     private void ensureAvailable(int i) throws IOException {
+        assert buffer.capacity() >= i : "Can not make " + i + " bytes available, buffer is too small";
         while (buffer.remaining() < i) {
             flush();
         }
@@ -186,10 +186,10 @@
 
     private void writeString(String str) throws IOException {
         writeInt(str.length());
-        ensureAvailable(str.length() * 2);
-        for (int i = 0; i < str.length(); i++) {
-            buffer.putChar(str.charAt(i));
-        }
+        int sizeInBytes = str.length() * 2;
+        ensureAvailable(sizeInBytes);
+        buffer.asCharBuffer().put(str);
+        buffer.position(buffer.position() + sizeInBytes);
     }
 
     private void writeBytes(byte[] b) throws IOException {
@@ -207,10 +207,10 @@
             writeInt(-1);
         } else {
             writeInt(b.length);
-            ensureAvailable(b.length * 4);
-            for (int i = 0; i < b.length; i++) {
-                buffer.putInt(b[i]);
-            }
+            int sizeInBytes = b.length * 4;
+            ensureAvailable(sizeInBytes);
+            buffer.asIntBuffer().put(b);
+            buffer.position(buffer.position() + sizeInBytes);
         }
     }
 
@@ -219,10 +219,10 @@
             writeInt(-1);
         } else {
             writeInt(b.length);
-            ensureAvailable(b.length * 8);
-            for (int i = 0; i < b.length; i++) {
-                buffer.putDouble(b[i]);
-            }
+            int sizeInBytes = b.length * 8;
+            ensureAvailable(sizeInBytes);
+            buffer.asDoubleBuffer().put(b);
+            buffer.position(buffer.position() + sizeInBytes);
         }
     }
 
@@ -231,7 +231,7 @@
             writeByte(POOL_NULL);
             return;
         }
-        Integer id = constantPool.get(object);
+        Character id = constantPool.get(object);
         if (id == null) {
             addPoolEntry(object);
         } else {
@@ -250,7 +250,7 @@
             } else {
                 writeByte(POOL_STRING);
             }
-            writeInt(id.intValue());
+            writeShort(id.charValue());
         }
     }
 
@@ -262,9 +262,9 @@
     }
 
     private void addPoolEntry(Object object) throws IOException {
-        int index = constantPool.add(object);
+        char index = constantPool.add(object);
         writeByte(POOL_NEW);
-        writeInt(index);
+        writeShort(index);
         if (object instanceof Class<?>) {
             Class<?> klass = (Class<?>) object;
             writeByte(POOL_CLASS);
@@ -293,14 +293,16 @@
             writeByte(POOL_NODE_CLASS);
             writeString(nodeClass.getJavaClass().getSimpleName());
             writeString(nodeClass.getNameTemplate());
-            List<Position> directInputPositions = nodeClass.getFirstLevelInputPositions();
+            Collection<Position> directInputPositions = nodeClass.getFirstLevelInputPositions();
             writeShort((char) directInputPositions.size());
             for (Position pos : directInputPositions) {
+                writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1);
                 writePoolObject(nodeClass.getName(pos));
             }
-            List<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions();
+            Collection<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions();
             writeShort((char) directSuccessorPositions.size());
             for (Position pos : directSuccessorPositions) {
+                writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1);
                 writePoolObject(nodeClass.getName(pos));
             }
         } else if (object instanceof ResolvedJavaMethod) {
@@ -411,25 +413,53 @@
                 writePoolObject(key);
                 writePropertyObject(entry.getValue());
             }
-            // successors
-            NodeClassIterable successors = node.successors();
-            writeShort((char) successors.count());
-            NodeClassIterator suxIt = successors.iterator();
-            while (suxIt.hasNext()) {
-                Position pos = suxIt.nextPosition();
-                Node sux = nodeClass.get(node, pos);
-                writeInt(sux.getId());
-                writeShort((char) pos.index);
+            // inputs
+            Collection<Position> directInputPositions = nodeClass.getFirstLevelInputPositions();
+            for (Position pos : directInputPositions) {
+                if (pos.subIndex == NodeClass.NOT_ITERABLE) {
+                    Node in = nodeClass.get(node, pos);
+                    if (in != null) {
+                        writeInt(in.getId());
+                    } else {
+                        writeInt(-1);
+                    }
+                } else {
+                    NodeList<?> list = nodeClass.getNodeList(node, pos);
+                    int listSize = list.count();
+                    assert listSize == ((char) listSize);
+                    writeShort((char) listSize);
+                    for (Node in : list) {
+                        if (in != null) {
+                            writeInt(in.getId());
+                        } else {
+                            writeInt(-1);
+                        }
+                    }
+                }
             }
-            // inputs
-            NodeClassIterable inputs = node.inputs();
-            writeShort((char) inputs.count());
-            NodeClassIterator inIt = inputs.iterator();
-            while (inIt.hasNext()) {
-                Position pos = inIt.nextPosition();
-                Node in = nodeClass.get(node, pos);
-                writeInt(in.getId());
-                writeShort((char) pos.index);
+            // successors
+            Collection<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions();
+            for (Position pos : directSuccessorPositions) {
+                if (pos.subIndex == NodeClass.NOT_ITERABLE) {
+                    Node sux = nodeClass.get(node, pos);
+                    if (sux != null) {
+                        writeInt(sux.getId());
+                    } else {
+                        writeInt(-1);
+                    }
+                } else {
+                    NodeList<?> list = nodeClass.getNodeList(node, pos);
+                    int listSize = list.count();
+                    assert listSize == ((char) listSize);
+                    writeShort((char) listSize);
+                    for (Node sux : list) {
+                        if (sux != null) {
+                            writeInt(sux.getId());
+                        } else {
+                            writeInt(-1);
+                        }
+                    }
+                }
             }
             props.clear();
         }
--- a/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java	Tue Oct 22 11:43:37 2013 +0200
@@ -35,10 +35,9 @@
  */
 public class PTX extends Architecture {
 
-    public static final RegisterCategory REG    = new RegisterCategory("REG");
-    public static final RegisterCategory SREG   = new RegisterCategory("SREG");
-    public static final RegisterCategory PARAM  = new RegisterCategory("PARAM");
-
+    public static final RegisterCategory REG = new RegisterCategory("REG");
+    public static final RegisterCategory SREG = new RegisterCategory("SREG");
+    public static final RegisterCategory PARAM = new RegisterCategory("PARAM");
 
     // @formatter:off
 
@@ -194,8 +193,7 @@
     // @formatter:on
 
     public PTX() {
-        super("PTX", 8, ByteOrder.LITTLE_ENDIAN, false, allRegisters,
-              LOAD_STORE | STORE_STORE, 0, r15.encoding + 1, 8);
+        super("PTX", 8, ByteOrder.LITTLE_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 0, r15.encoding + 1, 8);
     }
 
     @Override
@@ -232,5 +230,4 @@
         }
     }
 
-
 }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -51,8 +51,7 @@
                 StructuredGraph graph = parse(snippet);
                 PhasePlan phasePlan = getDefaultPhasePlan();
                 Assumptions assumptions = new Assumptions(true);
-                HighTierContext context = new HighTierContext(getProviders(), assumptions, null, phasePlan,
-                                OptimisticOptimizations.ALL);
+                HighTierContext context = new HighTierContext(getProviders(), assumptions, null, phasePlan, OptimisticOptimizations.ALL);
                 Debug.dump(graph, "Graph");
                 new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 Debug.dump(graph, "Graph");
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Oct 22 11:43:37 2013 +0200
@@ -71,6 +71,8 @@
         protected final ResolvedJavaMethod method;
         protected final boolean[] constantParameters;
         protected final boolean[] varargsParameters;
+        private final DebugMetric instantiationCounter;
+        private final DebugTimer instantiationTimer;
 
         /**
          * The parameter names, taken from the local variables table. Only used for assertion
@@ -80,7 +82,8 @@
 
         protected SnippetInfo(ResolvedJavaMethod method) {
             this.method = method;
-
+            instantiationCounter = Debug.metric("SnippetInstantiationCount[" + method.getName() + "]");
+            instantiationTimer = Debug.timer("SnippetInstantiationTime[" + method.getName() + "]");
             assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
             int count = method.getSignature().getParameterCount(false);
             constantParameters = new boolean[count];
@@ -316,6 +319,7 @@
     }
 
     private static final DebugTimer SnippetCreationAndSpecialization = Debug.timer("SnippetCreationAndSpecialization");
+    private static final DebugMetric SnippetSpecializations = Debug.metric("SnippetSpecializations");
 
     /**
      * Base class for snippet classes. It provides a cache for {@link SnippetTemplate}s.
@@ -355,6 +359,7 @@
         protected SnippetTemplate template(final Arguments args) {
             SnippetTemplate template = templates.get(args.cacheKey);
             if (template == null) {
+                SnippetSpecializations.increment();
                 try (TimerCloseable a = SnippetCreationAndSpecialization.start()) {
                     template = Debug.scope("SnippetSpecialization", args.info.method, new Callable<SnippetTemplate>() {
 
@@ -385,9 +390,6 @@
         return false;
     }
 
-    private final DebugMetric instantiationCounter;
-    private final DebugTimer instantiationTimer;
-
     /**
      * Creates a snippet template.
      */
@@ -580,9 +582,6 @@
         this.deoptNodes = curDeoptNodes;
         this.stampNodes = curStampNodes;
         this.returnNode = retNode;
-
-        this.instantiationCounter = Debug.metric("SnippetInstantiationCount[" + method.getName() + "]");
-        this.instantiationTimer = Debug.timer("SnippetInstantiationTime[" + method.getName() + "]");
     }
 
     private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, ConstantNode[] placeholders) {
@@ -865,8 +864,8 @@
      */
     public Map<Node, Node> instantiate(MetaAccessProvider metaAccess, FixedNode replacee, UsageReplacer replacer, Arguments args) {
         assert checkSnippetKills(replacee);
-        try (TimerCloseable a = instantiationTimer.start()) {
-            instantiationCounter.increment();
+        try (TimerCloseable a = args.info.instantiationTimer.start()) {
+            args.info.instantiationCounter.increment();
             // Inline the snippet nodes, replacing parameters with the given args in the process
             StartNode entryPointNode = snippet.start();
             FixedNode firstCFGNode = entryPointNode.next();
@@ -958,8 +957,8 @@
      */
     public void instantiate(MetaAccessProvider metaAccess, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) {
         assert checkSnippetKills(replacee);
-        try (TimerCloseable a = instantiationTimer.start()) {
-            instantiationCounter.increment();
+        try (TimerCloseable a = args.info.instantiationTimer.start()) {
+            args.info.instantiationCounter.increment();
 
             // Inline the snippet nodes, replacing parameters with the given args in the process
             String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.runtime/src/com/oracle/graal/runtime/RuntimeProvider.java	Tue Oct 22 11:43:37 2013 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009, 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.runtime;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * A runtime supporting a host backend as well, zero or more additional backends and an optional
+ * {@linkplain GraphCache graph cache}.
+ */
+public interface RuntimeProvider {
+
+    /**
+     * Gets the host backend.
+     */
+    Backend getHostBackend();
+
+    /**
+     * Gets the backend for a given architecture.
+     * 
+     * @param arch a specific architecture class
+     */
+    <T extends Architecture> Backend getBackend(Class<T> arch);
+
+    /**
+     * Gets the graph cache (if any) maintained by this runtime.
+     */
+    GraphCache getGraphCache();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java	Tue Oct 22 11:43:37 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.truffle.hotspot.amd64;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.amd64.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Subclass of {@link AMD64HotSpotBackend} that injects special code into
+ * {@link OptimizedCallTarget#call(PackedFrame, Arguments)} for making a tail-call to the entry
+ * point of the target callee.
+ */
+class AMD64HotSpotTruffleBackend extends AMD64HotSpotBackend {
+
+    private ResolvedJavaMethod optimizedCallTargetCall;
+
+    public AMD64HotSpotTruffleBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
+        super(runtime, providers);
+    }
+
+    private ResolvedJavaMethod getInstrumentedMethod() throws GraalInternalError {
+        if (optimizedCallTargetCall == null) {
+            try {
+                optimizedCallTargetCall = getProviders().getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("call", PackedFrame.class, Arguments.class));
+            } catch (NoSuchMethodException | SecurityException e) {
+                throw new GraalInternalError(e);
+            }
+        }
+        return optimizedCallTargetCall;
+    }
+
+    @Override
+    protected void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) {
+        super.emitCodePrefix(installedCodeOwner, tasm, asm, regConfig, config, verifiedStub);
+        if (getInstrumentedMethod().equals(installedCodeOwner)) {
+            // TODO emit tailcall code
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackendFactory.java	Tue Oct 22 11:43:37 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.truffle.hotspot.amd64;
+
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.amd64.*;
+import com.oracle.graal.hotspot.meta.*;
+
+/**
+ * Factory to create a Truffle-specialized AMD64 HotSpot backend.
+ */
+@ServiceProvider(HotSpotBackendFactory.class)
+public class AMD64HotSpotTruffleBackendFactory extends AMD64HotSpotBackendFactory {
+
+    @Override
+    protected AMD64HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
+        return new AMD64HotSpotTruffleBackend(runtime, providers);
+    }
+}
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.substitutions.*;
 import com.oracle.truffle.api.*;
 
@@ -36,7 +37,8 @@
 
     public ExactMathTest() {
         if (!substitutionsInstalled) {
-            Graal.getRequiredCapability(Replacements.class).registerSubstitutions(ExactMathSubstitutions.class);
+            Replacements replacements = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getReplacements();
+            replacements.registerSubstitutions(ExactMathSubstitutions.class);
             substitutionsInstalled = true;
         }
     }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -28,6 +28,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.*;
@@ -41,6 +42,7 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.printer.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.*;
 import com.oracle.graal.virtual.phases.ea.*;
 import com.oracle.truffle.api.*;
@@ -58,7 +60,7 @@
         Replacements truffleReplacements = ((GraalTruffleRuntime) Truffle.getRuntime()).getReplacements();
         Providers providers = getProviders().copyWith(truffleReplacements);
         TruffleCache truffleCache = new TruffleCache(providers, GraphBuilderConfiguration.getDefault(), TruffleCompilerImpl.Optimizations);
-        this.partialEvaluator = new PartialEvaluator(providers, truffleCache);
+        this.partialEvaluator = new PartialEvaluator(Graal.getRequiredCapability(RuntimeProvider.class), providers, truffleCache);
 
         DebugEnvironment.initialize(System.out);
     }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java	Tue Oct 22 11:43:37 2013 +0200
@@ -26,8 +26,8 @@
 
 import org.junit.*;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.*;
 import com.oracle.truffle.api.*;
 
@@ -35,7 +35,7 @@
 
     @Test
     public void testGraalCapabilities() {
-        assertNotNull(Graal.getRuntime().getCapability(MetaAccessProvider.class));
+        assertNotNull(Graal.getRuntime().getCapability(RuntimeProvider.class));
     }
 
     @Test
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Tue Oct 22 11:43:37 2013 +0200
@@ -31,17 +31,21 @@
     private int loopAndInvokeCounter;
     private long prevTimestamp;
 
-    private final int initialInvokeCounter;
     private final int compilationThreshold;
+    private final String name;
 
-    public CompilationPolicy(final int compilationThreshold, final int initialInvokeCounter) {
+    public CompilationPolicy(final int compilationThreshold, final int initialInvokeCounter, final String name) {
         this.invokeCounter = initialInvokeCounter;
         this.loopAndInvokeCounter = compilationThreshold;
         this.originalInvokeCounter = compilationThreshold;
-        this.prevTimestamp = System.currentTimeMillis();
+        this.prevTimestamp = System.nanoTime();
 
         this.compilationThreshold = compilationThreshold;
-        this.initialInvokeCounter = initialInvokeCounter;
+        this.name = name;
+    }
+
+    public String getName() {
+        return this.name;
     }
 
     public int getInvokeCounter() {
@@ -91,19 +95,23 @@
     public boolean compileOrInline() {
         if (invokeCounter <= 0 && loopAndInvokeCounter <= 0) {
             if (TruffleUseTimeForCompilationDecision.getValue()) {
-                long timestamp = System.currentTimeMillis();
-                if ((timestamp - prevTimestamp) < TruffleCompilationDecisionTime.getValue()) {
+                long timestamp = System.nanoTime();
+                long timespan = (timestamp - prevTimestamp);
+                if (timespan < (TruffleCompilationDecisionTime.getValue())) {
                     return true;
                 }
-                this.invokeCounter = initialInvokeCounter;
                 this.loopAndInvokeCounter = compilationThreshold;
                 this.originalInvokeCounter = compilationThreshold;
                 this.prevTimestamp = timestamp;
+                if (TruffleCompilationDecisionTimePrintFail.getValue()) {
+                    // Checkstyle: stop
+                    System.out.println(name + ": timespan  " + (timespan / 1000000) + " ms  larger than threshold");
+                    // Checkstyle: resume
+                }
             } else {
                 return true;
             }
         }
         return false;
     }
-
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Tue Oct 22 11:43:37 2013 +0200
@@ -46,7 +46,7 @@
     protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int invokeCounter, int compilationThreshold) {
         super(rootNode, descriptor);
         this.compiler = compiler;
-        this.compilationPolicy = new CompilationPolicy(compilationThreshold, invokeCounter);
+        this.compilationPolicy = new CompilationPolicy(compilationThreshold, invokeCounter, rootNode.toString());
         this.rootNode.setCallTarget(this);
 
         if (TruffleCallTargetProfiling.getValue()) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Oct 22 11:43:37 2013 +0200
@@ -36,8 +36,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
@@ -51,6 +49,7 @@
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.nodes.asserts.*;
 import com.oracle.graal.truffle.nodes.frame.*;
 import com.oracle.graal.truffle.nodes.frame.NewFrameNode.VirtualOnlyInstanceNode;
@@ -70,15 +69,15 @@
     private final CanonicalizerPhase canonicalizer;
     private final ResolvedJavaType[] skippedExceptionTypes;
     private Set<Constant> constantReceivers;
-    private final HotSpotGraphCache cache;
+    private final GraphCache cache;
     private final TruffleCache truffleCache;
 
-    public PartialEvaluator(Providers providers, TruffleCache truffleCache) {
+    public PartialEvaluator(RuntimeProvider runtime, Providers providers, TruffleCache truffleCache) {
         this.providers = providers;
         CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(providers.getMetaAccess(), providers.getConstantReflection());
         this.canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue(), customCanonicalizer);
         this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(providers.getMetaAccess());
-        this.cache = HotSpotGraalRuntime.runtime().getCache();
+        this.cache = runtime.getGraphCache();
         this.truffleCache = truffleCache;
 
         try {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Oct 22 11:43:37 2013 +0200
@@ -38,7 +38,6 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -47,6 +46,7 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.printer.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.nodes.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.*;
@@ -63,7 +63,7 @@
     private final PartialEvaluator partialEvaluator;
     private final Backend backend;
     private final ResolvedJavaType[] skippedExceptionTypes;
-    private final HotSpotGraalRuntime runtime;
+    private final RuntimeProvider runtime;
     private final TruffleCache truffleCache;
     private final ThreadPoolExecutor compileQueue;
 
@@ -73,11 +73,11 @@
                     OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints);
 
     public TruffleCompilerImpl() {
+        this.runtime = Graal.getRequiredCapability(RuntimeProvider.class);
+        this.backend = runtime.getHostBackend();
         Replacements truffleReplacements = ((GraalTruffleRuntime) Truffle.getRuntime()).getReplacements();
-        this.providers = GraalCompiler.getGraalProviders().copyWith(truffleReplacements);
-        this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
-        this.backend = Graal.getRequiredCapability(Backend.class);
-        this.runtime = HotSpotGraalRuntime.runtime();
+        this.providers = backend.getProviders().copyWith(truffleReplacements);
+        this.suites = backend.getSuites().createSuites();
         this.skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess());
 
         // Create compilation queue.
@@ -87,7 +87,7 @@
         config.setSkippedExceptionTypes(skippedExceptionTypes);
         this.truffleCache = new TruffleCache(providers, config, TruffleCompilerImpl.Optimizations);
 
-        this.partialEvaluator = new PartialEvaluator(providers, truffleCache);
+        this.partialEvaluator = new PartialEvaluator(runtime, providers, truffleCache);
 
         if (Debug.isEnabled()) {
             DebugEnvironment.initialize(System.out);
@@ -128,7 +128,10 @@
         final StructuredGraph graph;
         final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault();
         config.setSkippedExceptionTypes(skippedExceptionTypes);
-        runtime.evictDeoptedGraphs();
+        GraphCache graphCache = runtime.getGraphCache();
+        if (graphCache != null) {
+            graphCache.removeStaleGraphs();
+        }
 
         if (TraceTruffleInliningTree.getValue()) {
             printInlineTree(compilable.getRootNode());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Tue Oct 22 11:43:37 2013 +0200
@@ -72,6 +72,10 @@
     @Option(help = "")
     public static final OptionValue<Integer> TruffleCompilationDecisionTime = new OptionValue<>(100);
     @Option(help = "")
+    public static final OptionValue<Long> TruffleCompilationDecisionTime = new OptionValue<>(100 * 1000000L);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleCompilationDecisionTimePrintFail = new OptionValue<>(false);
+    @Option(help = "")
     public static final OptionValue<Boolean> TruffleBackgroundCompilation = new OptionValue<>(true);
 
     // tracing
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Tue Oct 22 11:43:37 2013 +0200
@@ -26,12 +26,13 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.*;
+import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.substitutions.*;
 
 /**
@@ -47,7 +48,7 @@
     }
 
     static Replacements makeInstance() {
-        Providers graalProviders = GraalCompiler.getGraalProviders();
+        Providers graalProviders = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders();
         Replacements truffleReplacements = new TruffleReplacements(graalProviders);
 
         truffleReplacements.registerSubstitutions(CompilerAssertsSubstitutions.class);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Tue Oct 22 11:43:37 2013 +0200
@@ -34,6 +34,7 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.graal.truffle.*;
 import com.oracle.graal.truffle.nodes.*;
 import com.oracle.truffle.api.*;
@@ -45,7 +46,7 @@
  */
 public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable {
 
-    static final ResolvedJavaType FRAME_TYPE = Graal.getRequiredCapability(MetaAccessProvider.class).lookupJavaType(FrameWithoutBoxing.class);
+    static final ResolvedJavaType FRAME_TYPE = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess().lookupJavaType(FrameWithoutBoxing.class);
 
     @Input private ValueNode descriptor;
     @Input private ValueNode caller;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Oct 22 11:43:37 2013 +0200
@@ -170,8 +170,8 @@
      * @param reason a description of the reason for the replacement
      * @return the new node
      */
-    @SuppressWarnings({"unchecked"})
     public final <T extends Node> T replace(T newNode, String reason) {
+        CompilerDirectives.transferToInterpreter();
         if (this.getParent() == null) {
             throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
         }
@@ -180,13 +180,40 @@
             newNode.assignSourceSection(sourceSection);
         }
         onReplace(newNode, reason);
-        return (T) this.getParent().replaceChild(this, newNode);
+        ((Node) newNode).parent = this.parent;
+        if (!NodeUtil.replaceChild(this.parent, this, newNode)) {
+            fixupTree();
+        }
+        return newNode;
     }
 
-    private <T extends Node> T replaceChild(T oldChild, T newChild) {
-        NodeUtil.replaceChild(this, oldChild, newChild);
-        adoptChild(newChild);
-        return newChild;
+    /**
+     * Rewrite has failed; the tree is likely inconsistent, so fix any stale parent references.
+     * 
+     * This is a rather expensive operation but rare to occur.
+     */
+    private void fixupTree() {
+        Node rootNode = NodeUtil.findParent(this, RootNode.class);
+        if (rootNode == null) {
+            throw new UnsupportedOperationException("Tree does not have a root node.");
+        }
+        int fixCount = rootNode.fixupChildren();
+        assert fixCount != 0 : "sanity check failed: missing @Child[ren] or adoptChild?";
+        // if nothing had to be fixed, rewrite failed due to node not being a proper child.
+    }
+
+    private int fixupChildren() {
+        int fixCount = 0;
+        for (Node child : getChildren()) {
+            if (child != null) {
+                if (child.parent != this) {
+                    child.parent = this;
+                    fixCount++;
+                }
+                fixCount += child.fixupChildren();
+            }
+        }
+        return fixCount;
     }
 
     /**
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Oct 22 11:43:37 2013 +0200
@@ -976,7 +976,7 @@
 
         private List<CodeExecutableElement> createImplicitChildrenAccessors() {
             NodeData node = getModel().getNode();
-// Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>();
+            // Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>();
             @SuppressWarnings("unchecked")
             List<Set<TypeData>> expectTypes = Arrays.<Set<TypeData>> asList(new Set[node.getGenericSpecialization().getParameters().size()]);
 
@@ -2688,8 +2688,8 @@
             final SpecializationData polymorphic = node.getGenericPolymorphicSpecialization();
 
             ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic));
-// ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached,
-// node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType());
+            // ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached,
+            // node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType());
 
             ExecutableTypeMethodParser parser = new ExecutableTypeMethodParser(getContext(), node);
             ExecutableTypeData execType = parser.parse(Arrays.asList(executeCached)).get(0);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Oct 22 11:43:37 2013 +0200
@@ -227,7 +227,7 @@
 
         List<TypeData> polymorphicSignature = new ArrayList<>();
         // TODO we should support more optimized for boxing
-// List<ActualParameter> updatePolymorphic = generic.getReturnTypeAndParameters();
+        // List<ActualParameter> updatePolymorphic = generic.getReturnTypeAndParameters();
         List<ActualParameter> updatePolymorphic = Arrays.asList();
         for (ActualParameter genericParameter : updatePolymorphic) {
             if (!genericParameter.getSpecification().isSignature()) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Tue Oct 22 11:43:37 2013 +0200
@@ -21,9 +21,10 @@
  * questions.
  */
 
- // The content of this file is automatically generated. DO NOT EDIT.
+// The content of this file is automatically generated. DO NOT EDIT.
 
 package com.oracle.truffle.sl.parser;
+
 import java.util.*;
 
 import com.oracle.truffle.sl.*;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Tue Oct 22 11:43:37 2013 +0200
@@ -21,7 +21,7 @@
  * questions.
  */
 
- // The content of this file is automatically generated. DO NOT EDIT.
+// The content of this file is automatically generated. DO NOT EDIT.
 
 package com.oracle.truffle.sl.parser;
 
--- a/hotspot/.project	Tue Oct 22 11:42:10 2013 +0200
+++ b/hotspot/.project	Tue Oct 22 11:43:37 2013 +0200
@@ -96,6 +96,11 @@
 			<locationURI>PARENT-1-PROJECT_LOC/src/cpu/x86/vm</locationURI>
 		</link>
 		<link>
+			<name>ptx</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/src/gpu/ptx/vm</locationURI>
+		</link>
+		<link>
 			<name>sparc</name>
 			<type>2</type>
 			<locationURI>PARENT-1-PROJECT_LOC/src/cpu/sparc/vm</locationURI>
@@ -121,6 +126,11 @@
 			<locationURI>PARENT-1-PROJECT_LOC/src/os_cpu/bsd_x86/vm</locationURI>
 		</link>
 		<link>
+			<name>bsd_ptx</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/src/os_gpu/bsd_ptx/vm</locationURI>
+		</link>
+		<link>
 			<name>windows</name>
 			<type>2</type>
 			<locationURI>PARENT-1-PROJECT_LOC/src/os/windows/vm</locationURI>
@@ -141,6 +151,11 @@
 			<locationURI>PARENT-1-PROJECT_LOC/src/os_cpu/linux_x86/vm</locationURI>
 		</link>
 		<link>
+			<name>linux_ptx</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/src/os_gpu/linux_ptx/vm</locationURI>
+		</link>
+		<link>
 			<name>linux_sparc</name>
 			<type>2</type>
 			<locationURI>PARENT-1-PROJECT_LOC/src/os_cpu/linux_sparc/vm</locationURI>
--- a/make/bsd/makefiles/gcc.make	Tue Oct 22 11:42:10 2013 +0200
+++ b/make/bsd/makefiles/gcc.make	Tue Oct 22 11:43:37 2013 +0200
@@ -313,6 +313,14 @@
     OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
     OPT_CFLAGS/unsafe.o += -O1
   endif
+  # Clang 5.0
+  ifeq ($(shell expr $(CC_VER_MAJOR) = 5 \& $(CC_VER_MINOR) = 0), 1)
+    OPT_CFLAGS/graalCompilerToVM.o += -O1
+    OPT_CFLAGS/unsafe.o += -O1
+    # Specific optimization level plus precompiled headers produces:
+    #     error: __OPTIMIZE_SIZE__ predefined macro was enabled in PCH file but is currently disabled
+    USE_PRECOMPILED_HEADER = 0
+  endif
 else
   # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
   ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
--- a/make/windows/makefiles/projectcreator.make	Tue Oct 22 11:42:10 2013 +0200
+++ b/make/windows/makefiles/projectcreator.make	Tue Oct 22 11:43:37 2013 +0200
@@ -193,7 +193,6 @@
 ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
  -define_compiler2 COMPILER2 \
  -define_compiler2 GRAAL \
- -define_compiler2 TIERED \
  -ignorePath_compiler2 graal/generated \
  -additionalFile_compiler2 $(Platform_arch_model).ad \
  -additionalFile_compiler2 ad_$(Platform_arch_model).cpp \
--- a/mx/commands.py	Tue Oct 22 11:42:10 2013 +0200
+++ b/mx/commands.py	Tue Oct 22 11:43:37 2013 +0200
@@ -989,8 +989,8 @@
     global _jacoco
     _jacoco = 'off'
 
-    t = Task('CleanAndBuildGraalVisualizer')
-    mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build'])
+    t = Task('CleanAndBuildIdealGraphVisualizer')
+    mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-q', 'clean', 'build'])
     tasks.append(t.stop())
 
     # Prevent Graal modifications from breaking the standard builds
--- a/mx/projects	Tue Oct 22 11:42:10 2013 +0200
+++ b/mx/projects	Tue Oct 22 11:43:37 2013 +0200
@@ -32,6 +32,7 @@
 com.oracle.graal.hotspot.amd64,\
 com.oracle.graal.hotspot.ptx,\
 com.oracle.graal.truffle,\
+com.oracle.graal.truffle.hotspot.amd64,\
 com.oracle.graal.hotspot.sparc,\
 com.oracle.graal.hotspot,\
 com.oracle.graal.hotspot.hsail
@@ -61,7 +62,7 @@
 # graal.api.meta.test
 project@com.oracle.graal.api.meta.test@subDir=graal
 project@com.oracle.graal.api.meta.test@sourceDirs=src
-project@com.oracle.graal.api.meta.test@dependencies=JUNIT,com.oracle.graal.api.meta,com.oracle.graal.api.runtime
+project@com.oracle.graal.api.meta.test@dependencies=JUNIT,com.oracle.graal.runtime,com.oracle.graal.java
 project@com.oracle.graal.api.meta.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.api.meta.test@javaCompliance=1.7
 project@com.oracle.graal.api.meta.test@workingSets=API,Graal,Test
@@ -117,7 +118,7 @@
 # graal.hotspot
 project@com.oracle.graal.hotspot@subDir=graal
 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@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,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@javaCompliance=1.7
@@ -414,6 +415,14 @@
 project@com.oracle.graal.compiler.sparc.test@javaCompliance=1.7
 project@com.oracle.graal.compiler.sparc.test@workingSets=Graal,SPARC,Test
 
+# graal.runtime
+project@com.oracle.graal.runtime@subDir=graal
+project@com.oracle.graal.runtime@sourceDirs=src
+project@com.oracle.graal.runtime@dependencies=com.oracle.graal.compiler
+project@com.oracle.graal.runtime@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.runtime@javaCompliance=1.7
+project@com.oracle.graal.runtime@workingSets=Graal
+
 # graal.bytecode
 project@com.oracle.graal.bytecode@subDir=graal
 project@com.oracle.graal.bytecode@sourceDirs=src
@@ -440,7 +449,7 @@
 # graal.java.decompiler.test
 project@com.oracle.graal.java.decompiler.test@subDir=graal
 project@com.oracle.graal.java.decompiler.test@sourceDirs=src
-project@com.oracle.graal.java.decompiler.test@dependencies=com.oracle.graal.printer
+project@com.oracle.graal.java.decompiler.test@dependencies=com.oracle.graal.printer,com.oracle.graal.runtime
 project@com.oracle.graal.java.decompiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.java.decompiler.test@javaCompliance=1.7
 project@com.oracle.graal.java.decompiler.test@workingSets=Graal,Test
@@ -464,7 +473,7 @@
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
 project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer,com.oracle.graal.runtime
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.test@javaCompliance=1.7
 project@com.oracle.graal.compiler.test@workingSets=Graal,Test
@@ -488,7 +497,7 @@
 # graal.asm.test
 project@com.oracle.graal.asm.test@subDir=graal
 project@com.oracle.graal.asm.test@sourceDirs=src
-project@com.oracle.graal.asm.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.test,com.oracle.graal.asm
+project@com.oracle.graal.asm.test@dependencies=com.oracle.graal.test,com.oracle.graal.runtime
 project@com.oracle.graal.asm.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.test@javaCompliance=1.7
 project@com.oracle.graal.asm.test@workingSets=Graal,Assembler,Test
@@ -628,7 +637,7 @@
 # graal.truffle
 project@com.oracle.graal.truffle@subDir=graal
 project@com.oracle.graal.truffle@sourceDirs=src
-project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.hotspot
+project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer
 project@com.oracle.graal.truffle@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.truffle@javaCompliance=1.7
 project@com.oracle.graal.truffle@workingSets=Graal,Truffle
@@ -641,4 +650,11 @@
 project@com.oracle.graal.truffle.test@javaCompliance=1.7
 project@com.oracle.graal.truffle.test@workingSets=Graal,Truffle,Test
 
-
+# graal.truffle.hotspot.amd64
+project@com.oracle.graal.truffle.hotspot.amd64@subDir=graal
+project@com.oracle.graal.truffle.hotspot.amd64@sourceDirs=src
+project@com.oracle.graal.truffle.hotspot.amd64@dependencies=com.oracle.graal.truffle,com.oracle.graal.hotspot.amd64
+project@com.oracle.graal.truffle.hotspot.amd64@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.truffle.hotspot.amd64@javaCompliance=1.7
+project@com.oracle.graal.truffle.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor
+project@com.oracle.graal.truffle.hotspot.amd64@workingSets=Graal,Truffle
--- a/mxtool/mx.py	Tue Oct 22 11:42:10 2013 +0200
+++ b/mxtool/mx.py	Tue Oct 22 11:43:37 2013 +0200
@@ -55,17 +55,18 @@
   commands.py
       Suite specific extensions to the commands available to mx.
 
-  includes
+  imports
       Other suites to be loaded. This is recursive. Each
-      line in an includes file is a path to a suite directory.
+      line in an imports file is the name of an imported suite.
+      The suite is located using a SuiteModel (cf searchpath)
 
   env
       A set of environment variable definitions. These override any
       existing environment variables. Common properties set here
       include JAVA_HOME and IGNORED_PROJECTS.
 
-The includes and env files are typically not put under version control
-as they usually contain local file-system paths.
+The env file is typically not put under version control
+as it usually contain local file-system paths.
 
 The projects file is like the pom.xml file from Maven except that
 it is a properties file (not XML). Each non-comment line
@@ -156,9 +157,13 @@
 _suites = dict()
 _annotationProcessors = None
 _mainSuite = None
+_src_suitemodel = None
+_dst_suitemodel = None
 _opts = None
 _java = None
 _check_global_structures = True  # can be set False to allow suites with duplicate definitions to load without aborting
+_warn = False
+_hg = None
 
 
 """
@@ -493,38 +498,291 @@
         deps.append(self)
         return deps
 
+class HgConfig:
+    """
+    Encapsulates access to Mercurial (hg)
+    """
+    def __init__(self):
+        self.missing = 'no hg executable found'
+        try:
+            subprocess.check_output(['hg'])
+            self.has_hg = True
+        except OSError:
+            self.has_hg = False
+            warn(self.missing)
+
+    def _check(self, abortOnFail=True):
+        if not self.has_hg:
+            if abortOnFail:
+                abort(self.missing)
+            else:
+                warn(self.missing)
+        return self.has_hg
+
+    def _tip(self, s, abortOnError=True):
+        if not self.has_hg:
+            return None
+        try:
+            version = subprocess.check_output(['hg', 'tip', '-R', s.dir, '--template', '{node}'])
+            if s.version is not None and s.version != version:
+                abort('version of suite ' + s.name +' has changed during run')
+            return version
+        except subprocess.CalledProcessError:
+            if abortOnError:
+                abort('failed to get tip revision id')
+            else:
+                return None
+
+    def _canpush(self, s, strict=True):
+        try:
+            output = subprocess.check_output(['hg', '-R', s.dir, 'status'])
+            # super strict
+            return output == ''
+        except subprocess.CalledProcessError:
+            return False
+
+    def _default_push(self, sdir):
+        with open(join(sdir, '.hg', 'hgrc')) as f:
+            for line in f:
+                line = line.rstrip()
+                if line.startswith('default = '):
+                    return line[len('default = '):]
+        return None
+
+class SuiteModel:
+    """
+    Defines how to locate a URL/path for a suite, including imported suites.
+    Conceptually a SuiteModel is defined by a primary suite URL/path and a
+    map from suite name to URL/path for imported suites.
+    Subclasses define a specfic implementation.
+    """
+    def __init__(self):
+        self.primaryDir = None
+        self.suitenamemap = {}
+
+    def _find_suite_dir(self, suitename):
+        """locates the URL/path for suitename or None if not found"""
+        abort('_find_suite_dir not implemented')
+
+    def _set_primary_dir(self, d):
+        """informs that d is the primary suite directory"""
+        self._primaryDir = d
+
+    def _importee_dir(self, importer_dir, suitename):
+        """returns the directory path for an import of suitename, given importer_dir"""
+        abort('_importee_dir not implemented')
+
+    def _nestedsuites_dirname(self):
+        """Returns the dirname that contains any nested suites if the model supports that"""
+        return None
+
+    def _mxDirName(self, name):
+        # temporary workaround until mx.graal exists
+        if name == 'graal':
+            return 'mx'
+        else:
+            return 'mx.' + name
+
+    def _search_dir(self, searchDir, mxDirName):
+        for dd in os.listdir(searchDir):
+            sd = _is_suite_dir(join(searchDir, dd), mxDirName)
+            if sd is not None:
+                return sd
+
+    def _create_suitenamemap(self, optionspec, suitemap):
+        """Three ways to specify a suite name mapping, in order of precedence:
+        1. Explicitly in optionspec.
+        2. In suitemap.
+        3. in MXSUITEMAP environment variable.
+        """
+        if optionspec != '':
+            spec = optionspec
+        elif suitemap is not None:
+            spec = suitemap
+        elif get_env('MXSUITEMAP') is not None:
+            spec = get_env('MXSUITEMAP')
+        else:
+            return
+        pairs = spec.split(',')
+        for pair in pairs:
+            mappair = pair.split('=')
+            self.suitenamemap[mappair[0]] = mappair[1]
+
+    @staticmethod
+    def _set_suitemodel(option, suitemap):
+        if option.startswith('sibling'):
+            return SiblingSuiteModel(os.getcwd(), option, suitemap)
+        elif option.startswith('nested'):
+            return NestedImportsSuiteModel(os.getcwd(), option, suitemap)
+        elif option.startswith('path'):
+            return PathSuiteModel(option[len('path:'):])
+        else:
+            abort('unknown suitemodel type: ' + option)
+
+    @staticmethod
+    def _parse_options():
+        # suite-specific args may match the known args so there is no way at this early stage
+        # to use ArgParser to handle the suite model global arguments, so we just do it manually.
+        def _get_argvalue(arg, args, i):
+            if i < len(args):
+                return args[i]
+            else:
+                abort('value expected with ' + arg)
+
+        args = sys.argv[1:]
+        src_suitemodel_arg = dst_suitemodel_arg = 'sibling'
+        suitemap_arg = None
+
+        i = 0
+        while i < len(args):
+            arg = args[i]
+            if arg == '--src-suitemodel':
+                src_suitemodel_arg = _get_argvalue(arg, args, i + 1)
+            elif arg == '--dst-suitemodel':
+                dst_suitemodel_arg = _get_argvalue(arg, args, i + 1)
+            elif arg == '--suitemap':
+                suitemap_arg = _get_argvalue(arg, args, i + 1)
+            elif arg == '-w':
+                # to get warnings on suite loading issues before command line is parsed
+                global _warn
+                _warn = True
+
+            i = i + 1
+
+        global _src_suitemodel
+        _src_suitemodel = SuiteModel._set_suitemodel(src_suitemodel_arg, suitemap_arg)
+        global _dst_suitemodel
+        _dst_suitemodel = SuiteModel._set_suitemodel(dst_suitemodel_arg, suitemap_arg)
+
+
+class SiblingSuiteModel(SuiteModel):
+    """All suites are siblings in the same parent directory, recorded as _suiteRootDir"""
+    def __init__(self, suiteRootDir, option, suitemap):
+        SuiteModel.__init__(self)
+        self._suiteRootDir = suiteRootDir
+        self._create_suitenamemap(option[len('sibling:'):], suitemap)
+
+    def _find_suite_dir(self, name):
+        return self._search_dir(self._suiteRootDir, self._mxDirName(name))
+
+    def _set_primary_dir(self, d):
+        SuiteModel._set_primary_dir(self, d)
+        self._suiteRootDir = dirname(d)
+
+    def _importee_dir(self, importer_dir, suitename):
+        if self.suitenamemap.has_key(suitename):
+            suitename = self.suitenamemap[suitename]
+        return join(dirname(importer_dir), suitename)
+
+class NestedImportsSuiteModel(SuiteModel):
+    """Imported suites are all siblings in an 'imported_suites' directory of the primary suite"""
+    def _imported_suites_dirname(self):
+        return "imported_suites"
+
+    def __init__(self, primaryDir, option, suitemap):
+        SuiteModel.__init__(self)
+        self._primaryDir = primaryDir
+        self._create_suitenamemap(option[len('nested:'):], suitemap)
+
+    def _find_suite_dir(self, name):
+        return self._search_dir(join(self._primaryDir, self._imported_suites_dirname()), self._mxDirName(name))
+
+    def _importee_dir(self, importer_dir, suitename):
+        if self.suitenamemap.has_key(suitename):
+            suitename = self.suitenamemap[suitename]
+        if basename(importer_dir) == basename(self._primaryDir):
+            # primary is importer
+            this_imported_suites_dirname = join(importer_dir, self._imported_suites_dirname())
+            if not exists(this_imported_suites_dirname):
+                os.mkdir(this_imported_suites_dirname)
+            return join(this_imported_suites_dirname, suitename)
+        else:
+            return join(dirname(importer_dir), suitename)
+
+    def _nestedsuites_dirname(self):
+        return self._imported_suites_dirname()
+
+class PathSuiteModel(SuiteModel):
+    """The most general model. Uses a map from suitename to URL/path provided by the user"""
+    def __init__(self, path):
+        SuiteModel.__init__(self)
+        paths = path.split(',')
+        self.suit_to_url = {}
+        for path in paths:
+            pair = path.split('=')
+            if len(pair) > 1:
+                suitename = pair[0]
+                suiteurl = pair[1]
+            else:
+                suitename = basename(pair[0])
+                suiteurl = pair[0]
+            self.suit_to_url[suitename] = suiteurl
+
+    def _find_suite_dir(self, suitename):
+        if self.suit_to_url.has_key(suitename):
+            return self.suit_to_url[suitename]
+        else:
+            return None
+
+    def _importee_dir(self, importer_dir, suitename):
+        if suitename in self.suit_to_url:
+            return self.suit_to_url[suitename]
+        else:
+            abort('suite ' + suitename + ' not found')
+
+class SuiteImport:
+    def __init__(self, name, version):
+        self.name = name
+        self.version = version
+
+    @staticmethod
+    def _parse_specification(specification):
+        pair = specification.split(',')
+        name = pair[0]
+        if len(pair) > 1:
+            version = pair[1]
+        else:
+            version = None
+        return SuiteImport(name, version)
+
+    @staticmethod
+    def _tostring(name, version):
+        return name + ',' + version
+
+    def __str__(self):
+        return self.name + ',' + self.version
+
 class Suite:
-    def __init__(self, d, mxDir, primary):
-        self.dir = d
+    def __init__(self, mxDir, primary, load=True):
+        self.dir = dirname(mxDir)
         self.mxDir = mxDir
         self.projects = []
         self.libs = []
         self.dists = []
-        self.includes = []
+        self.imports = []
         self.commands = None
         self.primary = primary
-        self._load_env(mxDir)
-        self._load_commands(mxDir)
-        self._load_includes(mxDir)
-        self.name = d  # re-initialized in _load_projects
+        self.name = _suitename(mxDir)  # validated in _load_projects
+        self.version = None  # _hg._tip checks current version if not None
+        self.version = _hg._tip(self, False)
+        if load:
+            # load suites bottom up to make sure command overriding works properly
+            self._load_imports()
+            self._load_env()
+            self._load_commands()
+        _suites[self.name] = self
 
     def __str__(self):
         return self.name
 
-    def _load_projects(self, mxDir):
+    def _load_projects(self):
         libsMap = dict()
         projsMap = dict()
         distsMap = dict()
-        projectsFile = join(mxDir, 'projects')
+        projectsFile = join(self.mxDir, 'projects')
         if not exists(projectsFile):
             return
 
-        def _find_suite_key():
-            for items in _suites.items():
-                if items[1].dir == self.dir:
-                    return items[0]
-            raise KeyError
-
         with open(projectsFile) as f:
             prefix = ''
             for line in f:
@@ -544,10 +802,7 @@
                         if parts[0] != 'suite':
                             abort('Single part property must be "suite": ' + key)
                         if self.name != value:
-                            currentKey = _find_suite_key()
-                            _suites.pop(currentKey)
-                            self.name = value
-                            _suites[value] = self
+                            abort('suite name in project file does not match ' + _suitename(self.mxDir))
                         continue
                     if len(parts) != 3:
                         abort('Property name does not have 3 parts separated by "@": ' + key)
@@ -616,38 +871,89 @@
         if self.name is None:
             abort('Missing "suite=<name>" in ' + projectsFile)
 
-    def _load_commands(self, mxDir):
-        commandsPath = join(mxDir, 'commands.py')
+    def _commands_name(self):
+        return 'mx_' + self.name
+
+    def _find_commands(self, name):
+        commandsPath = join(self.mxDir, name + '.py')
         if exists(commandsPath):
+            return name
+        else:
+            return None
+
+    def _load_commands(self):
+        commandsName = self._find_commands(self._commands_name())
+        if commandsName is None:
+            # backwards compatibility
+            commandsName = self._find_commands('commands')
+        if commandsName is not None:
+            if commandsName in sys.modules:
+                abort(commandsName + '.py in suite ' + self.name + ' duplicates ' + sys.modules[commandsName].__file__)
             # temporarily extend the Python path
-            sys.path.insert(0, mxDir)
-            mod = __import__('commands')
-
-            self.commands = sys.modules.pop('commands')
-            sys.modules[join(mxDir, 'commands')] = self.commands
+            sys.path.insert(0, self.mxDir)
+            mod = __import__(commandsName)
+
+            self.commands = sys.modules.pop(commandsName)
+            sys.modules[commandsName] = self.commands
 
             # revert the Python path
             del sys.path[0]
 
             if not hasattr(mod, 'mx_init'):
-                abort(commandsPath + ' must define an mx_init(env) function')
+                abort(commandsName + '.py in suite ' + self.name + ' must define an mx_init(suite) function')
             if hasattr(mod, 'mx_post_parse_cmd_line'):
                 self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line
 
             mod.mx_init(self)
             self.commands = mod
 
-    def _load_includes(self, mxDir):
-        includes = join(mxDir, 'includes')
-        if exists(includes):
-            with open(includes) as f:
+    def _visit_imports(self, visitor, **extra_args):
+        """
+        Visitor support for the imports file.
+        For each line of the imports file that specifies an import, the visitor function is
+        called with this suite, a SuiteImport instance created from the line and any extra args
+        passed to this call. In addition, if extra_args contains a key 'update_versions' that is True,
+        a StringIO value is added to extra_args with key 'updated_imports', and the visitor is responsible
+        for writing a (possibly) updated import line to the file, and the file is (possibly) updated after
+        all imports are processed.
+        N.B. There is no built-in support for avoiding visiting the same suite multiple times,
+        as this function only visits the imports of a singkle suite. If a (recursive) visitor function
+        wishes to visit a suite exactly once, it must manage that through extra_args.
+        """
+        importsFile = join(self.mxDir, 'imports')
+        if exists(importsFile):
+            update_versions = extra_args.has_key('update_versions') and extra_args['update_versions']
+            out = StringIO.StringIO() if update_versions else None
+            extra_args['updated_imports'] = out
+            with open(importsFile) as f:
                 for line in f:
-                    include = expandvars_in_property(line.strip())
-                    self.includes.append(include)
-                    _loadSuite(os.path.abspath(include), False)
-
-    def _load_env(self, mxDir):
-        e = join(mxDir, 'env')
+                    sline = line.strip()
+                    if len(sline) == 0 or sline.startswith('#'):
+                        if out is not None:
+                            out.write(sline + '\n')
+                        continue
+                    suite_import = SuiteImport._parse_specification(line.strip())
+                    visitor(self, suite_import, **extra_args)
+
+            if out is not None:
+                update_file(importsFile, out.getvalue())
+
+    @staticmethod
+    def _find_and_loadsuite(suite, suite_import, **extra_args):
+        """visitor for the initial suite load"""
+        importMxDir = _src_suitemodel._find_suite_dir(suite_import.name)
+        if importMxDir is None:
+            abort('import ' + suite_import.name + ' not found')
+        suite.imports.append(suite_import)
+        imported_suite = _loadSuite(importMxDir, False)
+        if imported_suite.version != suite.version:
+            warn('import version of ' + imported_suite.name +' does not match tip of ' + suite.version)
+
+    def _load_imports(self):
+        self._visit_imports(self._find_and_loadsuite)
+
+    def _load_env(self):
+        e = join(self.mxDir, 'env')
         if exists(e):
             with open(e) as f:
                 lineNum = 0
@@ -661,8 +967,8 @@
                         os.environ[key.strip()] = expandvars_in_property(value.strip())
 
     def _post_init(self, opts):
-        self._load_projects(self.mxDir)
-        # set the global data structures, checking for conflicts unless _global_structures is False
+        self._load_projects()
+        # set the global data structures, checking for conflicts unless _check_global_structures is False
         for p in self.projects:
             existing = _projects.get(p.name)
             if existing is not None and _check_global_structures:
@@ -680,7 +986,7 @@
             if existing is not None and _check_global_structures:
                 # allow redefinition, so use path from existing
                 # abort('cannot redefine distribution  ' + d.name)
-                print('WARNING: distribution ' + d.name + ' redefined')
+                warn('distribution ' + d.name + ' redefined')
                 d.path = existing.path
             _dists[d.name] = d
         if hasattr(self, 'mx_post_parse_cmd_line'):
@@ -777,28 +1083,16 @@
     else:
         abort('Unknown operating system ' + sys.platform)
 
-def _loadSuite(d, primary=False):
+def _loadSuite(mxDir, primary=False):
     """
-    Load a suite from the 'mx' or 'mx.bbb' subdirectory of d, where 'bbb' is basename of d
+    Load a suite from 'mxDir'.
     """
-    mxDefaultDir = join(d, 'mx')
-    name = os.path.basename(d)
-    mxTaggedDir = mxDefaultDir + '.' + name
-    mxDir = None
-    if exists(mxTaggedDir) and isdir(mxTaggedDir):
-        mxDir = mxTaggedDir
-    else:
-        if exists(mxDefaultDir) and isdir(mxDefaultDir):
-            mxDir = mxDefaultDir
-
-
-    if mxDir is None:
-        return None
-    if len([s for s in _suites.itervalues() if s.dir == d]) == 0:
-        s = Suite(d, mxDir, primary)
-        # N.B. this will be updated once the projects file has been read
-        _suites[name] = s
-        return s
+    for s in _suites.itervalues():
+        if s.mxDir == mxDir:
+            return s
+    # create the new suite
+    s = Suite(mxDir, primary)
+    return s
 
 def suites(opt_limit_to_suite=False):
     """
@@ -822,6 +1116,7 @@
         abort('suite named ' + name + ' not found')
     return s
 
+
 def projects_from_names(projectNames):
     """
     Get the list of projects corresponding to projectNames; all projects if None
@@ -1020,7 +1315,7 @@
         else:
             break
 
-    envPath = join(_mainSuite.dir, 'mx', 'env')
+    envPath = join(_mainSuite.mxDir, 'env')
     if ask_yes_no('Persist this setting by adding "JAVA_HOME=' + javaHome + '" to ' + envPath, 'y'):
         with open(envPath, 'a') as fp:
             print >> fp, 'JAVA_HOME=' + javaHome
@@ -1028,7 +1323,6 @@
     return javaHome
 
 class ArgParser(ArgumentParser):
-
     # Override parent to append the list of available commands
     def format_help(self):
         return ArgumentParser.format_help(self) + _format_commands()
@@ -1041,6 +1335,7 @@
 
         self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output')
         self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output')
+        self.add_argument('-w', action='store_true', dest='warn', help='enable warning messages')
         self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on <port> for a debugger', metavar='<port>')
         self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"')
         self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='<arg>')
@@ -1052,6 +1347,9 @@
         self.add_argument('--java-home', help='bootstrap JDK installation directory (must be JDK 6 or later)', metavar='<path>')
         self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
         self.add_argument('--suite', action='append', dest='specific_suites', help='limit command to given suite', default=[])
+        self.add_argument('--src-suitemodel', help='mechanism for locating imported suites', metavar='<arg>', default='sibling')
+        self.add_argument('--dst-suitemodel', help='mechanism for placing cloned/pushed suites', metavar='<arg>', default='sibling')
+        self.add_argument('--suitemap', help='explicit remapping of suite names', metavar='<args>')
         if get_os() != 'windows':
             # Time outs are (currently) implemented with Unix specific functionality
             self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='<secs>')
@@ -1606,7 +1904,7 @@
 
     javaCompliance = java().javaCompliance
 
-    defaultEcjPath = join(_mainSuite.dir, 'mx', 'ecj.jar')
+    defaultEcjPath = join(_mainSuite.mxDir, 'ecj.jar')
 
     parser = parser if parser is not None else ArgumentParser(prog='mx build')
     parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)')
@@ -1803,7 +2101,7 @@
 
 
                 jdtProperties = join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs')
-                rootJdtProperties = join(p.suite.dir, 'mx', 'eclipse-settings', 'org.eclipse.jdt.core.prefs')
+                rootJdtProperties = join(p.suite.mxDir, 'eclipse-settings', 'org.eclipse.jdt.core.prefs')
                 if not exists(jdtProperties) or os.path.getmtime(jdtProperties) < os.path.getmtime(rootJdtProperties):
                     # Try to fix a missing properties file by running eclipseinit
                     eclipseinit([], buildProcessorJars=False)
@@ -2122,7 +2420,7 @@
     The exit code of this command reflects how many files were updated."""
 
     changedFiles = 0
-    for s in suites():
+    for s in suites(True):
         projectsFile = join(s.mxDir, 'projects')
         if not exists(projectsFile):
             continue
@@ -2682,8 +2980,7 @@
 
         if _isAnnotationProcessorDependency(p):
             _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh=False, async=False, xmlIndent='', xmlStandalone='no')
-            # Refresh.launch seems to cause occasional build looping in Eclipse
-            # _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh=True, async=True)
+            _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh=True, async=True)
 
         if projToDist.has_key(p.name):
             dist, distDeps = projToDist[p.name]
@@ -2763,12 +3060,20 @@
     launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn})
     launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'})
 
-    baseDir = dirname(dirname(os.path.abspath(__file__)))
+    # expect to find the OS command to invoke mx in the same directory
+    baseDir = dirname(os.path.abspath(__file__))
 
     cmd = 'mx.sh'
     if get_os() == 'windows':
         cmd = 'mx.cmd'
-    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': join(baseDir, cmd) })
+    cmdPath = join(baseDir, cmd)
+    if not os.path.exists(cmdPath):
+        # backwards compatibility for when the commands lived in parent of mxtool
+        cmdPath = join(dirname(baseDir), cmd)
+        if not os.path.exists(cmdPath):
+            abort('cannot locate ' + cmd)
+
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value':  cmdPath})
     launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS', 'value': 'auto,full,incremental'})
     launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS', 'value': mxCommand})
     launchOut.element('booleanAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED', 'value': 'true'})
@@ -3210,18 +3515,24 @@
     """find directories corresponding to deleted Java projects and delete them"""
     for suite in suites(True):
         projectDirs = [p.dir for p in suite.projects]
-        for root, dirnames, files in os.walk(suite.dir):
-            currentDir = join(suite.dir, root)
-            if currentDir in projectDirs:
-                # don't traverse subdirs of an existing project
+        for dirpath, dirnames, files in os.walk(suite.dir):
+            if dirpath == suite.dir:
+                # no point in traversing .hg
+                if '.hg' in dirnames:
+                    dirnames.remove('.hg')
+                # if there are nested suites must not scan those now, as they are not in projectDirs
+                if _src_suitemodel._nestedsuites_dirname() in dirnames:
+                    dirnames.remove(_src_suitemodel._nestedsuites_dirname())
+            elif dirpath in projectDirs:
+                # don't traverse subdirs of an existing project in this suite
                 dirnames[:] = []
             else:
                 projectConfigFiles = frozenset(['.classpath', 'nbproject'])
                 indicators = projectConfigFiles.intersection(files)
                 if len(indicators) != 0:
-                    if not sys.stdout.isatty() or ask_yes_no(currentDir + ' looks like a removed project -- delete it', 'n'):
-                        shutil.rmtree(currentDir)
-                        log('Deleted ' + currentDir)
+                    if not sys.stdout.isatty() or ask_yes_no(dirpath + ' looks like a removed project -- delete it', 'n'):
+                        shutil.rmtree(dirpath)
+                        log('Deleted ' + dirpath)
 
 def javadoc(args, parser=None, docDir='javadoc', includeDeps=True, stdDoclet=True):
     """generate javadoc for some/all Java projects"""
@@ -3625,9 +3936,270 @@
         if exists(tmpbase):
             shutil.rmtree(tmpbase)
 
+def _kwArg(kwargs):
+    if len(kwargs) > 0:
+        return kwargs.pop(0)
+    return None
+
+def sclone(args):
+    """clone a suite repository, and its imported suites"""
+    _hg._check(True)
+    parser = ArgumentParser(prog='mx sclone')
+    parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>')
+    parser.add_argument('--dest', help='destination directory (default basename of source)', metavar='<path>')
+    parser.add_argument("--no-imports", action='store_true', help='do not clone imported suites')
+    parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...')
+    args = parser.parse_args(args)
+    # check for non keyword args
+    if args.source is None:
+        args.source = _kwArg(args.nonKWArgs)
+    if args.dest is None:
+        args.dest = _kwArg(args.nonKWArgs)
+    if len(args.nonKWArgs) > 0:
+        abort('unrecognized args: ' + ' '.join(args.nonKWArgs))
+
+    if args.source is None:
+        # must be primary suite and dest is required
+        if _mainSuite is None:
+            abort('--source missing and no primary suite found')
+        if args.dest is None:
+            abort('--dest required when --source is not given')
+        source = _mainSuite.dir
+    else:
+        source = args.source
+
+    if args.dest is not None:
+        dest = args.dest
+    else:
+        dest = basename(source)
+
+    dest = os.path.abspath(dest)
+    # We can now set the primary dir for the src/dst suitemodel
+    _dst_suitemodel._set_primary_dir(dest)
+    _src_suitemodel._set_primary_dir(source)
+
+    _sclone(source, dest, None, args.no_imports)
+
+def _sclone(source, dest, version, no_imports):
+    cmd = ['hg', 'clone']
+    if version is not None:
+        cmd.append('-r')
+        cmd.append(version)
+    cmd.append(source)
+    cmd.append(dest)
+
+    run(cmd)
+
+    mxDir = _is_suite_dir(dest)
+    if mxDir is None:
+        warn(source + ' is not an mx suite')
+        return None
+
+    # create a Suite (without loading) to enable imports visitor
+    s = Suite(mxDir, False, load=False)
+    if not no_imports:
+        s._visit_imports(_scloneimports_visitor, source=source)
+    return s
+
+def _scloneimports_visitor(s, suite_import, source, **extra_args):
+    """
+    cloneimports visitor for Suite._visit_imports.
+    The destination information is encapsulated by 's'
+    """
+    _scloneimports(s, suite_import, source)
+
+def _scloneimports_suitehelper(sdir):
+    mxDir = _is_suite_dir(sdir)
+    if mxDir is None:
+        abort(sdir + ' is not an mx suite')
+    else:
+        # create a Suite (without loading) to enable imports visitor
+        return Suite(mxDir, False, load=False)
+
+def _scloneimports(s, suite_import, source):
+    # clone first, then visit imports once we can locate them
+    importee_source = _src_suitemodel._importee_dir(source, suite_import.name)
+    importee_dest = _dst_suitemodel._importee_dir(s.dir, suite_import.name)
+    if exists(importee_dest):
+        importee_suite = _scloneimports_suitehelper(importee_dest)
+        importee_suite._visit_imports(_scloneimports_visitor, source=importee_source)
+    else:
+        _sclone(importee_source, importee_dest, suite_import.version, False)
+        # _clone handles the recursive visit of the new imports
+
+def scloneimports(args):
+    """clone the imports of an existing suite"""
+    _hg._check(True)
+    parser = ArgumentParser(prog='mx scloneimports')
+    parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>')
+    parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...')
+    args = parser.parse_args(args)
+    # check for non keyword args
+    if args.source is None:
+        args.source = _kwArg(args.nonKWArgs)
+
+    if not os.path.isdir(args.source):
+        abort(args.source + ' is not a directory')
+
+    s = _scloneimports_suitehelper(args.source)
+
+    default_path = _hg._default_push(args.source)
+
+    if default_path is None:
+        abort('no default path in ' + join(args.source, '.hg', 'hgrc'))
+
+    # We can now set the primary dir for the dst suitemodel
+    # N.B. source is effectively the destination and the default_path is the (original) source
+    _dst_suitemodel._set_primary_dir(args.source)
+
+    s._visit_imports(_scloneimports_visitor, source=default_path)
+
+def _spush_import_visitor(s, suite_import, dest, checks, clonemissing, **extra_args):
+    """push visitor for Suite._visit_imports"""
+    if dest is not None:
+        dest = _dst_suitemodel._importee_dir(dest, suite_import.name)
+    _spush(suite(suite_import.name), suite_import, dest, checks, clonemissing)
+
+def _spush_check_import_visitor(s, suite_import, **extra_args):
+    """push check visitor for Suite._visit_imports"""
+    currentTip = _hg._tip(suite(suite_import.name))
+    if currentTip != suite_import.version:
+        abort('import version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip')
+
+def _spush(s, suite_import, dest, checks, clonemissing):
+    if checks:
+        if not _hg._canpush(s):
+            abort('working directory ' + s.dir + ' contains uncommitted changes, push aborted')
+
+    # check imports first
+    if checks:
+        s._visit_imports(_spush_check_import_visitor)
+
+    # ok, push imports
+    s._visit_imports(_spush_import_visitor, dest=dest, checks=checks, clonemissing=clonemissing)
+
+    dest_exists = True
+
+    if clonemissing:
+        if not os.path.exists(dest):
+            dest_exists = False
+
+    def add_version(cmd, suite_import):
+        if suite_import is not None and suite_import.version is not None:
+            cmd.append('-r')
+            cmd.append(suite_import.version)
+
+    if dest_exists:
+        cmd = ['hg', '-R', s.dir, 'push']
+        add_version(cmd, suite_import)
+        if dest is not None:
+            cmd.append(dest)
+        rc = run(cmd, nonZeroIsFatal=False)
+        if rc != 0:
+            # rc of 1 not an error,  means no changes
+            if rc != 1:
+                abort("push failed, exit code " + str(rc))
+    else:
+        cmd = ['hg', 'clone']
+        add_version(cmd, suite_import)
+        cmd.append(s.dir)
+        cmd.append(dest)
+        run(cmd)
+
+def spush(args):
+    """push primary suite and all its imports"""
+    _hg._check(True)
+    parser = ArgumentParser(prog='mx spush')
+    parser.add_argument('--dest', help='url/path of repo to push to (default as per hg push)', metavar='<path>')
+    parser.add_argument('--no-checks', action='store_true', help='checks on status, versions are disabled')
+    parser.add_argument('--clonemissing', action='store_true', help='clone missing imported repos at destination (forces --no-checks)')
+    parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...')
+    args = parser.parse_args(args)
+    if args.dest is None:
+        args.dest = _kwArg(args.nonKWArgs)
+    if len(args.nonKWArgs) > 0:
+        abort('unrecognized args: ' + ' '.join(args.nonKWArgs))
+
+    if args.dest is not None and not os.path.isdir(args.dest):
+        abort('destination must be a directory')
+
+    s = _check_primary_suite()
+
+    if args.clonemissing:
+        if args.dest is None:
+            abort('--dest required with --clonemissing')
+        args.nochecks = True
+
+    if args.dest is not None:
+        _dst_suitemodel._set_primary_dir(args.dest)
+
+    _spush(s, None, args.dest, not args.no_checks, args.clonemissing)
+
+def _supdate_import_visitor(s, suite_import, **extra_args):
+    _supdate(suite(suite_import.name), suite_import)
+
+def _supdate(s, suite_import):
+    s._visit_imports(_supdate_import_visitor)
+
+    run(['hg', '-R', s.dir, 'update'])
+
+def supdate(args):
+    """update primary suite and all its imports"""
+
+    _hg._check(True)
+    s = _check_primary_suite()
+
+    _supdate(s, None)
+
+def _scheck_imports_visitor(s, suite_import, update_versions, updated_imports):
+    """checkimportversions visitor for Suite._visit_imports"""
+    _scheck_imports(suite(suite_import.name), suite_import, update_versions, updated_imports)
+
+def _scheck_imports(s, suite_import, update_versions, updated_imports):
+    # check imports recursively
+    s._visit_imports(_scheck_imports_visitor, update_versions=update_versions)
+
+    currentTip = _hg._tip(s)
+    if currentTip != suite_import.version:
+        print('import version of ' + s.name + ' does not match tip' + (': updating' if update_versions else ''))
+
+    if update_versions:
+        suite_import.version = currentTip
+        line = str(suite_import)
+        updated_imports.write(line + '\n')
+
+def scheckimports(args):
+    """check that suite import versions are up to date"""
+    parser = ArgumentParser(prog='mx scheckimports')
+    parser.add_argument('--update-versions', help='update imported version ids', action='store_true')
+    args = parser.parse_args(args)
+    _check_primary_suite()._visit_imports(_scheck_imports_visitor, update_versions=args.update_versions)
+
+def _spull_import_visitor(s, suite_import, update_versions, updated_imports):
+    """pull visitor for Suite._visit_imports"""
+    _spull(suite(suite_import.name), update_versions, updated_imports)
+
+def _spull(s, update_versions, updated_imports):
+    _hg._check(True)
+    # pull imports first
+    s._visit_imports(_spull_import_visitor, update_versions=update_versions)
+
+    run(['hg', '-R', s.dir, 'pull', '-u'])
+    if update_versions and updated_imports is not None:
+        tip = _hg._tip(s)
+        updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n')
+
+def spull(args):
+    """pull primary suite and all its imports"""
+    _hg._check(True)
+    parser = ArgumentParser(prog='mx spull')
+    parser.add_argument('--update-versions', action='store_true', help='update version ids of imported suites')
+    args = parser.parse_args(args)
+
+    _spull(_check_primary_suite(), args.update_versions, None)
+
 def findclass(args, logToConsole=True):
     """find all classes matching a given substring"""
-
     matches = []
     for entry, filename in classpath_walk(includeBootClasspath=True):
         if filename.endswith('.class'):
@@ -3734,17 +4306,19 @@
 
 def update_commands(suite, new_commands):
     for key, value in new_commands.iteritems():
-        if _commands.has_key(key) and not suite.primary:
-            pass
-            # print("WARNING: attempt to redefine command '" + key + "' in suite " + suite.dir)
-        else:
-            _commands[key] = value
+        if _commands.has_key(key):
+            warn("redefining command '" + key + "' in suite " + suite.name)
+        _commands[key] = value
+
+def warn(msg):
+    if _warn:
+        print('WARNING: ' + msg)
 
 # Table of commands in alphabetical order.
 # Keys are command names, value are lists: [<function>, <usage msg>, <format args to doc string of function>...]
 # If any of the format args are instances of Callable, then they are called with an 'env' are before being
 # used in the call to str.format().
-# Extensions should update this table directly
+# Suite extensions should not update this table directly, but use update_commands
 _commands = {
     'about': [about, ''],
     'build': [build, '[options]'],
@@ -3760,6 +4334,12 @@
     'ideinit': [ideinit, ''],
     'archive': [archive, '[options]'],
     'projectgraph': [projectgraph, ''],
+    'sclone': [sclone, '[options]'],
+    'scheckimports': [scheckimports, ''],
+    'scloneimports': [scloneimports, '[options]'],
+    'spull': [spull, '[options'],
+    'spush': [spush, '[options'],
+    'supdate': [supdate, ''],
     'pylint': [pylint, ''],
     'javap': [javap, '<class name patterns>'],
     'javadoc': [javadoc, '[options]'],
@@ -3770,36 +4350,71 @@
 
 _argParser = ArgParser()
 
-def _findPrimarySuite():
-    def is_suite_dir(d):
+def _suitename(mxDir):
+    base = os.path.basename(mxDir)
+    parts = base.split('.')
+    # temporary workaround until mx.graal exists
+    if len(parts) == 1:
+        return 'graal'
+    else:
+        return parts[1]
+
+def _is_suite_dir(d, mxDirName=None):
+    """
+    Checks if d contains a suite.
+    If mxDirName is None, matches any suite name, otherwise checks for exactly that suite.
+    """
+    if os.path.isdir(d):
         for f in os.listdir(d):
-            if f == 'mx' or fnmatch.fnmatch(f, 'mx.*'):
+            if (mxDirName == None and (f == 'mx' or fnmatch.fnmatch(f, 'mx.*'))) or f == mxDirName:
                 mxDir = join(d, f)
                 if exists(mxDir) and isdir(mxDir) and exists(join(mxDir, 'projects')):
-                    return dirname(mxDir)
-
-
-    # try current working directory first
-    if is_suite_dir(os.getcwd()):
-        return os.getcwd()
-
-    # now search path of my executable
-    me = sys.argv[0]
-    parent = dirname(me)
-    while parent:
-        if is_suite_dir(parent):
-            return parent
-        parent = dirname(parent)
+                    return mxDir
+
+def _check_primary_suite():
+    if _mainSuite is None:
+        abort('no primary suite found')
+    else:
+        return _mainSuite
+
+def _needs_primary_suite(command):
+    return not command.startswith("sclone")
+
+def _findPrimarySuiteMxDir():
+    # try current working directory first, the look up the tree
+    curdir = os.getcwd()
+    while curdir:
+        mxDir = _is_suite_dir(curdir)
+        if mxDir is not None:
+            return mxDir
+        parent = dirname(curdir)
+        if curdir == parent:
+            return None
+        curdir = parent
+
     return None
 
 def main():
-    primarySuiteDir = _findPrimarySuite()
-    if primarySuiteDir:
+    SuiteModel._parse_options()
+
+    global _hg
+    _hg = HgConfig()
+
+    primarySuiteMxDir = _findPrimarySuiteMxDir()
+    if primarySuiteMxDir:
+        _src_suitemodel._set_primary_dir(dirname(primarySuiteMxDir))
         global _mainSuite
-        _mainSuite = _loadSuite(primarySuiteDir, True)
+        _mainSuite = _loadSuite(primarySuiteMxDir, True)
 
     opts, commandAndArgs = _argParser._parse_cmd_line()
 
+    if primarySuiteMxDir is None:
+        msg = 'no primary suite found'
+        if len(commandAndArgs) > 0 and _needs_primary_suite(commandAndArgs[0]):
+            abort(msg)
+        else:
+            warn(msg)
+
     global _opts, _java
     _opts = opts
     _java = JavaConfig(opts)
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Tue Oct 22 11:42:10 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Tue Oct 22 11:43:37 2013 +0200
@@ -201,12 +201,21 @@
         }
     }
     
+    private static class Port {
+        public final boolean isList;
+        public final String name;
+        private Port(boolean isList, String name) {
+            this.isList = isList;
+            this.name = name;
+        }
+    }
+    
     private static class NodeClass {
         public final String className;
         public final String nameTemplate;
-        public final List<String> inputs;
-        public final List<String> sux;
-        private NodeClass(String className, String nameTemplate, List<String> inputs, List<String> sux) {
+        public final List<Port> inputs;
+        public final List<Port> sux;
+        private NodeClass(String className, String nameTemplate, List<Port> inputs, List<Port> sux) {
             this.className = className;
             this.nameTemplate = nameTemplate;
             this.inputs = inputs;
@@ -301,9 +310,8 @@
         int len = readInt();
         ensureAvailable(len * 2);
         char[] chars = new char[len];
-        for (int i = 0; i < len; i++) {
-            chars[i] = buffer.getChar();
-        }
+        buffer.asCharBuffer().get(chars);
+        buffer.position(buffer.position() + len * 2);
         return new String(chars);
     }
 
@@ -377,7 +385,7 @@
             return (T) addPoolEntry(klass);
         }
         assert assertObjectType(klass, type);
-        int index = readInt();
+        char index = readShort();
         if (index < 0 || index >= constantPool.size()) {
             throw new IOException("Invalid constant pool index : " + index);
         }
@@ -409,7 +417,7 @@
     }
 
     private Object addPoolEntry(Class<?> klass) throws IOException {
-        int index = readInt();
+        char index = readShort();
         int type = readByte();
         assert assertObjectType(klass, type) : "Wrong object type : " + klass + " != " + type;
         Object obj;
@@ -441,14 +449,18 @@
                 String className = readString();
                 String nameTemplate = readString();
                 int inputCount = readShort();
-                List<String> inputs = new ArrayList<>(inputCount);
+                List<Port> inputs = new ArrayList<>(inputCount);
                 for (int i = 0; i < inputCount; i++) {
-                    inputs.add(readPoolObject(String.class));
+                    boolean isList = readByte() != 0;
+                    String name = readPoolObject(String.class);
+                    inputs.add(new Port(isList, name));
                 }
                 int suxCount = readShort();
-                List<String> sux = new ArrayList<>(suxCount);
+                List<Port> sux = new ArrayList<>(suxCount);
                 for (int i = 0; i < suxCount; i++) {
-                    sux.add(readPoolObject(String.class));
+                    boolean isList = readByte() != 0;
+                    String name = readPoolObject(String.class);
+                    sux.add(new Port(isList, name));
                 }
                 obj = new NodeClass(className, nameTemplate, inputs, sux);
                 break;
@@ -685,17 +697,44 @@
                 }
             }
             int edgesStart = edges.size();
-            int suxCount = readShort();
-            for (int j = 0; j < suxCount; j++) {
-                int sux = readInt();
-                int index = readShort();
-                edges.add(new Edge(id, sux, (char) j, nodeClass.sux.get(index), false));
+            int portNum = 0;
+            for (Port p : nodeClass.inputs) {
+                if (p.isList) {
+                    int size = readShort();
+                    for (int j = 0; j < size; j++) {
+                        int in = readInt();
+                        if (in >= 0) {
+                            edges.add(new Edge(in, id, (char) (preds + portNum), p.name + "[" + j + "]", true));
+                            portNum++;
+                        }
+                    }
+                } else {
+                    int in = readInt();
+                    if (in >= 0) {
+                        edges.add(new Edge(in, id, (char) (preds + portNum), p.name, true));
+                        portNum++;
+                    }
+                }
+                
             }
-            int inputCount = readShort();
-            for (int j = 0; j < inputCount; j++) {
-                int in = readInt();
-                int index = readShort();
-                edges.add(new Edge(in, id, (char) (preds + j), nodeClass.inputs.get(index), true));
+            portNum = 0;
+            for (Port p : nodeClass.sux) {
+                if (p.isList) {
+                    int size = readShort();
+                    for (int j = 0; j < size; j++) {
+                        int sux = readInt();
+                        if (sux >= 0) {
+                            edges.add(new Edge(id, sux, (char) portNum, p.name + "[" + j + "]", false));
+                            portNum++;
+                        }
+                    }
+                } else {
+                    int sux = readInt();
+                    if (sux >= 0) {
+                        edges.add(new Edge(id, sux, (char) portNum, p.name, false));
+                        portNum++;
+                    }
+                }
             }
             properties.setProperty("name", createName(edges.subList(edgesStart, edges.size()), props, nodeClass.nameTemplate));
             properties.setProperty("class", nodeClass.className);
--- a/src/share/vm/gc_interface/collectedHeap.cpp	Tue Oct 22 11:42:10 2013 +0200
+++ b/src/share/vm/gc_interface/collectedHeap.cpp	Tue Oct 22 11:43:37 2013 +0200
@@ -506,7 +506,7 @@
          " to threads list is doomed to failure!");
   for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
      if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
-#ifdef COMPILER2
+#if defined(COMPILER2) || defined(GRAAL)
      // The deferred store barriers must all have been flushed to the
      // card-table (or other remembered set structure) before GC starts
      // processing the card-table (or other remembered set).
--- a/src/share/vm/graal/graalCompilerToGPU.cpp	Tue Oct 22 11:42:10 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToGPU.cpp	Tue Oct 22 11:43:37 2013 +0200
@@ -190,29 +190,6 @@
   return gpu::available_processors();
 C2V_END
 
-static objArrayHandle newSingletonStringArray(const char* value, TRAPS) {
-  objArrayHandle nullRes;
-  objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, CHECK_(nullRes));
-  objArrayHandle res_h = objArrayHandle(THREAD, res);
-  Handle valueString = java_lang_String::create_from_str(value, CHECK_(nullRes));
-  res_h->obj_at_put(0, valueString());
-  return res_h;
-}
-
-C2V_VMENTRY(jobject, getAvailableGPUArchitectures, (JNIEnv *env, jobject))
-  if (UseGPU) {
-    if (gpu::is_available() && gpu::has_gpu_linkage()) {
-      if (gpu::get_target_il_type() == gpu::PTX) {
-        return JNIHandles::make_local(newSingletonStringArray("PTX", THREAD)());
-      }
-      if (gpu::get_target_il_type() == gpu::HSAIL) {
-        return JNIHandles::make_local(newSingletonStringArray("HSAIL", THREAD)());
-      }
-    }
-  }
-  return JNIHandles::make_local(oopFactory::new_objArray(SystemDictionary::String_klass(), 0, THREAD));
-C2V_END
-
 C2V_VMENTRY(jboolean, deviceDetach, (JNIEnv *env, jobject))
 return true;
 C2V_END
@@ -258,7 +235,6 @@
   {CC"deviceInit",                    CC"()Z",                                    FN_PTR(deviceInit)},
   {CC"deviceDetach",                  CC"()Z",                                    FN_PTR(deviceDetach)},
   {CC"availableProcessors",           CC"()I",                                    FN_PTR(availableProcessors)},
-  {CC"getAvailableGPUArchitectures",  CC"()["STRING,                              FN_PTR(getAvailableGPUArchitectures)},
   {CC"executeExternalMethodVarargs",  CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT,    FN_PTR(executeExternalMethodVarargs)},
   {CC"executeParallelMethodVarargs",  CC"(III["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeParallelMethodVarargs)},
 };
--- a/src/share/vm/graal/graalGlobals.hpp	Tue Oct 22 11:42:10 2013 +0200
+++ b/src/share/vm/graal/graalGlobals.hpp	Tue Oct 22 11:43:37 2013 +0200
@@ -55,7 +55,7 @@
   product(intx, TraceGraal, 0,                                              \
           "Trace level for Graal")                                          \
                                                                             \
-  product(bool, GraalDeferredInitBarriers, true,                            \
+  product(bool, GraalDeferredInitBarriers, false,                           \
           "Defer write barriers of young objects")                          \
                                                                             \
   develop(bool, GraalUseFastLocking, true,                                  \
--- a/src/share/vm/runtime/arguments.cpp	Tue Oct 22 11:42:10 2013 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Tue Oct 22 11:43:37 2013 +0200
@@ -35,6 +35,7 @@
 #include "prims/jvmtiExport.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/globals_extension.hpp"
+#include "runtime/gpu.hpp"
 #include "runtime/java.hpp"
 #include "services/management.hpp"
 #include "services/memTracker.hpp"
@@ -130,6 +131,9 @@
 SystemProperty *Arguments::_java_home = NULL;
 SystemProperty *Arguments::_java_class_path = NULL;
 SystemProperty *Arguments::_sun_boot_class_path = NULL;
+#ifdef GRAAL
+SystemProperty *Arguments::_graal_gpu_isalist = NULL;
+#endif
 
 char* Arguments::_meta_index_path = NULL;
 char* Arguments::_meta_index_dir = NULL;
@@ -193,6 +197,9 @@
   _sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL,  true);
 
   _java_class_path = new SystemProperty("java.class.path", "",  true);
+#ifdef GRAAL
+  _graal_gpu_isalist = new SystemProperty("graal.gpu.isalist", NULL, true);
+#endif
 
   // Add to System Property list.
   PropertyList_add(&_system_properties, _java_ext_dirs);
@@ -202,6 +209,9 @@
   PropertyList_add(&_system_properties, _java_home);
   PropertyList_add(&_system_properties, _java_class_path);
   PropertyList_add(&_system_properties, _sun_boot_class_path);
+#ifdef GRAAL
+  PropertyList_add(&_system_properties, _graal_gpu_isalist);
+#endif
 
   // Set OS specific system properties values
   os::init_system_properties_values();
@@ -3801,6 +3811,24 @@
     }
   }
 
+#ifdef GRAAL
+  if (_graal_gpu_isalist->value() == NULL) {
+    // Initialize the graal.gpu.isalist system property if
+    // a) it was not explicitly defined by the user and
+    // b) at least one GPU is available.
+    // GPU offload can be disabled by setting the property
+    // to the empty string on the command line
+    if (gpu::is_available() && gpu::has_gpu_linkage()) {
+      if (gpu::get_target_il_type() == gpu::PTX) {
+        _graal_gpu_isalist->append_value("PTX");
+      }
+      if (gpu::get_target_il_type() == gpu::HSAIL) {
+        _graal_gpu_isalist->append_value("HSAIL");
+      }
+    }
+  }
+#endif
+
   return JNI_OK;
 }
 
--- a/src/share/vm/runtime/arguments.hpp	Tue Oct 22 11:42:10 2013 +0200
+++ b/src/share/vm/runtime/arguments.hpp	Tue Oct 22 11:43:37 2013 +0200
@@ -264,6 +264,9 @@
   static SystemProperty *_java_home;
   static SystemProperty *_java_class_path;
   static SystemProperty *_sun_boot_class_path;
+#ifdef GRAAL
+  static SystemProperty *_graal_gpu_isalist;
+#endif
 
   // Meta-index for knowing what packages are in the boot class path
   static char* _meta_index_path;
--- a/src/share/vm/runtime/globals.hpp	Tue Oct 22 11:42:10 2013 +0200
+++ b/src/share/vm/runtime/globals.hpp	Tue Oct 22 11:43:37 2013 +0200
@@ -3774,9 +3774,6 @@
   product(bool, TraceGPUInteraction, false,                                 \
           "Trace external GPU Interaction")                                 \
                                                                             \
-  product(bool, UseGPU, false,                                              \
-          "Run code on GPU")                                                \
-                                                                            \
   diagnostic(ccstr, SharedArchiveFile, NULL,                                \
           "Override the default location of the CDS archive file")          \
                                                                             \