changeset 12565:e47f373499ec

Merge.
author Christian Humer <christian.humer@gmail.com>
date Mon, 21 Oct 2013 11:07:47 +0200
parents 935dcd8ad8eb (current diff) b7c8b843dc7b (diff)
children c17bfad2fa98
files graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntimeFactory.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotGraalRuntime.java graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntimeFactory.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java
diffstat 136 files changed, 4127 insertions(+), 2568 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Mon Oct 21 11:07:47 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.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.asm.sparc;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.sparc.*;
 
 /**
@@ -1269,7 +1269,7 @@
 
         Icc(0b00, "icc"),
         Xcc(0b10, "xcc"),
-        Ptrcc(HotSpotGraalRuntime.wordKind() == Kind.Long ? Xcc.getValue() : Icc.getValue(), "ptrcc"),
+        Ptrcc(getHostWordKind() == Kind.Long ? Xcc.getValue() : Icc.getValue(), "ptrcc"),
         Fcc0(0b00, "fcc0"),
         Fcc1(0b01, "fcc1"),
         Fcc2(0b10, "fcc2"),
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Mon Oct 21 11:07:47 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.asm/src/com/oracle/graal/asm/Buffer.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java	Mon Oct 21 11:07:47 2013 +0200
@@ -60,6 +60,9 @@
     }
 
     public byte[] copyData(int start, int end) {
+        if (data == null) {
+            return null;
+        }
         return Arrays.copyOfRange(data, start, end);
     }
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -24,15 +24,20 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.test.GraalCompilerTest;
+import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.hotspot.hsail.*;
-import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.hsail.*;
+import com.oracle.graal.nodes.*;
 
 /**
  * Test class for small Java methods compiled to HSAIL kernels.
  */
 public class BasicHSAILTest extends GraalCompilerTest {
 
+    public BasicHSAILTest() {
+        super(HSAIL.class);
+    }
+
     public void testAdd() {
         test("testAddSnippet");
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -24,8 +24,12 @@
 package com.oracle.graal.compiler.hsail.test;
 
 import java.util.*;
+
 import org.junit.*;
-import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+import com.oracle.graal.compiler.hsail.*;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+import com.oracle.graal.graph.*;
 
 /**
  * Tests floating point square root.
@@ -54,7 +58,10 @@
         dispatchMethodKernel(64, input, output);
     }
 
-    @Test
+    /**
+     * Requires {@link HSAILLIRGenerator#emitDirectCall} to be implemented.
+     */
+    @Test(expected = GraalInternalError.class)
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodySpillTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodySpillTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -27,7 +27,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.compiler.hsail.*;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+import com.oracle.graal.graph.*;
 
 /**
  * This version of NBody causes Graal to generate register spilling code.
@@ -96,9 +98,11 @@
     }
 
     // Marked to only run on hardware until simulator spill bug is fixed.
-    @Test
+    /**
+     * Requires {@link HSAILLIRGenerator#emitDirectCall} to be implemented.
+     */
+    @Test(expected = GraalInternalError.class)
     public void test() {
         testGeneratedHsail();
     }
-
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -26,7 +26,10 @@
 import java.util.*;
 
 import org.junit.*;
-import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+import com.oracle.graal.compiler.hsail.*;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+import com.oracle.graal.graph.*;
 
 /**
  * Unit test of NBody demo app.
@@ -94,7 +97,10 @@
         dispatchMethodKernel(bodies, inxyz, outxyz, invxyz, outvxyz);
     }
 
-    @Test
+    /**
+     * Requires {@link HSAILLIRGenerator#emitDirectCall} to be implemented.
+     */
+    @Test(expected = GraalInternalError.class)
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -24,6 +24,9 @@
 package com.oracle.graal.compiler.hsail.test;
 
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.hsail.*;
+
 import org.junit.Test;
 
 /**
@@ -56,7 +59,10 @@
         dispatchMethodKernel(NUM, base);
     }
 
-    @Test
+    /**
+     * Requires {@link HSAILHotSpotForeignCallsProvider#lookupForeignCall} to be implemented.
+     */
+    @Test(expected = GraalInternalError.class)
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringIndexOfTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringIndexOfTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -24,6 +24,9 @@
 package com.oracle.graal.compiler.hsail.test;
 
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.hsail.*;
+
 import org.junit.Test;
 
 /**
@@ -56,7 +59,10 @@
         dispatchMethodKernel(NUM, base);
     }
 
-    @Test
+    /**
+     * Requires {@link HSAILHotSpotForeignCallsProvider#lookupForeignCall} to be implemented.
+     */
+    @Test(expected = GraalInternalError.class)
     public void test() {
         testGeneratedHsail();
     }
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Oct 21 11:07:47 2013 +0200
@@ -164,7 +164,7 @@
 
     @Override
     public Variable emitAddress(StackSlot address) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -212,12 +212,12 @@
 
     @Override
     public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -243,7 +243,7 @@
 
     @Override
     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -435,12 +435,12 @@
 
     @Override
     public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -461,12 +461,12 @@
 
     @Override
     public Variable emitOr(Value a, Value b) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public Variable emitXor(Value a, Value b) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -487,7 +487,7 @@
 
     @Override
     public Variable emitShr(Value a, Value b) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -545,17 +545,17 @@
 
     @Override
     public void emitMembar(int barriers) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -571,11 +571,11 @@
                     append(new ForeignCall1ArgOp(callName, result, arguments[0]));
                     break;
                 default:
-                    throw new InternalError("NYI emitForeignCall");
+                    throw GraalInternalError.unimplemented();
             }
 
         } else {
-            throw new InternalError("NYI emitForeignCall");
+            throw GraalInternalError.unimplemented();
         }
     }
 
@@ -590,17 +590,17 @@
 
     @Override
     public void emitBitScanForward(Variable result, Value value) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public void emitBitScanReverse(Variable result, Value value) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public Value emitMathAbs(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -612,27 +612,27 @@
 
     @Override
     public Value emitMathLog(Value input, boolean base10) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public Value emitMathCos(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public Value emitMathSin(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public Value emitMathTan(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public void emitByteSwap(Variable result, Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -642,27 +642,27 @@
 
     @Override
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public void visitBreakpointNode(BreakpointNode node) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -672,7 +672,7 @@
 
     @Override
     public void emitUnwind(Value operand) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -685,6 +685,6 @@
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Mon Oct 21 11:07:47 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.ptx.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -54,13 +55,17 @@
 
     }
 
+    public PTXTestBase() {
+        super(PTX.class);
+    }
+
     protected CompilationResult compile(String test) {
-        if (getCodeCache() instanceof PTXHotSpotCodeCacheProvider) {
+        if (getBackend() instanceof PTXHotSpotBackend) {
             StructuredGraph graph = parse(test);
             sg = graph;
             Debug.dump(graph, "Graph");
-            TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true);
-            PTXBackend ptxBackend = new PTXBackend(getProviders());
+            Backend ptxBackend = getBackend();
+            TargetDescription target = ptxBackend.getTarget();
             PhasePlan phasePlan = new PhasePlan();
             GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
@@ -76,8 +81,9 @@
              * Ultimately we might want to have both the kernel and the code natively compiled for
              * GPU fallback to CPU in cases of ECC failure on kernel invocation.
              */
+            Suites suites = Suites.createDefaultSuites();
             CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), ptxBackend, target, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(),
-                            Suites.createDefaultSuites(), new ExternalCompilationResult());
+                            suites, new ExternalCompilationResult());
             return result;
         } else {
             return null;
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Mon Oct 21 11:07:32 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.ptx;
-
-import static com.oracle.graal.lir.LIRValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.OperandFlag;
-import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-import com.oracle.graal.lir.StandardOp.LabelOp;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.lir.ptx.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.util.*;
-
-/**
- * PTX specific backend.
- */
-public class PTXBackend extends Backend {
-
-    public PTXBackend(Providers providers) {
-        super(providers);
-    }
-
-    @Override
-    public boolean shouldAllocateRegisters() {
-        return false;
-    }
-
-    @Override
-    public FrameMap newFrameMap() {
-        return new PTXFrameMap(getCodeCache());
-    }
-
-    @Override
-    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        return new PTXLIRGenerator(graph, getProviders(), frameMap, cc, lir);
-    }
-
-    class PTXFrameContext implements FrameContext {
-
-        @Override
-        public void enter(TargetMethodAssembler tasm) {
-            // codeBuffer.emitString(".address_size 32"); // PTX ISA version 2.3
-        }
-
-        @Override
-        public void leave(TargetMethodAssembler tasm) {
-        }
-    }
-
-    @Override
-    protected AbstractAssembler createAssembler(FrameMap frameMap) {
-        return new PTXAssembler(getTarget(), frameMap.registerConfig);
-    }
-
-    @Override
-    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
-        // Omit the frame of the method:
-        // - has no spill slots or other slots allocated during register allocation
-        // - has no callee-saved registers
-        // - has no incoming arguments passed on the stack
-        // - has no instructions with debug info
-        FrameMap frameMap = lirGen.frameMap;
-        AbstractAssembler masm = createAssembler(frameMap);
-        PTXFrameContext frameContext = new PTXFrameContext();
-        TargetMethodAssembler tasm = new PTXTargetMethodAssembler(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
-        tasm.setFrameSize(0);
-        return tasm;
-    }
-
-    private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
-        // Emit PTX kernel entry text based on PTXParameterOp
-        // instructions in the start block. Remove the instructions
-        // once kernel entry text and directives are emitted to
-        // facilitate seemless PTX code generation subsequently.
-        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
-        final String name = codeCacheOwner.getName();
-        Buffer codeBuffer = tasm.asm.codeBuffer;
-
-        // Emit initial boiler-plate directives.
-        codeBuffer.emitString(".version 3.0");
-        codeBuffer.emitString(".target sm_30");
-        codeBuffer.emitString0(".entry " + name + " (");
-        codeBuffer.emitString("");
-
-        // Get the start block
-        Block startBlock = lirGen.lir.cfg.getStartBlock();
-        // Keep a list of ParameterOp instructions to delete from the
-        // list of instructions in the block.
-        ArrayList<LIRInstruction> deleteOps = new ArrayList<>();
-
-        // Emit .param arguments to kernel entry based on ParameterOp
-        // instruction.
-        for (LIRInstruction op : lirGen.lir.lir(startBlock)) {
-            if (op instanceof PTXParameterOp) {
-                op.emitCode(tasm);
-                deleteOps.add(op);
-            }
-        }
-
-        // Delete ParameterOp instructions.
-        for (LIRInstruction op : deleteOps) {
-            lirGen.lir.lir(startBlock).remove(op);
-        }
-
-        // Start emiting body of the PTX kernel.
-        codeBuffer.emitString0(") {");
-        codeBuffer.emitString("");
-    }
-
-    // Emit .reg space declarations
-    private static void emitRegisterDecl(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
-
-        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
-
-        Buffer codeBuffer = tasm.asm.codeBuffer;
-
-        final SortedSet<Integer> signed32 = new TreeSet<>();
-        final SortedSet<Integer> signed64 = new TreeSet<>();
-        final SortedSet<Integer> unsigned64 = new TreeSet<>();
-        final SortedSet<Integer> float32 = new TreeSet<>();
-        final SortedSet<Integer> float64 = new TreeSet<>();
-
-        ValueProcedure trackRegisterKind = new ValueProcedure() {
-
-            @Override
-            public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-                if (isVariable(value)) {
-                    Variable regVal = (Variable) value;
-                    Kind regKind = regVal.getKind();
-                    switch (regKind) {
-                        case Int:
-                            // If the register was used as a wider signed type
-                            // do not add it here
-                            if (!signed64.contains(regVal.index)) {
-                                signed32.add(regVal.index);
-                            }
-                            break;
-                        case Long:
-                            // If the register was used as a narrower signed type
-                            // remove it from there and add it to wider type.
-                            if (signed32.contains(regVal.index)) {
-                                signed32.remove(regVal.index);
-                            }
-                            signed64.add(regVal.index);
-                            break;
-                        case Float:
-                            // If the register was used as a wider signed type
-                            // do not add it here
-                            if (!float64.contains(regVal.index)) {
-                                float32.add(regVal.index);
-                            }
-                            break;
-                        case Double:
-                            // If the register was used as a narrower signed type
-                            // remove it from there and add it to wider type.
-                            if (float32.contains(regVal.index)) {
-                                float32.remove(regVal.index);
-                            }
-                            float64.add(regVal.index);
-                            break;
-                        case Object:
-                            unsigned64.add(regVal.index);
-                            break;
-                        default:
-                            throw GraalInternalError.shouldNotReachHere("unhandled register type " + value.toString());
-                    }
-                }
-                return value;
-            }
-        };
-
-        for (Block b : lirGen.lir.codeEmittingOrder()) {
-            for (LIRInstruction op : lirGen.lir.lir(b)) {
-                if (op instanceof LabelOp) {
-                    // Don't consider this as a definition
-                } else {
-                    op.forEachTemp(trackRegisterKind);
-                    op.forEachOutput(trackRegisterKind);
-                }
-            }
-        }
-
-        for (Integer i : signed32) {
-            codeBuffer.emitString(".reg .s32 %r" + i.intValue() + ";");
-        }
-        for (Integer i : signed64) {
-            codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";");
-        }
-        for (Integer i : unsigned64) {
-            codeBuffer.emitString(".reg .u64 %r" + i.intValue() + ";");
-        }
-        for (Integer i : float32) {
-            codeBuffer.emitString(".reg .f32 %r" + i.intValue() + ";");
-        }
-        for (Integer i : float64) {
-            codeBuffer.emitString(".reg .f64 %r" + i.intValue() + ";");
-        }
-        // emit predicate register declaration
-        int maxPredRegNum = ((PTXLIRGenerator) lirGen).getNextPredRegNumber();
-        if (maxPredRegNum > 0) {
-            codeBuffer.emitString(".reg .pred %p<" + maxPredRegNum + ">;");
-        }
-        codeBuffer.emitString(".reg .pred %r;");  // used for setp bool
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
-        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
-        Buffer codeBuffer = tasm.asm.codeBuffer;
-        // Emit the prologue
-        emitKernelEntry(tasm, lirGen, codeCacheOwner);
-
-        // Emit register declarations
-        try {
-            emitRegisterDecl(tasm, lirGen, codeCacheOwner);
-        } catch (GraalInternalError e) {
-            e.printStackTrace();
-            // TODO : Better error handling needs to be done once
-            // all types of parameters are handled.
-            codeBuffer.setPosition(0);
-            codeBuffer.close(false);
-            return;
-        }
-        // Emit code for the LIR
-        try {
-            lirGen.lir.emitCode(tasm);
-        } catch (GraalInternalError e) {
-            e.printStackTrace();
-            // TODO : Better error handling needs to be done once
-            // all types of parameters are handled.
-            codeBuffer.setPosition(0);
-            codeBuffer.close(false);
-            return;
-        }
-
-        // Emit the epilogue
-        codeBuffer.emitString0("}");
-        codeBuffer.emitString("");
-    }
-}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Oct 21 11:07:47 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.*;
 
 /**
@@ -78,13 +79,32 @@
 public abstract class GraalCompilerTest extends GraalTest {
 
     private final Providers providers;
-    protected final Backend backend;
-    protected final Suites suites;
+    private final Backend backend;
+    private final Suites suites;
 
     public GraalCompilerTest() {
-        this.providers = GraalCompiler.getGraalProviders();
-        this.backend = Graal.getRequiredCapability(Backend.class);
-        this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
+        this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
+        this.providers = getBackend().getProviders();
+        this.suites = backend.getSuites().createSuites();
+    }
+
+    /**
+     * Set up a test for a non-default backend. The test should check (via {@link #getBackend()} )
+     * whether the desired backend is available.
+     * 
+     * @param arch the name of the desired backend architecture
+     */
+    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 = runtime.getHostBackend();
+        }
+        this.providers = backend.getProviders();
+        this.suites = backend.getSuites().createSuites();
     }
 
     @BeforeClass
@@ -157,6 +177,14 @@
         return result.toString();
     }
 
+    protected Backend getBackend() {
+        return backend;
+    }
+
+    protected Suites getSuites() {
+        return suites;
+    }
+
     protected Providers getProviders() {
         return providers;
     }
@@ -487,8 +515,8 @@
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                 CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
-                final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, getProviders(), backend, getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
-                                new SpeculationLog(), suites, new CompilationResult());
+                final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, phasePlan,
+                                OptimisticOptimizations.ALL, new SpeculationLog(), getSuites(), new CompilationResult());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
@@ -504,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/InfopointReasonTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -59,8 +59,8 @@
         final Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
         CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
-        final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), backend, getCodeCache().getTarget(), null, getDefaultPhasePlan(),
-                        OptimisticOptimizations.ALL, new SpeculationLog(), suites, new CompilationResult());
+        final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultPhasePlan(),
+                        OptimisticOptimizations.ALL, new SpeculationLog(), getSuites(), new CompilationResult());
         for (Infopoint sp : cr.getInfopoints()) {
             assertNotNull(sp.reason);
             if (sp instanceof Call) {
@@ -81,8 +81,8 @@
         }
         assertTrue(graphLineSPs > 0);
         CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
-        final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), backend, getCodeCache().getTarget(), null, getDefaultPhasePlan(true),
-                        OptimisticOptimizations.ALL, new SpeculationLog(), suites, new CompilationResult());
+        final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultPhasePlan(true),
+                        OptimisticOptimizations.ALL, new SpeculationLog(), getSuites(), new CompilationResult());
         int lineSPs = 0;
         for (Infopoint sp : cr.getInfopoints()) {
             assertNotNull(sp.reason);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Oct 21 11:07:47 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/backend/AllocatorTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -119,7 +119,7 @@
 
             @Override
             public LIR call() {
-                return GraalCompiler.emitHIR(getProviders(), backend.getTarget(), graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), suites);
+                return GraalCompiler.emitHIR(getProviders(), getBackend().getTarget(), graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), getSuites());
             }
         });
 
@@ -128,7 +128,7 @@
             @Override
             public RegisterStats call() {
                 CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
-                GraalCompiler.emitLIR(backend, backend.getTarget(), lir, graph, cc);
+                GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), lir, graph, cc);
                 return new RegisterStats(lir);
             }
         });
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Oct 21 11:07:47 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() {
@@ -284,19 +283,10 @@
         }
         result.setLeafGraphIds(leafGraphIds);
 
+        if (Debug.isLogEnabled()) {
+            Debug.log("%s", backend.getProviders().getCodeCache().disassemble(result, null));
+        }
+
         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/phases/MidTier.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Mon Oct 21 11:07:47 2013 +0200
@@ -29,10 +29,11 @@
 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.*;
 
 /**
- * The {@code Backend} class represents a compiler backend for Graal.
+ * Represents a compiler backend for Graal.
  */
 public abstract class Backend {
 
@@ -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.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Oct 21 11:07:47 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() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,183 @@
+/*
+ * 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.hotspot.amd64;
+
+import java.util.*;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+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)
+public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
+
+    protected Architecture createArchitecture(HotSpotVMConfig config) {
+        return new AMD64(config.useSSE, config.useAVX);
+    }
+
+    protected TargetDescription createTarget(HotSpotVMConfig config) {
+        final int stackFrameAlignment = 16;
+        final int implicitNullCheckLimit = 4096;
+        final boolean inlineObjects = true;
+        return new TargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+    }
+
+    @Override
+    public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host) {
+        assert host == null;
+        TargetDescription target = createTarget(runtime.getConfig());
+
+        HotSpotMetaAccessProvider metaAccess = createMetaAccess(runtime);
+        HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target);
+        HotSpotConstantReflectionProvider constantReflection = createConstantReflection(runtime);
+        Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig());
+        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);
+        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);
+    }
+
+    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
+            callerSave.remove(AMD64.rdi);
+            callerSave.remove(AMD64.rsi);
+            callerSave.remove(AMD64.rbx);
+            callerSave.remove(AMD64.rbp);
+            callerSave.remove(AMD64.rsp);
+            callerSave.remove(AMD64.r12);
+            callerSave.remove(AMD64.r13);
+            callerSave.remove(AMD64.r14);
+            callerSave.remove(AMD64.r15);
+            callerSave.remove(AMD64.xmm6);
+            callerSave.remove(AMD64.xmm7);
+            callerSave.remove(AMD64.xmm8);
+            callerSave.remove(AMD64.xmm9);
+            callerSave.remove(AMD64.xmm10);
+            callerSave.remove(AMD64.xmm11);
+            callerSave.remove(AMD64.xmm12);
+            callerSave.remove(AMD64.xmm13);
+            callerSave.remove(AMD64.xmm14);
+            callerSave.remove(AMD64.xmm15);
+        } else {
+            /*
+             * System V Application Binary Interface, AMD64 Architecture Processor Supplement
+             * 
+             * Draft Version 0.96
+             * 
+             * http://www.uclibc.org/docs/psABI-x86_64.pdf
+             * 
+             * 3.2.1
+             * 
+             * ...
+             * 
+             * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12
+             * through %r15 "belong" to the calling function and the called function is required to
+             * preserve their values. In other words, a called function must preserve these
+             * registers' values for its caller. Remaining registers "belong" to the called
+             * function. If a calling function wants to preserve such a register value across a
+             * function call, it must save the value in its local stack frame.
+             */
+            callerSave.remove(AMD64.rbp);
+            callerSave.remove(AMD64.rbx);
+            callerSave.remove(AMD64.r12);
+            callerSave.remove(AMD64.r13);
+            callerSave.remove(AMD64.r14);
+            callerSave.remove(AMD64.r15);
+        }
+        Value[] nativeABICallerSaveRegisters = new Value[callerSave.size()];
+        for (int i = 0; i < callerSave.size(); i++) {
+            nativeABICallerSaveRegisters[i] = callerSave.get(i).asValue();
+        }
+        return nativeABICallerSaveRegisters;
+    }
+
+    public String getArchitecture() {
+        return "AMD64";
+    }
+
+    public String getGraalRuntimeName() {
+        return "basic";
+    }
+
+    @Override
+    public String toString() {
+        return getGraalRuntimeName() + ":" + getArchitecture();
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,11 +22,8 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
@@ -34,13 +31,20 @@
 @Opcode("CRUNTIME_CALL_EPILOGUE")
 final class AMD64HotSpotCRuntimeCallEpilogueOp extends AMD64LIRInstruction {
 
+    private final int threadLastJavaSpOffset;
+    private final int threadLastJavaFpOffset;
+    private final Register thread;
+
+    public AMD64HotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaFpOffset, Register thread) {
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.threadLastJavaFpOffset = threadLastJavaFpOffset;
+        this.thread = thread;
+    }
+
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         // reset last Java frame:
-        HotSpotVMConfig config = runtime().getConfig();
-        Register thread = runtime().getProviders().getRegisters().getThreadRegister();
-
-        masm.movslq(new AMD64Address(thread, config.threadLastJavaSpOffset), 0);
-        masm.movslq(new AMD64Address(thread, config.threadLastJavaFpOffset), 0);
+        masm.movslq(new AMD64Address(thread, threadLastJavaSpOffset), 0);
+        masm.movslq(new AMD64Address(thread, threadLastJavaFpOffset), 0);
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java	Mon Oct 21 11:07:47 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.amd64.AMD64.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
@@ -34,11 +33,17 @@
 @Opcode
 final class AMD64HotSpotCRuntimeCallPrologueOp extends AMD64LIRInstruction {
 
+    private final int threadLastJavaSpOffset;
+    private final Register thread;
+
+    public AMD64HotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread) {
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.thread = thread;
+    }
+
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-
         // save last Java frame
-        Register thread = runtime().getProviders().getRegisters().getThreadRegister();
-        masm.movq(new AMD64Address(thread, runtime().getConfig().threadLastJavaSpOffset), rsp);
+        masm.movq(new AMD64Address(thread, threadLastJavaSpOffset), rsp);
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCodeCacheProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCodeCacheProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -28,13 +28,12 @@
 
 public class AMD64HotSpotCodeCacheProvider extends HotSpotCodeCacheProvider {
 
-    public AMD64HotSpotCodeCacheProvider(HotSpotGraalRuntime runtime) {
-        super(runtime);
-
+    public AMD64HotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) {
+        super(runtime, target);
     }
 
     @Override
     protected RegisterConfig createRegisterConfig() {
-        return new AMD64HotSpotRegisterConfig(runtime.getTarget().arch, runtime.getConfig());
+        return new AMD64HotSpotRegisterConfig(getTarget().arch, runtime.getConfig());
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -39,16 +39,18 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
-public class AMD64HotSpotForeignCallsProvider extends HotSpotForeignCallsProvider {
+public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider {
+
+    private final Value[] nativeABICallerSaveRegisters;
 
-    public AMD64HotSpotForeignCallsProvider(HotSpotGraalRuntime runtime) {
-        super(runtime);
+    public AMD64HotSpotForeignCallsProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, Value[] nativeABICallerSaveRegisters) {
+        super(runtime, metaAccess, codeCache);
+        this.nativeABICallerSaveRegisters = nativeABICallerSaveRegisters;
     }
 
     @Override
-    public void initialize(HotSpotProviders providers) {
-        Kind word = runtime.getTarget().wordKind;
-        HotSpotVMConfig config = runtime.getConfig();
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+        Kind word = providers.getCodeCache().getTarget().wordKind;
 
         // The calling convention for the exception handler stub is (only?) defined in
         // TemplateInterpreterGenerator::generate_throw_exception()
@@ -66,6 +68,12 @@
         registerForeignCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
 
-        super.initialize(providers);
+        super.initialize(providers, config);
     }
+
+    @Override
+    public Value[] getNativeABICallerSaveRegisters() {
+        return nativeABICallerSaveRegisters;
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java	Mon Oct 21 11:07:32 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +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.hotspot.amd64;
-
-import java.util.*;
-
-import com.oracle.graal.amd64.*;
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.phases.util.*;
-
-/**
- * AMD64 specific implementation of {@link HotSpotGraalRuntime}.
- */
-public class AMD64HotSpotGraalRuntime extends HotSpotGraalRuntime {
-
-    private Value[] nativeABICallerSaveRegisters;
-
-    protected AMD64HotSpotGraalRuntime() {
-    }
-
-    /**
-     * Called from C++ code to retrieve the singleton instance, creating it first if necessary.
-     */
-    public static HotSpotGraalRuntime makeInstance() {
-        HotSpotGraalRuntime runtime = runtime();
-        if (runtime == null) {
-            HotSpotGraalRuntimeFactory factory = findFactory("AMD64");
-            if (factory != null) {
-                runtime = factory.createRuntime();
-            } else {
-                runtime = new AMD64HotSpotGraalRuntime();
-            }
-            runtime.completeInitialization();
-        }
-        return runtime;
-    }
-
-    protected Architecture createArchitecture() {
-        return new AMD64(config.useSSE, config.useAVX);
-    }
-
-    @Override
-    protected HotSpotProviders createProviders() {
-        HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(this);
-        HotSpotCodeCacheProvider codeCache = new AMD64HotSpotCodeCacheProvider(this);
-        HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(this);
-        HotSpotForeignCallsProvider foreignCalls = new AMD64HotSpotForeignCallsProvider(this);
-        HotSpotLoweringProvider lowerer = new AMD64HotSpotLoweringProvider(this, 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, getConfig(), assumptions);
-        HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(this);
-        HotSpotSuitesProvider suites = new HotSpotSuitesProvider(this);
-        HotSpotRegisters registers = new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp);
-        return new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
-    }
-
-    @Override
-    protected TargetDescription createTarget() {
-        final int stackFrameAlignment = 16;
-        final int implicitNullCheckLimit = 4096;
-        final boolean inlineObjects = true;
-        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
-    }
-
-    @Override
-    protected HotSpotBackend createBackend() {
-        return new AMD64HotSpotBackend(this, getProviders());
-    }
-
-    @Override
-    protected Value[] getNativeABICallerSaveRegisters() {
-        if (nativeABICallerSaveRegisters == null) {
-            List<Register> callerSave = new ArrayList<>(Arrays.asList(getProviders().getCodeCache().getRegisterConfig().getAllocatableRegisters()));
-            if (getConfig().windowsOs) {
-                // http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
-                callerSave.remove(AMD64.rdi);
-                callerSave.remove(AMD64.rsi);
-                callerSave.remove(AMD64.rbx);
-                callerSave.remove(AMD64.rbp);
-                callerSave.remove(AMD64.rsp);
-                callerSave.remove(AMD64.r12);
-                callerSave.remove(AMD64.r13);
-                callerSave.remove(AMD64.r14);
-                callerSave.remove(AMD64.r15);
-                callerSave.remove(AMD64.xmm6);
-                callerSave.remove(AMD64.xmm7);
-                callerSave.remove(AMD64.xmm8);
-                callerSave.remove(AMD64.xmm9);
-                callerSave.remove(AMD64.xmm10);
-                callerSave.remove(AMD64.xmm11);
-                callerSave.remove(AMD64.xmm12);
-                callerSave.remove(AMD64.xmm13);
-                callerSave.remove(AMD64.xmm14);
-                callerSave.remove(AMD64.xmm15);
-            } else {
-                /*
-                 * System V Application Binary Interface, AMD64 Architecture Processor Supplement
-                 * 
-                 * Draft Version 0.96
-                 * 
-                 * http://www.uclibc.org/docs/psABI-x86_64.pdf
-                 * 
-                 * 3.2.1
-                 * 
-                 * ...
-                 * 
-                 * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12
-                 * through %r15 "belong" to the calling function and the called function is required
-                 * to preserve their values. In other words, a called function must preserve these
-                 * registers' values for its caller. Remaining registers "belong" to the called
-                 * function. If a calling function wants to preserve such a register value across a
-                 * function call, it must save the value in its local stack frame.
-                 */
-                callerSave.remove(AMD64.rbp);
-                callerSave.remove(AMD64.rbx);
-                callerSave.remove(AMD64.r12);
-                callerSave.remove(AMD64.r13);
-                callerSave.remove(AMD64.r14);
-                callerSave.remove(AMD64.r15);
-            }
-            nativeABICallerSaveRegisters = new Value[callerSave.size()];
-            for (int i = 0; i < callerSave.size(); i++) {
-                nativeABICallerSaveRegisters[i] = callerSave.get(i).asValue();
-            }
-        }
-
-        return nativeABICallerSaveRegisters;
-    }
-}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntimeFactory.java	Mon Oct 21 11:07:32 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.amd64;
-
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.hotspot.*;
-
-@ServiceProvider(HotSpotGraalRuntimeFactory.class)
-public class AMD64HotSpotGraalRuntimeFactory implements HotSpotGraalRuntimeFactory {
-
-    @Override
-    public HotSpotGraalRuntime createRuntime() {
-        return new AMD64HotSpotGraalRuntime();
-    }
-
-    @Override
-    public String getArchitecture() {
-        return "AMD64";
-    }
-
-    @Override
-    public String getName() {
-        return "basic";
-    }
-}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Mon Oct 21 11:07:47 2013 +0200
@@ -24,7 +24,6 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.code.*;
@@ -44,11 +43,15 @@
     @Use(REG) AllocatableValue handlerInCallerPc;
     @Use(REG) AllocatableValue exception;
     @Use(REG) AllocatableValue exceptionPc;
+    private final Register thread;
+    private final int isMethodHandleReturnOffset;
 
-    AMD64HotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc) {
+    AMD64HotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc, int isMethodHandleReturnOffset, Register thread) {
         this.handlerInCallerPc = handlerInCallerPc;
         this.exception = exception;
         this.exceptionPc = exceptionPc;
+        this.isMethodHandleReturnOffset = isMethodHandleReturnOffset;
+        this.thread = thread;
     }
 
     @Override
@@ -59,8 +62,6 @@
         masm.incrementq(rsp, 8);
 
         // Restore rsp from rbp if the exception PC is a method handle call site.
-        Register thread = runtime().getProviders().getRegisters().getThreadRegister();
-        int isMethodHandleReturnOffset = runtime().getConfig().threadIsMethodHandleReturnOffset;
         AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset);
         masm.cmpl(dst, 0);
         masm.cmovq(ConditionFlag.NotEqual, rsp, rbp);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Oct 21 11:07:47 2013 +0200
@@ -180,9 +180,24 @@
         }
     }
 
+    private Register findPollOnReturnScratchRegister() {
+        RegisterConfig regConfig = getProviders().getCodeCache().getRegisterConfig();
+        for (Register r : regConfig.getAllocatableRegisters(Kind.Long)) {
+            if (r != regConfig.getReturnRegister(Kind.Long) && r != AMD64.rbp) {
+                return r;
+            }
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    private Register pollOnReturnScratchRegister;
+
     @Override
     protected void emitReturn(Value input) {
-        append(new AMD64HotSpotReturnOp(input, getStub() != null));
+        if (pollOnReturnScratchRegister == null) {
+            pollOnReturnScratchRegister = findPollOnReturnScratchRegister();
+        }
+        append(new AMD64HotSpotReturnOp(input, getStub() != null, pollOnReturnScratchRegister));
     }
 
     @Override
@@ -249,9 +264,10 @@
 
         if (linkage.canDeoptimize()) {
             assert info != null || stub != null;
-            append(new AMD64HotSpotCRuntimeCallPrologueOp());
+            Register thread = getProviders().getRegisters().getThreadRegister();
+            append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset, thread));
             result = super.emitForeignCall(linkage, info, args);
-            append(new AMD64HotSpotCRuntimeCallEpilogueOp());
+            append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset, config.threadLastJavaFpOffset, thread));
         } else {
             result = super.emitForeignCall(linkage, null, args);
         }
@@ -408,7 +424,8 @@
         RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1);
         emitMove(exceptionFixed, operand(exception));
         emitMove(exceptionPcFixed, operand(exceptionPc));
-        AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed);
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, config.threadIsMethodHandleReturnOffset, thread);
         append(op);
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.amd64.*;
 
-public class AMD64HotSpotLoweringProvider extends HotSpotLoweringProvider {
+public class AMD64HotSpotLoweringProvider extends HotSpotHostLoweringProvider {
 
     private AMD64ConvertSnippets.Templates convertSnippets;
 
@@ -40,10 +40,9 @@
     }
 
     @Override
-    public void initialize() {
-        HotSpotProviders providers = runtime.getProviders();
-        convertSnippets = new AMD64ConvertSnippets.Templates(providers, runtime.getTarget());
-        super.initialize();
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+        convertSnippets = new AMD64ConvertSnippets.Templates(providers, providers.getCodeCache().getTarget());
+        super.initialize(providers, config);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Mon Oct 21 11:07:47 2013 +0200
@@ -26,12 +26,9 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
-import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -43,24 +40,14 @@
 
     @Use({REG, ILLEGAL}) protected Value value;
     private final boolean isStub;
+    private final Register scratchForSafepointOnReturn;
 
-    AMD64HotSpotReturnOp(Value value, boolean isStub) {
+    AMD64HotSpotReturnOp(Value value, boolean isStub, Register scratchForSafepointOnReturn) {
         this.value = value;
         this.isStub = isStub;
+        this.scratchForSafepointOnReturn = scratchForSafepointOnReturn;
     }
 
-    private static Register findPollOnReturnScratchRegister() {
-        RegisterConfig config = HotSpotGraalRuntime.runtime().getProviders().getCodeCache().getRegisterConfig();
-        for (Register r : config.getAllocatableRegisters(Kind.Long)) {
-            if (r != config.getReturnRegister(Kind.Long) && r != AMD64.rbp) {
-                return r;
-            }
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
-
-    private static final Register scratchForSafepointOnReturn = findPollOnReturnScratchRegister();
-
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         leaveFrameAndRestoreRbp(tasm, masm);
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Mon Oct 21 11:07:47 2013 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
@@ -57,8 +56,7 @@
                 acceptMethod = m;
             }
         }
-        HotSpotGraalRuntime runtime = HotSpotGraalRuntime.runtime();
-        HotSpotProviders providers = runtime.getProviders();
+        HotSpotProviders providers = HSAILCompilationResult.backend.getProviders();
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         ResolvedJavaMethod method = metaAccess.lookupJavaMethod(acceptMethod);
         StructuredGraph graph = new StructuredGraph(method);
@@ -83,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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java	Mon Oct 21 11:07:47 2013 +0200
@@ -23,6 +23,8 @@
 
 package com.oracle.graal.hotspot.hsail;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
 import java.lang.reflect.*;
 import java.util.logging.*;
 
@@ -33,8 +35,8 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.*;
 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.*;
@@ -42,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;
@@ -73,17 +77,27 @@
         consoleHandler.setLevel(logLevel);
     }
 
-    private static final HotSpotGraalRuntime runtime = new HSAILHotSpotGraalRuntime();
+    static final HSAILHotSpotBackend backend;
+    static {
+        // Look for installed HSAIL backend
+        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());
+        }
+        backend = b;
+    }
 
     public static HSAILCompilationResult getHSAILCompilationResult(Method meth) {
-        HotSpotMetaAccessProvider metaAccess = runtime.getProviders().getMetaAccess();
+        HotSpotMetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
         ResolvedJavaMethod javaMethod = metaAccess.lookupJavaMethod(meth);
         return getHSAILCompilationResult(javaMethod);
     }
 
     public static HSAILCompilationResult getHSAILCompilationResult(ResolvedJavaMethod javaMethod) {
-        HotSpotMetaAccessProvider metaAccess = runtime.getProviders().getMetaAccess();
-        ForeignCallsProvider foreignCalls = runtime.getProviders().getForeignCalls();
+        HotSpotMetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
+        ForeignCallsProvider foreignCalls = backend.getProviders().getForeignCalls();
         StructuredGraph graph = new StructuredGraph(javaMethod);
         new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
         return getHSAILCompilationResult(graph);
@@ -112,28 +126,27 @@
             argTypes[argIndex++] = sig.getParameterType(i, null);
         }
 
-        RegisterConfig registerConfig = runtime.getProviders().getCodeCache().getRegisterConfig();
+        RegisterConfig registerConfig = backend.getProviders().getCodeCache().getRegisterConfig();
         return registerConfig.getCallingConvention(type, retType, argTypes, target, stackOnly);
     }
 
     public static HSAILCompilationResult getHSAILCompilationResult(StructuredGraph graph) {
         Debug.dump(graph, "Graph");
-        Providers providers = runtime.getProviders();
+        Providers providers = backend.getProviders();
         TargetDescription target = providers.getCodeCache().getTarget();
-        HSAILHotSpotBackend hsailBackend = (HSAILHotSpotBackend) runtime.getBackend();
         PhasePlan phasePlan = new PhasePlan();
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(providers.getMetaAccess(), providers.getForeignCalls(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         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, hsailBackend, 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 = hsailBackend.getPartialCodeString();
+            String partialCode = backend.getPartialCodeString();
             if (partialCode != null && !partialCode.equals("")) {
                 logger.fine("-------------------\nPartial Code Generation:\n--------------------");
                 logger.fine(partialCode);
@@ -155,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/HSAILHotSpotBackend.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Mon Oct 21 11:07:47 2013 +0200
@@ -78,7 +78,11 @@
     }
 
     public String getPartialCodeString() {
-        return (codeBuffer == null ? "" : new String(codeBuffer.copyData(0, codeBuffer.position())));
+        if (codeBuffer == null) {
+            return "";
+        }
+        byte[] data = codeBuffer.copyData(0, codeBuffer.position());
+        return (data == null ? "" : new String(data));
     }
 
     class HotSpotFrameContext implements FrameContext {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.hsail;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hsail.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.util.*;
+
+@ServiceProvider(HotSpotBackendFactory.class)
+public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory {
+
+    @Override
+    public HSAILHotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend hostBackend) {
+        HotSpotProviders host = hostBackend.getProviders();
+
+        HotSpotMetaAccessProvider metaAccess = host.getMetaAccess();
+        HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, createTarget());
+        ConstantReflectionProvider constantReflection = host.getConstantReflection();
+        HotSpotForeignCallsProvider foreignCalls = new HSAILHotSpotForeignCallsProvider(host.getForeignCalls());
+        LoweringProvider lowerer = new HSAILHotSpotLoweringProvider(host.getLowerer());
+        // 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);
+        Replacements replacements = new HSAILHotSpotReplacementsImpl(p, assumptions);
+        HotSpotDisassemblerProvider disassembler = host.getDisassembler();
+        HotSpotSuitesProvider suites = host.getSuites();
+        HotSpotRegisters registers = new HotSpotRegisters(Register.None, Register.None, Register.None);
+        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
+
+        return new HSAILHotSpotBackend(runtime, providers);
+    }
+
+    protected TargetDescription createTarget() {
+        final int stackFrameAlignment = 8;
+        final int implicitNullCheckLimit = 0;
+        final boolean inlineObjects = true;
+        return new TargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+    }
+
+    public String getArchitecture() {
+        return "HSAIL";
+    }
+
+    public String getGraalRuntimeName() {
+        return "basic";
+    }
+
+    @Override
+    public String toString() {
+        return getGraalRuntimeName() + ":" + getArchitecture();
+    }
+}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java	Mon Oct 21 11:07:47 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.*;
@@ -29,9 +31,15 @@
 
 public class HSAILHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider {
 
-    public HSAILHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime) {
-        super(runtime);
+    public HSAILHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) {
+        super(runtime, target);
+
+    }
 
+    @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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotForeignCallsProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.hsail;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+
+public class HSAILHotSpotForeignCallsProvider implements HotSpotForeignCallsProvider {
+
+    private final ForeignCallsProvider host;
+
+    public HSAILHotSpotForeignCallsProvider(ForeignCallsProvider host) {
+        this.host = host;
+    }
+
+    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
+        return host.isReexecutable(descriptor);
+    }
+
+    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
+        return host.getKilledLocations(descriptor);
+    }
+
+    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
+        return host.canDeoptimize(descriptor);
+    }
+
+    public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public Value[] getNativeABICallerSaveRegisters() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+    }
+}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotGraalRuntime.java	Mon Oct 21 11:07:32 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +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.hotspot.hsail;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hsail.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * HSAIL specific implementation of {@link HotSpotGraalRuntime}.
- */
-public class HSAILHotSpotGraalRuntime extends HotSpotGraalRuntime {
-
-    @Override
-    protected HotSpotProviders createProviders() {
-        HotSpotProviders host = HotSpotGraalRuntime.runtime().getProviders();
-
-        HotSpotMetaAccessProvider metaAccess = host.getMetaAccess();
-        HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(this);
-        ConstantReflectionProvider constantReflection = host.getConstantReflection();
-        HotSpotForeignCallsProvider foreignCalls = host.getForeignCalls();
-        LoweringProvider lowerer = new HSAILHotSpotLoweringProvider(host.getLowerer());
-        Replacements replacements = host.getReplacements();
-        HotSpotDisassemblerProvider disassembler = host.getDisassembler();
-        HotSpotSuitesProvider suites = host.getSuites();
-        HotSpotRegisters registers = new HotSpotRegisters(Register.None, Register.None, Register.None);
-        return new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
-    }
-
-    @Override
-    protected TargetDescription createTarget() {
-        final int stackFrameAlignment = 8;
-        final int implicitNullCheckLimit = 0;
-        final boolean inlineObjects = true;
-        return new TargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
-    }
-
-    @Override
-    protected HotSpotBackend createBackend() {
-        return new HSAILHotSpotBackend(this, getProviders());
-    }
-
-    @Override
-    protected Value[] getNativeABICallerSaveRegisters() {
-        throw new InternalError("NYI");
-    }
-}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,18 +22,21 @@
  */
 package com.oracle.graal.hotspot.hsail;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-public class HSAILHotSpotLoweringProvider implements LoweringProvider {
+public class HSAILHotSpotLoweringProvider implements HotSpotLoweringProvider {
 
-    private LoweringProvider hostLowerer;
+    private LoweringProvider host;
 
-    public HSAILHotSpotLoweringProvider(LoweringProvider hostLowerer) {
-        this.hostLowerer = hostLowerer;
+    public HSAILHotSpotLoweringProvider(LoweringProvider host) {
+        this.host = host;
     }
 
     public void lower(Node n, LoweringTool tool) {
@@ -41,11 +44,18 @@
             // TODO
             return;
         } else {
-            hostLowerer.lower(n, tool);
+            host.lower(n, tool);
         }
     }
 
     public ValueNode reconstructArrayIndex(LocationNode location) {
-        return hostLowerer.reconstructArrayIndex(location);
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+    }
+
+    public int getScalingFactor(Kind elementKind) {
+        throw GraalInternalError.unimplemented();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.hsail;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.replacements.*;
+
+/**
+ * Filters the substitutions and snippets supported by HSAIL.
+ */
+public class HSAILHotSpotReplacementsImpl extends ReplacementsImpl {
+
+    public HSAILHotSpotReplacementsImpl(Providers providers, Assumptions assumptions) {
+        super(providers, assumptions);
+    }
+
+    @Override
+    protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) {
+        // TODO decide here what methods substitutions are supported
+        return null;
+    }
+
+    @Override
+    public Class<? extends FixedWithNextNode> getMacroSubstitution(ResolvedJavaMethod method) {
+        // TODO decide here what macro substitutions are supported
+        return null;
+    }
+
+    @Override
+    public StructuredGraph getSnippet(ResolvedJavaMethod method) {
+        // TODO must work in cooperation with HSAILHotSpotLoweringProvider
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,15 +22,28 @@
  */
 package com.oracle.graal.hotspot.ptx;
 
+import static com.oracle.graal.lir.LIRValueUtil.*;
+
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.ptx.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.ptx.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
 
 /**
  * HotSpot PTX specific backend.
@@ -43,31 +56,219 @@
 
     @Override
     public boolean shouldAllocateRegisters() {
-        throw new InternalError("NYI");
+        return false;
     }
 
     @Override
     public FrameMap newFrameMap() {
-        throw new InternalError("NYI");
+        return new PTXFrameMap(getCodeCache());
+    }
+
+    class PTXFrameContext implements FrameContext {
+
+        @Override
+        public void enter(TargetMethodAssembler tasm) {
+            // codeBuffer.emitString(".address_size 32"); // PTX ISA version 2.3
+        }
+
+        @Override
+        public void leave(TargetMethodAssembler tasm) {
+        }
     }
 
     @Override
     public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) {
-        throw new InternalError("NYI");
+        // Omit the frame of the method:
+        // - has no spill slots or other slots allocated during register allocation
+        // - has no callee-saved registers
+        // - has no incoming arguments passed on the stack
+        // - has no instructions with debug info
+        FrameMap frameMap = lirGen.frameMap;
+        AbstractAssembler masm = createAssembler(frameMap);
+        PTXFrameContext frameContext = new PTXFrameContext();
+        TargetMethodAssembler tasm = new PTXTargetMethodAssembler(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
+        tasm.setFrameSize(0);
+        return tasm;
     }
 
     @Override
     protected AbstractAssembler createAssembler(FrameMap frameMap) {
-        throw new InternalError("NYI");
+        return new PTXAssembler(getTarget(), frameMap.registerConfig);
     }
 
     @Override
     public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        throw new InternalError("NYI");
+        return new PTXLIRGenerator(graph, getProviders(), frameMap, cc, lir);
+    }
+
+    private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
+        // Emit PTX kernel entry text based on PTXParameterOp
+        // instructions in the start block. Remove the instructions
+        // once kernel entry text and directives are emitted to
+        // facilitate seemless PTX code generation subsequently.
+        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
+        final String name = codeCacheOwner.getName();
+        Buffer codeBuffer = tasm.asm.codeBuffer;
+
+        // Emit initial boiler-plate directives.
+        codeBuffer.emitString(".version 3.0");
+        codeBuffer.emitString(".target sm_30");
+        codeBuffer.emitString0(".entry " + name + " (");
+        codeBuffer.emitString("");
+
+        // Get the start block
+        Block startBlock = lirGen.lir.cfg.getStartBlock();
+        // Keep a list of ParameterOp instructions to delete from the
+        // list of instructions in the block.
+        ArrayList<LIRInstruction> deleteOps = new ArrayList<>();
+
+        // Emit .param arguments to kernel entry based on ParameterOp
+        // instruction.
+        for (LIRInstruction op : lirGen.lir.lir(startBlock)) {
+            if (op instanceof PTXParameterOp) {
+                op.emitCode(tasm);
+                deleteOps.add(op);
+            }
+        }
+
+        // Delete ParameterOp instructions.
+        for (LIRInstruction op : deleteOps) {
+            lirGen.lir.lir(startBlock).remove(op);
+        }
+
+        // Start emiting body of the PTX kernel.
+        codeBuffer.emitString0(") {");
+        codeBuffer.emitString("");
+    }
+
+    // Emit .reg space declarations
+    private static void emitRegisterDecl(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
+
+        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
+
+        Buffer codeBuffer = tasm.asm.codeBuffer;
+
+        final SortedSet<Integer> signed32 = new TreeSet<>();
+        final SortedSet<Integer> signed64 = new TreeSet<>();
+        final SortedSet<Integer> unsigned64 = new TreeSet<>();
+        final SortedSet<Integer> float32 = new TreeSet<>();
+        final SortedSet<Integer> float64 = new TreeSet<>();
+
+        ValueProcedure trackRegisterKind = new ValueProcedure() {
+
+            @Override
+            public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+                if (isVariable(value)) {
+                    Variable regVal = (Variable) value;
+                    Kind regKind = regVal.getKind();
+                    switch (regKind) {
+                        case Int:
+                            // If the register was used as a wider signed type
+                            // do not add it here
+                            if (!signed64.contains(regVal.index)) {
+                                signed32.add(regVal.index);
+                            }
+                            break;
+                        case Long:
+                            // If the register was used as a narrower signed type
+                            // remove it from there and add it to wider type.
+                            if (signed32.contains(regVal.index)) {
+                                signed32.remove(regVal.index);
+                            }
+                            signed64.add(regVal.index);
+                            break;
+                        case Float:
+                            // If the register was used as a wider signed type
+                            // do not add it here
+                            if (!float64.contains(regVal.index)) {
+                                float32.add(regVal.index);
+                            }
+                            break;
+                        case Double:
+                            // If the register was used as a narrower signed type
+                            // remove it from there and add it to wider type.
+                            if (float32.contains(regVal.index)) {
+                                float32.remove(regVal.index);
+                            }
+                            float64.add(regVal.index);
+                            break;
+                        case Object:
+                            unsigned64.add(regVal.index);
+                            break;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere("unhandled register type " + value.toString());
+                    }
+                }
+                return value;
+            }
+        };
+
+        for (Block b : lirGen.lir.codeEmittingOrder()) {
+            for (LIRInstruction op : lirGen.lir.lir(b)) {
+                if (op instanceof LabelOp) {
+                    // Don't consider this as a definition
+                } else {
+                    op.forEachTemp(trackRegisterKind);
+                    op.forEachOutput(trackRegisterKind);
+                }
+            }
+        }
+
+        for (Integer i : signed32) {
+            codeBuffer.emitString(".reg .s32 %r" + i.intValue() + ";");
+        }
+        for (Integer i : signed64) {
+            codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";");
+        }
+        for (Integer i : unsigned64) {
+            codeBuffer.emitString(".reg .u64 %r" + i.intValue() + ";");
+        }
+        for (Integer i : float32) {
+            codeBuffer.emitString(".reg .f32 %r" + i.intValue() + ";");
+        }
+        for (Integer i : float64) {
+            codeBuffer.emitString(".reg .f64 %r" + i.intValue() + ";");
+        }
+        // emit predicate register declaration
+        int maxPredRegNum = ((PTXLIRGenerator) lirGen).getNextPredRegNumber();
+        if (maxPredRegNum > 0) {
+            codeBuffer.emitString(".reg .pred %p<" + maxPredRegNum + ">;");
+        }
+        codeBuffer.emitString(".reg .pred %r;");  // used for setp bool
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
+        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
+        Buffer codeBuffer = tasm.asm.codeBuffer;
+        // Emit the prologue
+        emitKernelEntry(tasm, lirGen, codeCacheOwner);
+
+        // Emit register declarations
+        try {
+            emitRegisterDecl(tasm, lirGen, codeCacheOwner);
+        } catch (GraalInternalError e) {
+            e.printStackTrace();
+            // TODO : Better error handling needs to be done once
+            // all types of parameters are handled.
+            codeBuffer.setPosition(0);
+            codeBuffer.close(false);
+            return;
+        }
+        // Emit code for the LIR
+        try {
+            lirGen.lir.emitCode(tasm);
+        } catch (GraalInternalError e) {
+            e.printStackTrace();
+            // TODO : Better error handling needs to be done once
+            // all types of parameters are handled.
+            codeBuffer.setPosition(0);
+            codeBuffer.close(false);
+            return;
+        }
+
+        // Emit the epilogue
+        codeBuffer.emitString0("}");
+        codeBuffer.emitString("");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.hotspot.ptx;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+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.ptx.*;
+
+@ServiceProvider(HotSpotBackendFactory.class)
+public class PTXHotSpotBackendFactory implements HotSpotBackendFactory {
+
+    public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend hostBackend) {
+        HotSpotProviders host = hostBackend.getProviders();
+
+        HotSpotMetaAccessProvider metaAccess = host.getMetaAccess();
+        PTXHotSpotCodeCacheProvider codeCache = new PTXHotSpotCodeCacheProvider(runtime, createTarget());
+        ConstantReflectionProvider constantReflection = host.getConstantReflection();
+        HotSpotForeignCallsProvider foreignCalls = new PTXHotSpotForeignCallsProvider();
+        HotSpotLoweringProvider lowerer = new PTXHotSpotLoweringProvider(host.getLowerer());
+        Replacements replacements = host.getReplacements();
+        HotSpotDisassemblerProvider disassembler = host.getDisassembler();
+        HotSpotSuitesProvider suites = host.getSuites();
+        HotSpotRegistersProvider registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None);
+        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
+        return new PTXHotSpotBackend(runtime, providers);
+    }
+
+    protected Architecture createArchitecture() {
+        return new PTX();
+    }
+
+    protected TargetDescription createTarget() {
+        final int stackFrameAlignment = 1;
+        final int implicitNullCheckLimit = 0;
+        final boolean inlineObjects = true;
+        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+    }
+
+    public String getArchitecture() {
+        return "PTX";
+    }
+
+    public String getGraalRuntimeName() {
+        return "basic";
+    }
+
+    @Override
+    public String toString() {
+        return getGraalRuntimeName() + ":" + getArchitecture();
+    }
+}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -28,8 +28,8 @@
 
 public class PTXHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider {
 
-    public PTXHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime) {
-        super(runtime);
+    public PTXHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) {
+        super(runtime, target);
 
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.ptx;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+
+public class PTXHotSpotForeignCallsProvider implements HotSpotForeignCallsProvider {
+
+    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public Value[] getNativeABICallerSaveRegisters() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+    }
+}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime.java	Mon Oct 21 11:07:32 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +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.hotspot.ptx;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.phases.util.*;
-import com.oracle.graal.ptx.*;
-
-/**
- * PTX specific implementation of {@link HotSpotGraalRuntime}.
- */
-public class PTXHotSpotGraalRuntime extends HotSpotGraalRuntime {
-
-    protected PTXHotSpotGraalRuntime() {
-    }
-
-    /**
-     * Called from C++ code to retrieve the singleton instance, creating it first if necessary.
-     */
-    public static HotSpotGraalRuntime makeInstance() {
-        HotSpotGraalRuntime runtime = runtime();
-        if (runtime == null) {
-            HotSpotGraalRuntimeFactory factory = findFactory("PTX");
-            if (factory != null) {
-                runtime = factory.createRuntime();
-            } else {
-                runtime = new PTXHotSpotGraalRuntime();
-            }
-            runtime.completeInitialization();
-        }
-        return runtime;
-    }
-
-    @Override
-    protected HotSpotProviders createProviders() {
-        HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(this);
-        PTXHotSpotCodeCacheProvider codeCache = new PTXHotSpotCodeCacheProvider(this);
-        HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(this);
-        HotSpotForeignCallsProvider foreignCalls = new HotSpotForeignCallsProvider(this);
-        HotSpotLoweringProvider lowerer = new PTXHotSpotLoweringProvider(this, 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, getConfig(), assumptions);
-        HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(this);
-        HotSpotSuitesProvider suites = new HotSpotSuitesProvider(this);
-        HotSpotRegistersProvider registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None);
-        return new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
-    }
-
-    protected Architecture createArchitecture() {
-        return new PTX();
-    }
-
-    @Override
-    protected TargetDescription createTarget() {
-        final int stackFrameAlignment = 16;
-        final int implicitNullCheckLimit = 4096;
-        final boolean inlineObjects = true;
-        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
-    }
-
-    @Override
-    protected HotSpotBackend createBackend() {
-        return new PTXHotSpotBackend(this, getProviders());
-    }
-
-    @Override
-    protected Value[] getNativeABICallerSaveRegisters() {
-        throw new InternalError("NYI");
-    }
-}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,18 +22,21 @@
  */
 package com.oracle.graal.hotspot.ptx;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-public class PTXHotSpotLoweringProvider extends HotSpotLoweringProvider {
+public class PTXHotSpotLoweringProvider implements HotSpotLoweringProvider {
 
-    public PTXHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) {
-        super(runtime, metaAccess, foreignCalls);
+    private final LoweringProvider host;
+
+    public PTXHotSpotLoweringProvider(LoweringProvider host) {
+        this.host = host;
     }
 
     @Override
@@ -46,7 +49,18 @@
             // So, there is no need to lower the operation.
             return;
         } else {
-            super.lower(n, tool);
+            host.lower(n, tool);
         }
     }
+
+    public ValueNode reconstructArrayIndex(LocationNode location) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+    }
+
+    public int getScalingFactor(Kind elementKind) {
+        throw GraalInternalError.unimplemented();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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.hotspot.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.sparc.*;
+
+@ServiceProvider(HotSpotBackendFactory.class)
+public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory {
+
+    protected static Architecture createArchitecture() {
+        return new SPARC();
+    }
+
+    protected TargetDescription createTarget() {
+        final int stackFrameAlignment = 16;
+        final int implicitNullCheckLimit = 4096;
+        final boolean inlineObjects = true;
+        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+    }
+
+    public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host) {
+        assert host == null;
+        TargetDescription target = createTarget();
+
+        HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
+        HotSpotCodeCacheProvider codeCache = new SPARCHotSpotCodeCacheProvider(runtime, target);
+        HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
+        Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig());
+        HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters);
+        HotSpotLoweringProvider lowerer = new SPARCHotSpotLoweringProvider(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(Register.None, Register.None, Register.None); // FIXME
+        HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers);
+
+        return new SPARCHotSpotBackend(runtime, providers);
+    }
+
+    @SuppressWarnings("unused")
+    private static Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public String getArchitecture() {
+        return "SPARC";
+    }
+
+    public String getGraalRuntimeName() {
+        return "basic";
+    }
+
+    @Override
+    public String toString() {
+        return getGraalRuntimeName() + ":" + getArchitecture();
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java	Mon Oct 21 11:07:47 2013 +0200
@@ -23,30 +23,40 @@
 package com.oracle.graal.hotspot.sparc;
 
 import static com.oracle.graal.sparc.SPARC.*;
-import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.hotspot.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stw;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.asm.*;
 
 @Opcode("CRUNTIME_CALL_EPILOGUE")
 final class SPARCHotSpotCRuntimeCallEpilogueOp extends SPARCLIRInstruction {
 
+    private final int threadLastJavaSpOffset;
+    private final int threadLastJavaPcOffset;
+    private final int threadJavaFrameAnchorFlagsOffset;
+    private final Register thread;
+
+    public SPARCHotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, Register thread) {
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.threadLastJavaPcOffset = threadLastJavaPcOffset;
+        this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset;
+        this.thread = thread;
+    }
+
     @Override
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-        Register thread = runtime().getProviders().getRegisters().getThreadRegister();
-        HotSpotVMConfig config = runtime().getConfig();
 
         // Restore the thread register when coming back from the runtime.
         new Mov(l7, thread).emit(masm);
 
         // Reset last Java frame, last Java PC and flags.
-        new Stx(g0, new SPARCAddress(thread, config.threadLastJavaSpOffset)).emit(masm);
-        new Stx(g0, new SPARCAddress(thread, config.threadLastJavaPcOffset)).emit(masm);
-        new Stw(g0, new SPARCAddress(thread, config.threadJavaFrameAnchorFlagsOffset)).emit(masm);
+        new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
+        new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm);
+        new Stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)).emit(masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Mon Oct 21 11:07:47 2013 +0200
@@ -23,30 +23,35 @@
 package com.oracle.graal.hotspot.sparc;
 
 import static com.oracle.graal.sparc.SPARC.*;
-import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Add;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.asm.*;
 
 @Opcode("CRUNTIME_CALL_PROLOGUE")
 final class SPARCHotSpotCRuntimeCallPrologueOp extends SPARCLIRInstruction {
 
+    private final int threadLastJavaSpOffset;
+    private final Register thread;
+    private final Register stackPointer;
+
+    public SPARCHotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread, Register stackPointer) {
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.thread = thread;
+        this.stackPointer = stackPointer;
+    }
+
     @Override
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-        HotSpotRegistersProvider registers = runtime().getProviders().getRegisters();
-        HotSpotVMConfig config = runtime().getConfig();
-        Register thread = registers.getThreadRegister();
-        Register stackPointer = registers.getStackPointerRegister();
 
         // Save last Java frame.
         new Add(stackPointer, new SPARCAddress(stackPointer, 0).getDisplacement(), g4).emit(masm);
-        new Stx(g4, new SPARCAddress(thread, config.threadLastJavaSpOffset)).emit(masm);
+        new Stx(g4, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
 
         // Save the thread register when calling out to the runtime.
         new Mov(thread, l7).emit(masm);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCodeCacheProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+
+public class SPARCHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider {
+
+    public SPARCHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) {
+        super(runtime, target);
+    }
+
+    @Override
+    protected RegisterConfig createRegisterConfig() {
+        throw GraalInternalError.unimplemented();
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -35,15 +35,18 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
-public class SPARCHotSpotForeignCallsProvider extends HotSpotForeignCallsProvider {
+public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider {
+
+    private final Value[] nativeABICallerSaveRegisters;
 
-    public SPARCHotSpotForeignCallsProvider(HotSpotGraalRuntime runtime) {
-        super(runtime);
+    public SPARCHotSpotForeignCallsProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, Value[] nativeABICallerSaveRegisters) {
+        super(runtime, metaAccess, codeCache);
+        this.nativeABICallerSaveRegisters = nativeABICallerSaveRegisters;
     }
 
     @Override
-    public void initialize(HotSpotProviders providers) {
-        Kind word = runtime.getTarget().wordKind;
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+        Kind word = providers.getCodeCache().getTarget().wordKind;
 
         // The calling convention for the exception handler stub is (only?) defined in
         // TemplateInterpreterGenerator::generate_throw_exception()
@@ -56,5 +59,12 @@
         CallingConvention incomingExceptionCc = new CallingConvention(0, ILLEGAL, incomingException, incomingExceptionPc);
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
+
+        super.initialize(providers, config);
+    }
+
+    @Override
+    public Value[] getNativeABICallerSaveRegisters() {
+        return nativeABICallerSaveRegisters;
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Mon Oct 21 11:07:32 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +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.hotspot.sparc;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.sparc.*;
-
-/**
- * SPARC specific implementation of {@link HotSpotGraalRuntime}.
- */
-final class SPARCHotSpotGraalRuntime extends HotSpotGraalRuntime {
-
-    private SPARCHotSpotGraalRuntime() {
-    }
-
-    /**
-     * Called from C++ code to retrieve the singleton instance, creating it first if necessary.
-     */
-    public static HotSpotGraalRuntime makeInstance() {
-        HotSpotGraalRuntime runtime = runtime();
-        if (runtime == null) {
-            runtime = new SPARCHotSpotGraalRuntime();
-            runtime.completeInitialization();
-        }
-        return runtime;
-    }
-
-    @Override
-    protected HotSpotProviders createProviders() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    protected static Architecture createArchitecture() {
-        return new SPARC();
-    }
-
-    @Override
-    protected TargetDescription createTarget() {
-        final int stackFrameAlignment = 16;
-        final int implicitNullCheckLimit = 4096;
-        final boolean inlineObjects = true;
-        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
-    }
-
-    @Override
-    protected HotSpotBackend createBackend() {
-        return new SPARCHotSpotBackend(this, getProviders());
-    }
-
-    @Override
-    protected Value[] getNativeABICallerSaveRegisters() {
-        throw GraalInternalError.unimplemented();
-    }
-}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,15 +22,19 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
-import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Jmpl;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Lduw;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Movcc;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -44,11 +48,15 @@
     @Use(REG) AllocatableValue handlerInCallerPc;
     @Use(REG) AllocatableValue exception;
     @Use(REG) AllocatableValue exceptionPc;
+    private final Register thread;
+    private final int isMethodHandleReturnOffset;
 
-    SPARCHotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc) {
+    SPARCHotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc, int isMethodHandleReturnOffset, Register thread) {
         this.handlerInCallerPc = handlerInCallerPc;
         this.exception = exception;
         this.exceptionPc = exceptionPc;
+        this.isMethodHandleReturnOffset = isMethodHandleReturnOffset;
+        this.thread = thread;
     }
 
     @Override
@@ -56,8 +64,6 @@
         leaveFrame(tasm);
 
         // Restore SP from L7 if the exception PC is a method handle call site.
-        Register thread = runtime().getProviders().getRegisters().getThreadRegister();
-        int isMethodHandleReturnOffset = runtime().getConfig().threadIsMethodHandleReturnOffset;
         SPARCAddress dst = new SPARCAddress(thread, isMethodHandleReturnOffset);
         new Lduw(dst, o7).emit(masm);
         new Cmp(o7, o7).emit(masm);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Oct 21 11:07:47 2013 +0200
@@ -100,9 +100,12 @@
 
         if (linkage.canDeoptimize()) {
             assert info != null;
-            append(new SPARCHotSpotCRuntimeCallPrologueOp());
+            HotSpotRegistersProvider registers = getProviders().getRegisters();
+            Register thread = registers.getThreadRegister();
+            Register stackPointer = registers.getStackPointerRegister();
+            append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset, thread, stackPointer));
             result = super.emitForeignCall(linkage, info, args);
-            append(new SPARCHotSpotCRuntimeCallEpilogueOp());
+            append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset, config.threadLastJavaPcOffset, config.threadJavaFrameAnchorFlagsOffset, thread));
         } else {
             result = super.emitForeignCall(linkage, null, args);
         }
@@ -223,7 +226,8 @@
         RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1);
         emitMove(exceptionFixed, operand(exception));
         emitMove(exceptionPcFixed, operand(exceptionPc));
-        SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed);
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, config.threadIsMethodHandleReturnOffset, thread);
         append(op);
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
-public class SPARCHotSpotLoweringProvider extends HotSpotLoweringProvider {
+public class SPARCHotSpotLoweringProvider extends HotSpotHostLoweringProvider {
 
     public SPARCHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) {
         super(runtime, metaAccess, foreignCalls);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Oct 21 11:07:47 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,8 +205,8 @@
         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 CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, getProviders(), backend, getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
+        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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Oct 21 11:07:47 2013 +0200
@@ -42,7 +42,6 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.phases.util.*;
 
 public final class CompilationTask implements Runnable {
 
@@ -58,9 +57,8 @@
         Queued, Running
     }
 
-    private final HotSpotGraalRuntime runtime;
+    private final HotSpotBackend backend;
     private final PhasePlan plan;
-    private final SuitesProvider suitesProvider;
     private final OptimisticOptimizations optimisticOpts;
     private final HotSpotResolvedJavaMethod method;
     private final int entryBCI;
@@ -69,15 +67,14 @@
 
     private StructuredGraph graph;
 
-    public static CompilationTask create(HotSpotGraalRuntime runtime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id) {
-        return new CompilationTask(runtime, plan, optimisticOpts, method, entryBCI, id);
+    public static CompilationTask create(HotSpotBackend backend, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id) {
+        return new CompilationTask(backend, plan, optimisticOpts, method, entryBCI, id);
     }
 
-    private CompilationTask(HotSpotGraalRuntime runtime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id) {
+    private CompilationTask(HotSpotBackend backend, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id) {
         assert id >= 0;
-        this.runtime = runtime;
+        this.backend = backend;
         this.plan = plan;
-        this.suitesProvider = runtime.getCapability(SuitesProvider.class);
         this.method = method;
         this.optimisticOpts = optimisticOpts;
         this.entryBCI = entryBCI;
@@ -143,8 +140,12 @@
 
                     @Override
                     public CompilationResult call() throws Exception {
-                        runtime.evictDeoptedGraphs();
-                        Providers providers = runtime.getProviders();
+                        GraphCache graphCache = backend.getRuntime().getGraphCache();
+                        if (graphCache != null) {
+                            graphCache.removeStaleGraphs();
+                        }
+
+                        HotSpotProviders providers = backend.getProviders();
                         Replacements replacements = providers.getReplacements();
                         graph = replacements.getMethodSubstitution(method);
                         if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) {
@@ -155,8 +156,9 @@
                         }
                         InliningUtil.InlinedBytecodes.add(method.getCodeSize());
                         CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
-                        return GraalCompiler.compileGraph(graph, cc, method, providers, runtime.getBackend(), runtime.getTarget(), runtime.getCache(), plan, optimisticOpts,
-                                        method.getSpeculationLog(), suitesProvider.getDefaultSuites(), new CompilationResult());
+                        Suites suites = providers.getSuites().getDefaultSuites();
+                        return GraalCompiler.compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, plan, optimisticOpts, method.getSpeculationLog(), suites,
+                                        new CompilationResult());
                     }
                 });
             } finally {
@@ -212,7 +214,7 @@
     }
 
     private void installMethod(final CompilationResult compResult) {
-        final HotSpotCodeCacheProvider codeCache = runtime.getProviders().getCodeCache();
+        final HotSpotCodeCacheProvider codeCache = backend.getProviders().getCodeCache();
         Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), codeCache, method}, new Runnable() {
 
             @Override
@@ -222,7 +224,7 @@
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
                 if (Debug.isLogEnabled()) {
-                    Debug.log("%s", runtime.getProviders().getDisassembler().disassemble(installedCode));
+                    Debug.log("%s", backend.getProviders().getDisassembler().disassemble(installedCode));
                 }
             }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Oct 21 11:07:47 2013 +0200
@@ -182,7 +182,7 @@
                     }
 
                     // Are we compiling this class?
-                    HotSpotMetaAccessProvider metaAccess = runtime.getProviders().getMetaAccess();
+                    HotSpotMetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess();
                     if (classFileCounter >= startAt) {
                         TTY.println("CompileTheWorld (%d) : %s", classFileCounter, className);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Oct 21 11:07:47 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();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackendFactory.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot;
+
+import com.oracle.graal.hotspot.HotSpotGraalRuntime.Options;
+
+public interface HotSpotBackendFactory {
+
+    HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host);
+
+    /**
+     * Gets the CPU architecture of this backend.
+     */
+    String getArchitecture();
+
+    /**
+     * Gets the name of the {@link Options#GraalRuntime GraalRuntime} in which the backend created
+     * by this factory should be used.
+     */
+    String getGraalRuntimeName();
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Mon Oct 21 11:07:47 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.word.*;
 
@@ -119,13 +120,13 @@
      *            re-executed.
      * @param killedLocations the memory locations killed by the call
      */
-    public static HotSpotForeignCallLinkage create(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type outgoingCcType, Type incomingCcType, Transition transition,
-                    boolean reexecutable, LocationIdentity... killedLocations) {
-        CallingConvention outgoingCc = createCallingConvention(descriptor, outgoingCcType);
-        CallingConvention incomingCc = incomingCcType == null ? null : createCallingConvention(descriptor, incomingCcType);
+    public static HotSpotForeignCallLinkage create(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, HotSpotForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor,
+                    long address, RegisterEffect effect, Type outgoingCcType, Type incomingCcType, Transition transition, boolean reexecutable, LocationIdentity... killedLocations) {
+        CallingConvention outgoingCc = createCallingConvention(metaAccess, codeCache, descriptor, outgoingCcType);
+        CallingConvention incomingCc = incomingCcType == null ? null : createCallingConvention(metaAccess, codeCache, descriptor, incomingCcType);
         HotSpotForeignCallLinkage linkage = new HotSpotForeignCallLinkage(descriptor, address, effect, transition, outgoingCc, incomingCc, reexecutable, killedLocations);
         if (outgoingCcType == Type.NativeCall) {
-            linkage.temporaries = runtime().getNativeABICallerSaveRegisters();
+            linkage.temporaries = foreignCalls.getNativeABICallerSaveRegisters();
         }
         return linkage;
     }
@@ -133,23 +134,22 @@
     /**
      * Gets a calling convention for a given descriptor and call type.
      */
-    public static CallingConvention createCallingConvention(ForeignCallDescriptor descriptor, Type ccType) {
+    public static CallingConvention createCallingConvention(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ForeignCallDescriptor descriptor, Type ccType) {
         assert ccType != null;
-        MetaAccessProvider metaAccess = runtime().getProviders().getMetaAccess();
         Class<?>[] argumentTypes = descriptor.getArgumentTypes();
         JavaType[] parameterTypes = new JavaType[argumentTypes.length];
         for (int i = 0; i < parameterTypes.length; ++i) {
             parameterTypes[i] = asJavaType(argumentTypes[i], metaAccess);
         }
-        TargetDescription target = runtime().getTarget();
+        TargetDescription target = codeCache.getTarget();
         JavaType returnType = asJavaType(descriptor.getResultType(), metaAccess);
-        RegisterConfig regConfig = runtime().getProviders().getCodeCache().getRegisterConfig();
+        RegisterConfig regConfig = codeCache.getRegisterConfig();
         return regConfig.getCallingConvention(ccType, returnType, parameterTypes, target, false);
     }
 
     private static JavaType asJavaType(Class type, MetaAccessProvider metaAccess) {
         if (WordBase.class.isAssignableFrom(type)) {
-            return metaAccess.lookupJavaType(wordKind().toJavaClass());
+            return metaAccess.lookupJavaType(getHostWordKind().toJavaClass());
         } else {
             return metaAccess.lookupJavaType(type);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Oct 21 11:07:47 2013 +0200
@@ -38,24 +38,25 @@
 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}.
- * 
- * The platform specific subclass is created by a call from the C++ HotSpot code.
  */
-public abstract class HotSpotGraalRuntime implements GraalRuntime {
+public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider {
 
-    private static final HotSpotGraalRuntime instance = (HotSpotGraalRuntime) Graal.getRuntime();
+    private static final HotSpotGraalRuntime instance = new HotSpotGraalRuntime();
+    static {
+        instance.completeInitialization();
+    }
 
     /**
      * Gets the singleton {@link HotSpotGraalRuntime} object.
      */
     public static HotSpotGraalRuntime runtime() {
+        assert instance != null;
         return instance;
     }
 
@@ -86,7 +87,7 @@
         this.compilerToVm = toVM;
     }
 
-    // Options must not be directly declared in HotSpotGraalRuntime - see VerifyHotSpotOptionsPhase
+    // Options must not be directly declared in HotSpotGraalRuntime - see VerifyOptionsPhase
     static class Options {
 
         // @formatter:off
@@ -95,19 +96,19 @@
         // @formatter:on
     }
 
-    protected static HotSpotGraalRuntimeFactory findFactory(String architecture) {
-        HotSpotGraalRuntimeFactory basic = null;
-        HotSpotGraalRuntimeFactory selected = null;
-        HotSpotGraalRuntimeFactory nonBasic = null;
+    private static HotSpotBackendFactory findFactory(String architecture) {
+        HotSpotBackendFactory basic = null;
+        HotSpotBackendFactory selected = null;
+        HotSpotBackendFactory nonBasic = null;
         int nonBasicCount = 0;
 
-        for (HotSpotGraalRuntimeFactory factory : ServiceLoader.loadInstalled(HotSpotGraalRuntimeFactory.class)) {
-            if (factory.getArchitecture().equals(architecture)) {
-                if (factory.getName().equals(GraalRuntime.getValue())) {
+        for (HotSpotBackendFactory factory : ServiceLoader.loadInstalled(HotSpotBackendFactory.class)) {
+            if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
+                if (factory.getGraalRuntimeName().equals(GraalRuntime.getValue())) {
                     assert selected == null;
                     selected = factory;
                 }
-                if (factory.getName().equals("basic")) {
+                if (factory.getGraalRuntimeName().equals("basic")) {
                     assert basic == null;
                     basic = factory;
                 } else {
@@ -133,21 +134,18 @@
         }
     }
 
-    private static Kind wordKind;
-
     /**
-     * Gets the kind of a word value.
+     * Gets the kind of a word value on the {@linkplain #getHostBackend() host} backend.
      */
-    public static Kind wordKind() {
-        assert wordKind != null;
-        return wordKind;
+    public static Kind getHostWordKind() {
+        return instance.getHostBackend().getTarget().wordKind;
     }
 
     /**
      * Reads a word value from a given address.
      */
     public static long unsafeReadWord(long address) {
-        if (wordKind == Kind.Long) {
+        if (getHostWordKind() == Kind.Long) {
             return unsafe.getLong(address);
         }
         return unsafe.getInt(address);
@@ -164,7 +162,7 @@
      * Reads a word value from a given object.
      */
     public static long unsafeReadWord(Object object, long offset) {
-        if (wordKind == Kind.Long) {
+        if (getHostWordKind() == Kind.Long) {
             return unsafe.getLong(object, offset);
         }
         return unsafe.getInt(object, offset);
@@ -174,21 +172,17 @@
     protected/* final */CompilerToGPU compilerToGpu;
     protected/* final */VMToCompiler vmToCompiler;
 
-    protected final HotSpotProviders providers;
-
-    protected final TargetDescription target;
-
     private HotSpotRuntimeInterpreterInterface runtimeInterpreterInterface;
     private volatile HotSpotGraphCache cache;
 
     protected final HotSpotVMConfig config;
-    private final HotSpotBackend backend;
+    private final HotSpotBackend hostBackend;
 
-    protected HotSpotGraalRuntime() {
+    private final Map<Class<? extends Architecture>, HotSpotBackend> backends = new HashMap<>();
+
+    private HotSpotGraalRuntime() {
         CompilerToVM toVM = new CompilerToVMImpl();
         CompilerToGPU toGPU = new CompilerToGPUImpl();
-
-        // initialize VmToCompiler
         VMToCompiler toCompiler = new VMToCompilerImpl(this);
 
         compilerToVm = toVM;
@@ -213,18 +207,64 @@
             printConfig(config);
         }
 
-        target = createTarget();
-        providers = createProviders();
-        assert wordKind == null || wordKind.equals(target.wordKind);
-        wordKind = target.wordKind;
+        String hostArchitecture = getHostArchitectureName();
+        hostBackend = registerBackend(findFactory(hostArchitecture).createBackend(this, null));
 
-        backend = createBackend();
+        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);
+            }
+            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 getHostArchitectureName() {
+        String arch = System.getProperty("os.arch");
+        switch (arch) {
+            case "x86_64":
+                // This is what Mac OS X reports;
+                arch = "amd64";
+                break;
+        }
+        return arch;
+    }
+
+    public static final String GRAAL_GPU_ISALIST_PROPERTY_NAME = "graal.gpu.isalist";
+
+    /**
+     * 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 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 static String[] getGPUArchitectureNames() {
+        String gpuList = System.getProperty(GRAAL_GPU_ISALIST_PROPERTY_NAME);
+        if (gpuList != null && !gpuList.isEmpty()) {
+            String[] gpus = gpuList.split("[,:]");
+            return gpus;
+        }
+        return new String[0];
+    }
+
     private static void printConfig(HotSpotVMConfig config) {
         Field[] fields = config.getClass().getDeclaredFields();
         Map<String, Field> sortedFields = new TreeMap<>();
@@ -240,26 +280,15 @@
         }
     }
 
-    protected abstract HotSpotProviders createProviders();
-
-    protected abstract TargetDescription createTarget();
-
-    protected abstract HotSpotBackend createBackend();
-
-    /**
-     * Gets the registers that must be saved across a foreign call into the runtime.
-     */
-    protected abstract Value[] getNativeABICallerSaveRegisters();
-
     public HotSpotVMConfig getConfig() {
         return config;
     }
 
     public TargetDescription getTarget() {
-        return target;
+        return hostBackend.getTarget();
     }
 
-    public HotSpotGraphCache getCache() {
+    public HotSpotGraphCache getGraphCache() {
         return cache;
     }
 
@@ -309,26 +338,13 @@
 
     public HotSpotRuntimeInterpreterInterface getRuntimeInterpreterInterface() {
         if (runtimeInterpreterInterface == null) {
-            runtimeInterpreterInterface = new HotSpotRuntimeInterpreterInterface(providers.getMetaAccess());
+            runtimeInterpreterInterface = new HotSpotRuntimeInterpreterInterface(getHostProviders().getMetaAccess());
         }
         return runtimeInterpreterInterface;
     }
 
-    public HotSpotProviders getProviders() {
-        return providers;
-    }
-
-    public void evictDeoptedGraphs() {
-        if (cache != null) {
-            long[] deoptedGraphs = getCompilerToVM().getDeoptedLeafGraphIds();
-            if (deoptedGraphs != null) {
-                if (deoptedGraphs.length == 0) {
-                    cache.clear();
-                } else {
-                    cache.removeGraphs(deoptedGraphs);
-                }
-            }
-        }
+    public HotSpotProviders getHostProviders() {
+        return getHostBackend().getProviders();
     }
 
     @Override
@@ -339,44 +355,23 @@
     @SuppressWarnings("unchecked")
     @Override
     public <T> T getCapability(Class<T> clazz) {
-        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) getBackend();
+        if (clazz == RuntimeProvider.class) {
+            return (T) this;
         }
         return null;
     }
 
-    public HotSpotBackend getBackend() {
-        return backend;
+    public HotSpotBackend getHostBackend() {
+        return hostBackend;
+    }
+
+    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/HotSpotGraalRuntimeFactory.java	Mon Oct 21 11:07:32 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot;
-
-public interface HotSpotGraalRuntimeFactory {
-
-    HotSpotGraalRuntime createRuntime();
-
-    String getArchitecture();
-
-    String getName();
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java	Mon Oct 21 11:07:47 2013 +0200
@@ -48,8 +48,7 @@
     int availableProcessors();
 
     /**
-     * Attempts to generate and return a bound function to the
-     * loaded method kernel on the GPU.
+     * 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
      * @return the value of the bound kernel in GPU space.
@@ -58,7 +57,5 @@
 
     Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
-
-    Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ,
-                                        Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    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/CompilerToGPUImpl.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java	Mon Oct 21 11:07:47 2013 +0200
@@ -26,7 +26,6 @@
 import com.oracle.graal.api.code.InvalidInstalledCodeException;
 import com.oracle.graal.hotspot.meta.HotSpotInstalledCode;
 
-
 /**
  * Entries into the HotSpot GPU interface from Java code.
  */
@@ -40,10 +39,7 @@
 
     public native int availableProcessors();
 
-    public native Object executeExternalMethodVarargs(Object[] args,
-                                                      HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    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;
+    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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Oct 21 11:07:47 2013 +0200
@@ -128,7 +128,7 @@
 
         bootstrapRunning = bootstrapEnabled;
 
-        HotSpotVMConfig config = runtime.getConfig();
+        final HotSpotVMConfig config = runtime.getConfig();
         long offset = config.graalMirrorInClassOffset;
         initMirror(typeBoolean, offset);
         initMirror(typeChar, offset);
@@ -180,9 +180,8 @@
             }
         }
 
-        final HotSpotProviders providers = runtime.getProviders();
-        final MetaAccessProvider metaAccess = providers.getMetaAccess();
-        assert VerifyOptionsPhase.checkOptions(metaAccess, providers.getForeignCalls());
+        final HotSpotProviders hostProviders = runtime.getHostProviders();
+        assert VerifyOptionsPhase.checkOptions(hostProviders.getMetaAccess(), hostProviders.getForeignCalls());
 
         // Install intrinsics.
         if (Intrinsify.getValue()) {
@@ -190,15 +189,35 @@
 
                 @Override
                 public void run() {
+
+                    List<LoweringProvider> initializedLowerers = new ArrayList<>();
+                    List<ForeignCallsProvider> initializedForeignCalls = new ArrayList<>();
+
+                    for (Map.Entry<?, HotSpotBackend> e : runtime.getBackends().entrySet()) {
+                        HotSpotBackend backend = e.getValue();
+                        HotSpotProviders providers = backend.getProviders();
+
+                        HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls();
+                        if (!initializedForeignCalls.contains(foreignCalls)) {
+                            initializedForeignCalls.add(foreignCalls);
+                            foreignCalls.initialize(providers, config);
+                        }
+                        HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
+                        if (!initializedLowerers.contains(lowerer)) {
+                            initializedLowerers.add(lowerer);
+                            initializeLowerer(providers, lowerer);
+                        }
+                    }
+                }
+
+                private void initializeLowerer(HotSpotProviders providers, HotSpotLoweringProvider lowerer) {
                     final Replacements replacements = providers.getReplacements();
-                    ServiceLoader<ReplacementsProvider> serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class);
+                    ServiceLoader<ReplacementsProvider> sl = ServiceLoader.loadInstalled(ReplacementsProvider.class);
                     TargetDescription target = providers.getCodeCache().getTarget();
-                    HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
-                    for (ReplacementsProvider provider : serviceLoader) {
-                        provider.registerReplacements(metaAccess, lowerer, replacements, target);
+                    for (ReplacementsProvider replacementsProvider : sl) {
+                        replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, replacements, target);
                     }
-                    providers.getForeignCalls().initialize(providers);
-                    lowerer.initialize();
+                    lowerer.initialize(providers, config);
                     if (BootstrapReplacements.getValue()) {
                         for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
                             replacements.getMacroSubstitution(method);
@@ -326,6 +345,14 @@
                     TTY.print(".");
                     TTY.flush();
                 }
+
+                // Are we out of time?
+                final int timedBootstrap = TimedBootstrap.getValue();
+                if (timedBootstrap != -1) {
+                    if ((System.currentTimeMillis() - startTime) > timedBootstrap) {
+                        break;
+                    }
+                }
             }
         } while ((System.currentTimeMillis() - startTime) <= TimedBootstrap.getValue());
 
@@ -334,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");
@@ -350,7 +377,7 @@
     private MetricRateInPhase inlinedBytecodesPerSecond;
 
     private void enqueue(Method m) throws Throwable {
-        JavaMethod javaMethod = runtime.getProviders().getMetaAccess().lookupJavaMethod(m);
+        JavaMethod javaMethod = runtime.getHostProviders().getMetaAccess().lookupJavaMethod(m);
         assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) : javaMethod;
         compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, false);
     }
@@ -557,7 +584,8 @@
 
                 final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method);
                 int id = compileTaskIds.incrementAndGet();
-                CompilationTask task = CompilationTask.create(runtime, createPhasePlan(optimisticOpts, osrCompilation), optimisticOpts, method, entryBCI, id);
+                HotSpotBackend backend = runtime.getHostBackend();
+                CompilationTask task = CompilationTask.create(backend, createPhasePlan(backend.getProviders(), optimisticOpts, osrCompilation), optimisticOpts, method, entryBCI, id);
 
                 if (blocking) {
                     task.runCompilation();
@@ -690,10 +718,10 @@
         return new LocalImpl(name, type, holder, bciStart, bciEnd, slot);
     }
 
-    public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts, boolean onStackReplacement) {
+    public PhasePlan createPhasePlan(HotSpotProviders providers, OptimisticOptimizations optimisticOpts, boolean onStackReplacement) {
         PhasePlan phasePlan = new PhasePlan();
-        MetaAccessProvider metaAccess = runtime.getProviders().getMetaAccess();
-        ForeignCallsProvider foreignCalls = runtime.getProviders().getForeignCalls();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        ForeignCallsProvider foreignCalls = providers.getForeignCalls();
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getDefault(), optimisticOpts));
         if (onStackReplacement) {
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -44,10 +44,12 @@
 public abstract class HotSpotCodeCacheProvider implements CodeCacheProvider {
 
     protected final HotSpotGraalRuntime runtime;
+    protected final TargetDescription target;
     protected final RegisterConfig regConfig;
 
-    public HotSpotCodeCacheProvider(HotSpotGraalRuntime runtime) {
+    public HotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) {
         this.runtime = runtime;
+        this.target = target;
         regConfig = createRegisterConfig();
     }
 
@@ -57,7 +59,6 @@
     public String disassemble(CompilationResult compResult, InstalledCode installedCode) {
         byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode();
         long start = installedCode == null ? 0L : installedCode.getStart();
-        TargetDescription target = runtime.getTarget();
         HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
         if (compResult != null) {
             HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
@@ -191,7 +192,7 @@
 
     @Override
     public TargetDescription getTarget() {
-        return runtime.getTarget();
+        return target;
     }
 
     public String disassemble(InstalledCode code) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,202 +22,19 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.code.CallingConvention.Type.*;
-import static com.oracle.graal.api.meta.LocationIdentity.*;
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
-import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
-import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
-import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
-import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
-import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
-import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
-import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
-import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
-import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*;
-import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*;
-import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*;
-import static com.oracle.graal.hotspot.stubs.NewArrayStub.*;
-import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
-import static com.oracle.graal.hotspot.stubs.StubUtil.*;
-import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*;
-import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
-import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
-import static com.oracle.graal.replacements.Log.*;
-import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
-
-import java.util.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect;
-import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition;
-import com.oracle.graal.hotspot.stubs.*;
-import com.oracle.graal.word.*;
 
 /**
- * HotSpot implementation of {@link ForeignCallsProvider}.
+ * HotSpot extension of {@link ForeignCallsProvider}.
  */
-public class HotSpotForeignCallsProvider implements ForeignCallsProvider {
-
-    public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class);
-    public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class);
-    public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class);
-    public static final ForeignCallDescriptor LOAD_AND_CLEAR_EXCEPTION = new ForeignCallDescriptor("load_and_clear_exception", Object.class, Word.class);
-
-    protected final HotSpotGraalRuntime runtime;
-
-    private final Map<ForeignCallDescriptor, HotSpotForeignCallLinkage> foreignCalls = new HashMap<>();
-
-    public HotSpotForeignCallsProvider(HotSpotGraalRuntime runtime) {
-        this.runtime = runtime;
-    }
-
-    /**
-     * Registers the linkage for a foreign call.
-     */
-    protected HotSpotForeignCallLinkage register(HotSpotForeignCallLinkage linkage) {
-        assert !foreignCalls.containsKey(linkage.getDescriptor()) : "already registered linkage for " + linkage.getDescriptor();
-        foreignCalls.put(linkage.getDescriptor(), linkage);
-        return linkage;
-    }
+public interface HotSpotForeignCallsProvider extends ForeignCallsProvider {
 
-    /**
-     * Creates and registers the details for linking a foreign call to a {@link Stub}.
-     * 
-     * @param descriptor the signature of the call to the stub
-     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
-     *            effects. Deoptimization will not return to a point before a stub call that cannot
-     *            be re-executed.
-     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
-     * @param killedLocations the memory locations killed by the stub call
-     */
-    protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, Transition transition, LocationIdentity... killedLocations) {
-        return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations));
-    }
-
-    /**
-     * Creates and registers the linkage for a foreign call.
-     * 
-     * @param descriptor the signature of the foreign call
-     * @param address the address of the code to call
-     * @param outgoingCcType outgoing (caller) calling convention type
-     * @param effect specifies if the call destroys or preserves all registers (apart from
-     *            temporaries which are always destroyed)
-     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
-     * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
-     *            side effects. Deoptimization will not return to a point before a foreign call that
-     *            cannot be re-executed.
-     * @param killedLocations the memory locations killed by the foreign call
-     */
-    protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type outgoingCcType, RegisterEffect effect, Transition transition,
-                    boolean reexecutable, LocationIdentity... killedLocations) {
-        Class<?> resultType = descriptor.getResultType();
-        assert transition == LEAF || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor;
-        return register(HotSpotForeignCallLinkage.create(descriptor, address, effect, outgoingCcType, null, transition, reexecutable, killedLocations));
-    }
-
-    private static void link(Stub stub) {
-        stub.getLinkage().setCompiledStub(stub);
-    }
+    void initialize(HotSpotProviders providers, HotSpotVMConfig config);
 
     /**
-     * Creates a {@linkplain ForeignCallStub stub} for a foreign call.
-     * 
-     * @param descriptor the signature of the call to the stub
-     * @param address the address of the foreign code to call
-     * @param prependThread true if the JavaThread value for the current thread is to be prepended
-     *            to the arguments for the call to {@code address}
-     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
-     * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
-     *            side effects. Deoptimization will not return to a point before a foreign call that
-     *            cannot be re-executed.
-     * @param killedLocations the memory locations killed by the foreign call
+     * Gets the registers that must be saved across a foreign call into the runtime.
      */
-    private void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable,
-                    LocationIdentity... killedLocations) {
-        ForeignCallStub stub = new ForeignCallStub(providers, address, descriptor, prependThread, transition, reexecutable, killedLocations);
-        HotSpotForeignCallLinkage linkage = stub.getLinkage();
-        HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage();
-        linkage.setCompiledStub(stub);
-        register(linkage);
-        register(targetLinkage);
-    }
-
-    public static final boolean PREPEND_THREAD = true;
-    public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD;
-
-    public static final boolean REEXECUTABLE = true;
-    public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE;
-
-    public static final LocationIdentity[] NO_LOCATIONS = {};
-
-    public void initialize(HotSpotProviders providers) {
-        HotSpotVMConfig c = runtime.getConfig();
-        TargetDescription target = providers.getCodeCache().getTarget();
-
-        registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
-
-        registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
-
-        registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
-        registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
-        registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
-        registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
-        registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
-
-        link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
-        link(new NewArrayStub(providers, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, INIT_LOCATION)));
-        link(new ExceptionHandlerStub(providers, target, foreignCalls.get(EXCEPTION_HANDLER)));
-        link(new UnwindExceptionToCallerStub(providers, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
-        link(new VerifyOopStub(providers, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF, NO_LOCATIONS)));
-
-        linkForeignCall(providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, MARK_WORD_LOCATION);
-        linkForeignCall(providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
-        linkForeignCall(providers, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
-        linkForeignCall(providers, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
-        linkForeignCall(providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
-        linkForeignCall(providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
-        linkForeignCall(providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION);
-        linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION);
-        linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
-        linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF, NOT_REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
-    }
-
-    public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
-        HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor);
-        assert foreignCalls != null : descriptor;
-        callTarget.finalizeAddress(runtime.getBackend());
-        return callTarget;
-    }
-
-    @Override
-    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
-        return foreignCalls.get(descriptor).isReexecutable();
-    }
-
-    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
-        return foreignCalls.get(descriptor).canDeoptimize();
-    }
-
-    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
-        return foreignCalls.get(descriptor).getKilledLocations();
-    }
+    Value[] getNativeABICallerSaveRegisters();
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Mon Oct 21 11:07:47 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);
+            }
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.meta;
+
+import static com.oracle.graal.api.code.CallingConvention.Type.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
+import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
+import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
+import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
+import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
+import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
+import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*;
+import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*;
+import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*;
+import static com.oracle.graal.hotspot.stubs.NewArrayStub.*;
+import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
+import static com.oracle.graal.hotspot.stubs.StubUtil.*;
+import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*;
+import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
+import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
+import static com.oracle.graal.replacements.Log.*;
+import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect;
+import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.word.*;
+
+/**
+ * HotSpot implementation of {@link ForeignCallsProvider}.
+ */
+public abstract class HotSpotHostForeignCallsProvider implements HotSpotForeignCallsProvider {
+
+    public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class);
+    public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class);
+    public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class);
+    public static final ForeignCallDescriptor LOAD_AND_CLEAR_EXCEPTION = new ForeignCallDescriptor("load_and_clear_exception", Object.class, Word.class);
+
+    protected final HotSpotGraalRuntime runtime;
+
+    private final Map<ForeignCallDescriptor, HotSpotForeignCallLinkage> foreignCalls = new HashMap<>();
+    private final MetaAccessProvider metaAccess;
+    private final CodeCacheProvider codeCache;
+
+    public HotSpotHostForeignCallsProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache) {
+        this.runtime = runtime;
+        this.metaAccess = metaAccess;
+        this.codeCache = codeCache;
+    }
+
+    /**
+     * Registers the linkage for a foreign call.
+     */
+    protected HotSpotForeignCallLinkage register(HotSpotForeignCallLinkage linkage) {
+        assert !foreignCalls.containsKey(linkage.getDescriptor()) : "already registered linkage for " + linkage.getDescriptor();
+        foreignCalls.put(linkage.getDescriptor(), linkage);
+        return linkage;
+    }
+
+    /**
+     * Creates and registers the details for linking a foreign call to a {@link Stub}.
+     * 
+     * @param descriptor the signature of the call to the stub
+     * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side
+     *            effects. Deoptimization will not return to a point before a stub call that cannot
+     *            be re-executed.
+     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
+     * @param killedLocations the memory locations killed by the stub call
+     */
+    protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, Transition transition, LocationIdentity... killedLocations) {
+        return register(HotSpotForeignCallLinkage.create(metaAccess, codeCache, this, descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations));
+    }
+
+    /**
+     * Creates and registers the linkage for a foreign call.
+     * 
+     * @param descriptor the signature of the foreign call
+     * @param address the address of the code to call
+     * @param outgoingCcType outgoing (caller) calling convention type
+     * @param effect specifies if the call destroys or preserves all registers (apart from
+     *            temporaries which are always destroyed)
+     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
+     * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
+     *            side effects. Deoptimization will not return to a point before a foreign call that
+     *            cannot be re-executed.
+     * @param killedLocations the memory locations killed by the foreign call
+     */
+    protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type outgoingCcType, RegisterEffect effect, Transition transition,
+                    boolean reexecutable, LocationIdentity... killedLocations) {
+        Class<?> resultType = descriptor.getResultType();
+        assert transition == LEAF || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor;
+        return register(HotSpotForeignCallLinkage.create(metaAccess, codeCache, this, descriptor, address, effect, outgoingCcType, null, transition, reexecutable, killedLocations));
+    }
+
+    private static void link(Stub stub) {
+        stub.getLinkage().setCompiledStub(stub);
+    }
+
+    /**
+     * Creates a {@linkplain ForeignCallStub stub} for a foreign call.
+     * 
+     * @param descriptor the signature of the call to the stub
+     * @param address the address of the foreign code to call
+     * @param prependThread true if the JavaThread value for the current thread is to be prepended
+     *            to the arguments for the call to {@code address}
+     * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call
+     * @param reexecutable specifies if the foreign call can be re-executed without (meaningful)
+     *            side effects. Deoptimization will not return to a point before a foreign call that
+     *            cannot be re-executed.
+     * @param killedLocations the memory locations killed by the foreign call
+     */
+    private void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable,
+                    LocationIdentity... killedLocations) {
+        ForeignCallStub stub = new ForeignCallStub(providers, address, descriptor, prependThread, transition, reexecutable, killedLocations);
+        HotSpotForeignCallLinkage linkage = stub.getLinkage();
+        HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage();
+        linkage.setCompiledStub(stub);
+        register(linkage);
+        register(targetLinkage);
+    }
+
+    public static final boolean PREPEND_THREAD = true;
+    public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD;
+
+    public static final boolean REEXECUTABLE = true;
+    public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE;
+
+    public static final LocationIdentity[] NO_LOCATIONS = {};
+
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig c) {
+        TargetDescription target = providers.getCodeCache().getTarget();
+
+        registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+
+        registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+
+        registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
+
+        link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
+        link(new NewArrayStub(providers, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, INIT_LOCATION)));
+        link(new ExceptionHandlerStub(providers, target, foreignCalls.get(EXCEPTION_HANDLER)));
+        link(new UnwindExceptionToCallerStub(providers, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
+        link(new VerifyOopStub(providers, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF, NO_LOCATIONS)));
+
+        linkForeignCall(providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, MARK_WORD_LOCATION);
+        linkForeignCall(providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(providers, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(providers, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION);
+        linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION);
+        linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF, NOT_REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
+    }
+
+    public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
+        HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor);
+        assert foreignCalls != null : descriptor;
+        callTarget.finalizeAddress(runtime.getHostBackend());
+        return callTarget;
+    }
+
+    @Override
+    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
+        return foreignCalls.get(descriptor).isReexecutable();
+    }
+
+    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
+        return foreignCalls.get(descriptor).canDeoptimize();
+    }
+
+    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
+        return foreignCalls.get(descriptor).getKilledLocations();
+    }
+
+    /**
+     * Gets the registers that must be saved across a foreign call into the runtime.
+     */
+    public abstract Value[] getNativeABICallerSaveRegisters();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostLoweringProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,681 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.meta;
+
+import static com.oracle.graal.api.code.MemoryBarriers.*;
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.meta.HotSpotHostForeignCallsProvider.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
+import static com.oracle.graal.nodes.java.ArrayLengthNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.debug.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.debug.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.replacements.*;
+
+/**
+ * HotSpot implementation of {@link LoweringProvider}.
+ */
+public class HotSpotHostLoweringProvider implements HotSpotLoweringProvider {
+
+    protected final HotSpotGraalRuntime runtime;
+    protected final MetaAccessProvider metaAccess;
+    protected final ForeignCallsProvider foreignCalls;
+
+    private CheckCastDynamicSnippets.Templates checkcastDynamicSnippets;
+    private InstanceOfSnippets.Templates instanceofSnippets;
+    private NewObjectSnippets.Templates newObjectSnippets;
+    private MonitorSnippets.Templates monitorSnippets;
+    protected WriteBarrierSnippets.Templates writeBarrierSnippets;
+    private BoxingSnippets.Templates boxingSnippets;
+    private LoadExceptionObjectSnippets.Templates exceptionObjectSnippets;
+    private UnsafeLoadSnippets.Templates unsafeLoadSnippets;
+
+    public HotSpotHostLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) {
+        this.runtime = runtime;
+        this.metaAccess = metaAccess;
+        this.foreignCalls = foreignCalls;
+    }
+
+    public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
+        Replacements r = providers.getReplacements();
+
+        r.registerSubstitutions(ObjectSubstitutions.class);
+        r.registerSubstitutions(SystemSubstitutions.class);
+        r.registerSubstitutions(ThreadSubstitutions.class);
+        r.registerSubstitutions(UnsafeSubstitutions.class);
+        r.registerSubstitutions(ClassSubstitutions.class);
+        r.registerSubstitutions(AESCryptSubstitutions.class);
+        r.registerSubstitutions(CipherBlockChainingSubstitutions.class);
+        r.registerSubstitutions(CRC32Substitutions.class);
+        r.registerSubstitutions(ReflectionSubstitutions.class);
+
+        TargetDescription target = providers.getCodeCache().getTarget();
+        checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, target);
+        instanceofSnippets = new InstanceOfSnippets.Templates(providers, target);
+        newObjectSnippets = new NewObjectSnippets.Templates(providers, target);
+        monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking);
+        writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target);
+        boxingSnippets = new BoxingSnippets.Templates(providers, target);
+        exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target);
+        unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target);
+
+        r.registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target));
+    }
+
+    @Override
+    public void lower(Node n, LoweringTool tool) {
+        HotSpotVMConfig config = runtime.getConfig();
+        StructuredGraph graph = (StructuredGraph) n.graph();
+
+        Kind wordKind = runtime.getTarget().wordKind;
+        if (n instanceof ArrayLengthNode) {
+            ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
+            ValueNode array = arrayLengthNode.array();
+            ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(),
+                            BarrierType.NONE, false));
+            tool.createNullCheckGuard(arrayLengthRead, array);
+            graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
+        } else if (n instanceof Invoke) {
+            Invoke invoke = (Invoke) n;
+            if (invoke.callTarget() instanceof MethodCallTargetNode) {
+
+                MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
+                NodeInputList<ValueNode> parameters = callTarget.arguments();
+                ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
+                GuardingNode receiverNullCheck = null;
+                if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !ObjectStamp.isObjectNonNull(receiver)) {
+                    receiverNullCheck = tool.createNullCheckGuard(invoke, receiver);
+                }
+                JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
+
+                LoweredCallTargetNode loweredCallTarget = null;
+                if (callTarget.invokeKind() == InvokeKind.Virtual && InlineVTableStubs.getValue() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) {
+
+                    HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
+                    if (!hsMethod.getDeclaringClass().isInterface()) {
+                        if (hsMethod.isInVirtualMethodTable()) {
+                            int vtableEntryOffset = hsMethod.vtableEntryOffset();
+                            assert vtableEntryOffset > 0;
+                            FloatingReadNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck);
+
+                            ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod);
+                            // We use LocationNode.ANY_LOCATION for the reads that access the
+                            // compiled code entry as HotSpot does not guarantee they are final
+                            // values.
+                            ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
+                                            StampFactory.forKind(wordKind), BarrierType.NONE, false));
+
+                            loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
+                                            CallingConvention.Type.JavaCall));
+
+                            graph.addBeforeFixed(invoke.asNode(), metaspaceMethod);
+                            graph.addAfterFixed(metaspaceMethod, compiledEntry);
+                        }
+                    }
+                }
+
+                if (loweredCallTarget == null) {
+                    loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
+                                    callTarget.invokeKind()));
+                }
+                callTarget.replaceAndDelete(loweredCallTarget);
+            }
+        } else if (n instanceof LoadFieldNode) {
+            LoadFieldNode loadField = (LoadFieldNode) n;
+            HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
+            ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object();
+            assert loadField.kind() != Kind.Illegal;
+            BarrierType barrierType = getFieldLoadBarrierType(field);
+            ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object)));
+            graph.replaceFixedWithFixed(loadField, memoryRead);
+            tool.createNullCheckGuard(memoryRead, object);
+
+            if (loadField.isVolatile()) {
+                MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ));
+                graph.addBeforeFixed(memoryRead, preMembar);
+                MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ));
+                graph.addAfterFixed(memoryRead, postMembar);
+            }
+        } else if (n instanceof StoreFieldNode) {
+            StoreFieldNode storeField = (StoreFieldNode) n;
+            HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
+            ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object();
+            BarrierType barrierType = getFieldStoreBarrierType(storeField);
+            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field, false), barrierType, storeField.field().getKind() == Kind.Object));
+            tool.createNullCheckGuard(memoryWrite, object);
+            memoryWrite.setStateAfter(storeField.stateAfter());
+            graph.replaceFixedWithFixed(storeField, memoryWrite);
+            FixedWithNextNode last = memoryWrite;
+            FixedWithNextNode first = memoryWrite;
+
+            if (storeField.isVolatile()) {
+                MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
+                graph.addBeforeFixed(first, preMembar);
+                MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
+                graph.addAfterFixed(last, postMembar);
+            }
+        } else if (n instanceof CompareAndSwapNode) {
+            // Separate out GC barrier semantics
+            CompareAndSwapNode cas = (CompareAndSwapNode) n;
+            LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
+            LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, cas.expected(), cas.newValue(), getCompareAndSwapBarrier(cas),
+                            cas.expected().kind() == Kind.Object));
+            atomicNode.setStateAfter(cas.stateAfter());
+            graph.replaceFixedWithFixed(cas, atomicNode);
+        } else if (n instanceof LoadIndexedNode) {
+            LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
+            GuardingNode boundsCheck = createBoundsCheck(loadIndexed, tool);
+            Kind elementKind = loadIndexed.elementKind();
+            LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false);
+            ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object));
+            memoryRead.setGuard(boundsCheck);
+            graph.replaceFixedWithFixed(loadIndexed, memoryRead);
+        } else if (n instanceof StoreIndexedNode) {
+            StoreIndexedNode storeIndexed = (StoreIndexedNode) n;
+            GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool);
+            Kind elementKind = storeIndexed.elementKind();
+            LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false);
+            ValueNode value = storeIndexed.value();
+            ValueNode array = storeIndexed.array();
+
+            CheckCastNode checkcastNode = null;
+            CheckCastDynamicNode checkcastDynamicNode = null;
+            if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) {
+                // Store check!
+                ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array);
+                if (arrayType != null && ObjectStamp.isExactType(array)) {
+                    ResolvedJavaType elementType = arrayType.getComponentType();
+                    if (!MetaUtil.isJavaLangObject(elementType)) {
+                        checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true));
+                        graph.addBeforeFixed(storeIndexed, checkcastNode);
+                        value = checkcastNode;
+                    }
+                } else {
+                    FloatingReadNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck);
+                    LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph);
+                    /*
+                     * Anchor the read of the element klass to the cfg, because it is only valid
+                     * when arrayClass is an object class, which might not be the case in other
+                     * parts of the compiled method.
+                     */
+                    FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed)));
+                    checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true));
+                    graph.addBeforeFixed(storeIndexed, checkcastDynamicNode);
+                    value = checkcastDynamicNode;
+                }
+            }
+            BarrierType barrierType = getArrayStoreBarrierType(storeIndexed);
+            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object));
+            memoryWrite.setGuard(boundsCheck);
+            memoryWrite.setStateAfter(storeIndexed.stateAfter());
+            graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
+
+            // Lower the associated checkcast node.
+            if (checkcastNode != null) {
+                checkcastNode.lower(tool);
+            } else if (checkcastDynamicNode != null) {
+                checkcastDynamicSnippets.lower(checkcastDynamicNode);
+            }
+        } else if (n instanceof UnsafeLoadNode) {
+            UnsafeLoadNode load = (UnsafeLoadNode) n;
+            if (load.getGuardingCondition() != null) {
+                boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
+                ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition()));
+                LocationNode location = createLocation(load);
+                ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), valueAnchorNode, BarrierType.NONE, compressible));
+                load.replaceAtUsages(memoryRead);
+                graph.replaceFixedWithFixed(load, valueAnchorNode);
+                graph.addAfterFixed(valueAnchorNode, memoryRead);
+            } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) {
+                assert load.kind() != Kind.Illegal;
+                boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
+                if (addReadBarrier(load)) {
+                    unsafeLoadSnippets.lower(load, tool);
+                } else {
+                    LocationNode location = createLocation(load);
+                    ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible));
+                    // An unsafe read must not float outside its block otherwise
+                    // it may float above an explicit null check on its object.
+                    memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
+                    graph.replaceFixedWithFixed(load, memoryRead);
+                }
+            }
+        } else if (n instanceof UnsafeStoreNode) {
+            UnsafeStoreNode store = (UnsafeStoreNode) n;
+            LocationNode location = createLocation(store);
+            ValueNode object = store.object();
+            BarrierType barrierType = getUnsafeStoreBarrierType(store);
+            WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object));
+            write.setStateAfter(store.stateAfter());
+            graph.replaceFixedWithFixed(store, write);
+        } else if (n instanceof LoadHubNode) {
+            LoadHubNode loadHub = (LoadHubNode) n;
+            assert loadHub.kind() == wordKind;
+            ValueNode object = loadHub.object();
+            GuardingNode guard = loadHub.getGuard();
+            FloatingReadNode hub = createReadHub(graph, wordKind, object, guard);
+            graph.replaceFloating(loadHub, hub);
+        } else if (n instanceof LoadMethodNode) {
+            LoadMethodNode loadMethodNode = (LoadMethodNode) n;
+            ResolvedJavaMethod method = loadMethodNode.getMethod();
+            ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, loadMethodNode.getHub(), method);
+            graph.replaceFixed(loadMethodNode, metaspaceMethod);
+        } else if (n instanceof StoreHubNode) {
+            StoreHubNode storeHub = (StoreHubNode) n;
+            WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue());
+            graph.replaceFixed(storeHub, hub);
+        } else if (n instanceof CommitAllocationNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                CommitAllocationNode commit = (CommitAllocationNode) n;
+
+                ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
+                    int entryCount = virtual.entryCount();
+
+                    FixedWithNextNode newObject;
+                    if (virtual instanceof VirtualInstanceNode) {
+                        newObject = graph.add(new NewInstanceNode(virtual.type(), true));
+                    } else {
+                        ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType();
+                        newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true));
+                    }
+                    graph.addBeforeFixed(commit, newObject);
+                    allocations[objIndex] = newObject;
+                }
+                int valuePos = 0;
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
+                    int entryCount = virtual.entryCount();
+
+                    ValueNode newObject = allocations[objIndex];
+                    if (virtual instanceof VirtualInstanceNode) {
+                        VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
+                        for (int i = 0; i < entryCount; i++) {
+                            ValueNode value = commit.getValues().get(valuePos++);
+                            if (value instanceof VirtualObjectNode) {
+                                value = allocations[commit.getVirtualObjects().indexOf(value)];
+                            }
+                            if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
+                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true),
+                                                (virtualInstance.field(i).getKind() == Kind.Object && !deferInitBarrier(newObject)) ? BarrierType.IMPRECISE : BarrierType.NONE,
+                                                virtualInstance.field(i).getKind() == Kind.Object);
+                                graph.addBeforeFixed(commit, graph.add(write));
+                            }
+                        }
+
+                    } else {
+                        VirtualArrayNode array = (VirtualArrayNode) virtual;
+                        ResolvedJavaType element = array.componentType();
+                        for (int i = 0; i < entryCount; i++) {
+                            ValueNode value = commit.getValues().get(valuePos++);
+                            if (value instanceof VirtualObjectNode) {
+                                int indexOf = commit.getVirtualObjects().indexOf(value);
+                                assert indexOf != -1 : commit + " " + value;
+                                value = allocations[indexOf];
+                            }
+                            if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
+                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph), true),
+                                                (value.kind() == Kind.Object && !deferInitBarrier(newObject)) ? BarrierType.PRECISE : BarrierType.NONE, value.kind() == Kind.Object);
+                                graph.addBeforeFixed(commit, graph.add(write));
+                            }
+                        }
+                    }
+                }
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
+                    allocations[objIndex] = anchor;
+                    graph.addBeforeFixed(commit, anchor);
+                }
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    for (int lockDepth : commit.getLocks().get(objIndex)) {
+                        MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth));
+                        graph.addBeforeFixed(commit, enter);
+                        enter.lower(tool);
+                    }
+                }
+                for (Node usage : commit.usages().snapshot()) {
+                    AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
+                    int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
+                    graph.replaceFloating(addObject, allocations[index]);
+                }
+                graph.removeFixed(commit);
+            }
+        } else if (n instanceof OSRStartNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                OSRStartNode osrStart = (OSRStartNode) n;
+                StartNode newStart = graph.add(new StartNode());
+                LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind)));
+                ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer));
+                migrationEnd.setStateAfter(osrStart.stateAfter());
+
+                newStart.setNext(migrationEnd);
+                FixedNode next = osrStart.next();
+                osrStart.setNext(null);
+                migrationEnd.setNext(next);
+                graph.setStart(newStart);
+
+                // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
+                int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
+                for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
+                    int size = FrameStateBuilder.stackSlots(osrLocal.kind());
+                    int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
+                    IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1);
+                    ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false));
+                    osrLocal.replaceAndDelete(load);
+                    graph.addBeforeFixed(migrationEnd, load);
+                }
+                osrStart.replaceAtUsages(newStart);
+                osrStart.safeDelete();
+            }
+        } else if (n instanceof DynamicCounterNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
+                BenchmarkCounters.lower((DynamicCounterNode) n, runtime.getHostProviders().getRegisters(), runtime.getConfig(), wordKind);
+            }
+        } else if (n instanceof CheckCastDynamicNode) {
+            checkcastDynamicSnippets.lower((CheckCastDynamicNode) n);
+        } else if (n instanceof InstanceOfNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                instanceofSnippets.lower((InstanceOfNode) n, tool);
+            }
+        } else if (n instanceof InstanceOfDynamicNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
+            }
+        } else if (n instanceof NewInstanceNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
+                newObjectSnippets.lower((NewInstanceNode) n);
+            }
+        } else if (n instanceof NewArrayNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
+                newObjectSnippets.lower((NewArrayNode) n);
+            }
+        } else if (n instanceof DynamicNewArrayNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
+                newObjectSnippets.lower((DynamicNewArrayNode) n);
+            }
+        } else if (n instanceof MonitorEnterNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                monitorSnippets.lower((MonitorEnterNode) n, tool);
+            }
+        } else if (n instanceof MonitorExitNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                monitorSnippets.lower((MonitorExitNode) n, tool);
+            }
+        } else if (n instanceof G1PreWriteBarrier) {
+            writeBarrierSnippets.lower((G1PreWriteBarrier) n, tool);
+        } else if (n instanceof G1PostWriteBarrier) {
+            writeBarrierSnippets.lower((G1PostWriteBarrier) n, tool);
+        } else if (n instanceof G1ReferentFieldReadBarrier) {
+            writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, tool);
+        } else if (n instanceof SerialWriteBarrier) {
+            writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
+        } else if (n instanceof SerialArrayRangeWriteBarrier) {
+            writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
+        } else if (n instanceof G1ArrayRangePreWriteBarrier) {
+            writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, tool);
+        } else if (n instanceof G1ArrayRangePostWriteBarrier) {
+            writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool);
+        } else if (n instanceof NewMultiArrayNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
+                newObjectSnippets.lower((NewMultiArrayNode) n);
+            }
+        } else if (n instanceof LoadExceptionObjectNode) {
+            exceptionObjectSnippets.lower((LoadExceptionObjectNode) n);
+        } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
+            // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
+            // zero and the MIN_VALUE / -1 cases.
+        } else if (n instanceof BoxNode) {
+            boxingSnippets.lower((BoxNode) n, tool);
+        } else if (n instanceof UnboxNode) {
+            boxingSnippets.lower((UnboxNode) n, tool);
+        } else {
+            assert false : "Node implementing Lowerable not handled: " + n;
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static LocationNode createLocation(UnsafeAccessNode access) {
+        ValueNode offset = access.offset();
+        if (offset.isConstant()) {
+            long offsetValue = offset.asConstant().asLong();
+            return ConstantLocationNode.create(access.getLocationIdentity(), access.accessKind(), offsetValue, access.graph());
+        }
+
+        long displacement = 0;
+        int indexScaling = 1;
+        if (offset instanceof IntegerAddNode) {
+            IntegerAddNode integerAddNode = (IntegerAddNode) offset;
+            if (integerAddNode.y() instanceof ConstantNode) {
+                displacement = integerAddNode.y().asConstant().asLong();
+                offset = integerAddNode.x();
+            }
+        }
+
+        if (offset instanceof LeftShiftNode) {
+            LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
+            if (leftShiftNode.y() instanceof ConstantNode) {
+                long shift = leftShiftNode.y().asConstant().asLong();
+                if (shift >= 1 && shift <= 3) {
+                    if (shift == 1) {
+                        indexScaling = 2;
+                    } else if (shift == 2) {
+                        indexScaling = 4;
+                    } else {
+                        indexScaling = 8;
+                    }
+                    offset = leftShiftNode.x();
+                }
+            }
+        }
+
+        return IndexedLocationNode.create(access.getLocationIdentity(), access.accessKind(), displacement, offset, access.graph(), indexScaling);
+    }
+
+    private static boolean addReadBarrier(UnsafeLoadNode load) {
+        if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object &&
+                        !ObjectStamp.isObjectAlwaysNull(load.object())) {
+            ResolvedJavaType type = ObjectStamp.typeOrNull(load.object());
+            if (type != null && !type.isArray()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static ReadNode createReadVirtualMethod(StructuredGraph graph, Kind wordKind, ValueNode hub, ResolvedJavaMethod method) {
+        HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
+        assert !hsMethod.getDeclaringClass().isInterface();
+        assert hsMethod.isInVirtualMethodTable();
+
+        int vtableEntryOffset = hsMethod.vtableEntryOffset();
+        assert vtableEntryOffset > 0;
+        // We use LocationNode.ANY_LOCATION for the reads that access the vtable
+        // entry as HotSpot does not guarantee that this is a final value.
+        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE, false));
+        return metaspaceMethod;
+    }
+
+    private FloatingReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) {
+        HotSpotVMConfig config = runtime.getConfig();
+        LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
+        assert !object.isConstant() || object.asConstant().isNull();
+        return graph.unique(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind), guard, BarrierType.NONE, config.useCompressedClassPointers));
+    }
+
+    private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) {
+        HotSpotVMConfig config = runtime.getConfig();
+        LocationNode location = ConstantLocationNode.create(HUB_LOCATION, wordKind, config.hubOffset, graph);
+        assert !object.isConstant() || object.asConstant().isNull();
+        return graph.add(new WriteNode(object, value, location, BarrierType.NONE, config.useCompressedClassPointers));
+    }
+
+    private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) {
+        BarrierType barrierType = BarrierType.NONE;
+        if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) {
+            barrierType = BarrierType.PRECISE;
+        }
+        return barrierType;
+    }
+
+    private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) {
+        BarrierType barrierType = BarrierType.NONE;
+        if (storeField.field().getKind() == Kind.Object && !deferInitBarrier(storeField.object())) {
+            barrierType = BarrierType.IMPRECISE;
+        }
+        return barrierType;
+    }
+
+    private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) {
+        BarrierType barrierType = BarrierType.NONE;
+        if (store.elementKind() == Kind.Object && !deferInitBarrier(store.array())) {
+            barrierType = BarrierType.PRECISE;
+        }
+        return barrierType;
+    }
+
+    private static boolean deferInitBarrier(ValueNode object) {
+        return useDeferredInitBarriers() && (object instanceof NewInstanceNode || object instanceof NewArrayNode);
+    }
+
+    private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) {
+        BarrierType barrierType = BarrierType.NONE;
+        if (store.value().kind() == Kind.Object) {
+            ResolvedJavaType type = ObjectStamp.typeOrNull(store.object());
+            if (type != null && !type.isArray()) {
+                barrierType = BarrierType.IMPRECISE;
+            } else {
+                barrierType = BarrierType.PRECISE;
+            }
+        }
+        return barrierType;
+    }
+
+    private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
+        BarrierType barrierType = BarrierType.NONE;
+        if (cas.expected().kind() == Kind.Object) {
+            ResolvedJavaType type = ObjectStamp.typeOrNull(cas.object());
+            if (type != null && !type.isArray()) {
+                barrierType = BarrierType.IMPRECISE;
+            } else {
+                barrierType = BarrierType.PRECISE;
+            }
+        }
+        return barrierType;
+    }
+
+    protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) {
+        LocationIdentity loc = initialization ? INIT_LOCATION : field;
+        return ConstantLocationNode.create(loc, field.getKind(), field.offset(), graph);
+    }
+
+    public int getScalingFactor(Kind kind) {
+        if (useCompressedOops() && kind == Kind.Object) {
+            return this.runtime.getTarget().arch.getSizeInBytes(Kind.Int);
+        } else {
+            return this.runtime.getTarget().arch.getSizeInBytes(kind);
+        }
+    }
+
+    protected IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) {
+        LocationIdentity loc = initialization ? INIT_LOCATION : NamedLocationIdentity.getArrayLocation(elementKind);
+        int scale = getScalingFactor(elementKind);
+        return IndexedLocationNode.create(loc, elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
+    }
+
+    @Override
+    public ValueNode reconstructArrayIndex(LocationNode location) {
+        Kind elementKind = location.getValueKind();
+        assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind));
+
+        long base;
+        ValueNode index;
+        int scale = getScalingFactor(elementKind);
+
+        if (location instanceof ConstantLocationNode) {
+            base = ((ConstantLocationNode) location).getDisplacement();
+            index = null;
+        } else if (location instanceof IndexedLocationNode) {
+            IndexedLocationNode indexedLocation = (IndexedLocationNode) location;
+            assert indexedLocation.getIndexScaling() == scale;
+            base = indexedLocation.getDisplacement();
+            index = indexedLocation.getIndex();
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        base -= getArrayBaseOffset(elementKind);
+        assert base >= 0 && base % scale == 0;
+
+        base /= scale;
+        assert NumUtil.isInt(base);
+
+        if (index == null) {
+            return ConstantNode.forInt((int) base, location.graph());
+        } else {
+            if (base == 0) {
+                return index;
+            } else {
+                return IntegerArithmeticNode.add(ConstantNode.forInt((int) base, location.graph()), index);
+            }
+        }
+    }
+
+    private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
+        StructuredGraph g = n.graph();
+        ValueNode array = n.array();
+        ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection());
+        if (arrayLength == null) {
+            Stamp stamp = StampFactory.positiveInt();
+            ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false));
+            g.addBeforeFixed(n, readArrayLength);
+            tool.createNullCheckGuard(readArrayLength, array);
+            arrayLength = readArrayLength;
+        }
+
+        return tool.createGuard(g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile);
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,661 +22,16 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.code.MemoryBarriers.*;
-import static com.oracle.graal.api.meta.DeoptimizationAction.*;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
-import static com.oracle.graal.api.meta.LocationIdentity.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProvider.*;
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
-import static com.oracle.graal.nodes.java.ArrayLengthNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.debug.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.java.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.BarrierType;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.debug.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.replacements.*;
 
 /**
- * HotSpot implementation of {@link LoweringProvider}.
+ * HotSpot extension of {@link LoweringProvider}.
  */
-public class HotSpotLoweringProvider implements LoweringProvider {
-
-    protected final HotSpotGraalRuntime runtime;
-    protected final MetaAccessProvider metaAccess;
-    protected final ForeignCallsProvider foreignCalls;
-
-    private CheckCastDynamicSnippets.Templates checkcastDynamicSnippets;
-    private InstanceOfSnippets.Templates instanceofSnippets;
-    private NewObjectSnippets.Templates newObjectSnippets;
-    private MonitorSnippets.Templates monitorSnippets;
-    protected WriteBarrierSnippets.Templates writeBarrierSnippets;
-    private BoxingSnippets.Templates boxingSnippets;
-    private LoadExceptionObjectSnippets.Templates exceptionObjectSnippets;
-    private UnsafeLoadSnippets.Templates unsafeLoadSnippets;
-
-    public HotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) {
-        this.runtime = runtime;
-        this.metaAccess = metaAccess;
-        this.foreignCalls = foreignCalls;
-    }
-
-    public void initialize() {
-        HotSpotVMConfig c = runtime.getConfig();
-        HotSpotProviders providers = runtime.getProviders();
-        Replacements r = providers.getReplacements();
-
-        r.registerSubstitutions(ObjectSubstitutions.class);
-        r.registerSubstitutions(SystemSubstitutions.class);
-        r.registerSubstitutions(ThreadSubstitutions.class);
-        r.registerSubstitutions(UnsafeSubstitutions.class);
-        r.registerSubstitutions(ClassSubstitutions.class);
-        r.registerSubstitutions(AESCryptSubstitutions.class);
-        r.registerSubstitutions(CipherBlockChainingSubstitutions.class);
-        r.registerSubstitutions(CRC32Substitutions.class);
-        r.registerSubstitutions(ReflectionSubstitutions.class);
-
-        checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, runtime.getTarget());
-        instanceofSnippets = new InstanceOfSnippets.Templates(providers, runtime.getTarget());
-        newObjectSnippets = new NewObjectSnippets.Templates(providers, runtime.getTarget());
-        monitorSnippets = new MonitorSnippets.Templates(providers, runtime.getTarget(), c.useFastLocking);
-        writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, runtime.getTarget());
-        boxingSnippets = new BoxingSnippets.Templates(providers, runtime.getTarget());
-        exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, runtime.getTarget());
-        unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, runtime.getTarget());
-
-        r.registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, runtime.getTarget()));
-    }
-
-    @Override
-    public void lower(Node n, LoweringTool tool) {
-        HotSpotVMConfig config = runtime.getConfig();
-        StructuredGraph graph = (StructuredGraph) n.graph();
-
-        Kind wordKind = runtime.getTarget().wordKind;
-        if (n instanceof ArrayLengthNode) {
-            ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
-            ValueNode array = arrayLengthNode.array();
-            ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(),
-                            BarrierType.NONE, false));
-            tool.createNullCheckGuard(arrayLengthRead, array);
-            graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
-        } else if (n instanceof Invoke) {
-            Invoke invoke = (Invoke) n;
-            if (invoke.callTarget() instanceof MethodCallTargetNode) {
-
-                MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
-                NodeInputList<ValueNode> parameters = callTarget.arguments();
-                ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
-                GuardingNode receiverNullCheck = null;
-                if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !ObjectStamp.isObjectNonNull(receiver)) {
-                    receiverNullCheck = tool.createNullCheckGuard(invoke, receiver);
-                }
-                JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
-
-                LoweredCallTargetNode loweredCallTarget = null;
-                if (callTarget.invokeKind() == InvokeKind.Virtual && InlineVTableStubs.getValue() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) {
-
-                    HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
-                    if (!hsMethod.getDeclaringClass().isInterface()) {
-                        if (hsMethod.isInVirtualMethodTable()) {
-                            int vtableEntryOffset = hsMethod.vtableEntryOffset();
-                            assert vtableEntryOffset > 0;
-                            FloatingReadNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck);
-
-                            ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod);
-                            // We use LocationNode.ANY_LOCATION for the reads that access the
-                            // compiled code entry as HotSpot does not guarantee they are final
-                            // values.
-                            ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
-                                            StampFactory.forKind(wordKind), BarrierType.NONE, false));
-
-                            loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
-                                            CallingConvention.Type.JavaCall));
-
-                            graph.addBeforeFixed(invoke.asNode(), metaspaceMethod);
-                            graph.addAfterFixed(metaspaceMethod, compiledEntry);
-                        }
-                    }
-                }
-
-                if (loweredCallTarget == null) {
-                    loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
-                                    callTarget.invokeKind()));
-                }
-                callTarget.replaceAndDelete(loweredCallTarget);
-            }
-        } else if (n instanceof LoadFieldNode) {
-            LoadFieldNode loadField = (LoadFieldNode) n;
-            HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
-            ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object();
-            assert loadField.kind() != Kind.Illegal;
-            BarrierType barrierType = getFieldLoadBarrierType(field);
-            ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object)));
-            graph.replaceFixedWithFixed(loadField, memoryRead);
-            tool.createNullCheckGuard(memoryRead, object);
-
-            if (loadField.isVolatile()) {
-                MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ));
-                graph.addBeforeFixed(memoryRead, preMembar);
-                MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ));
-                graph.addAfterFixed(memoryRead, postMembar);
-            }
-        } else if (n instanceof StoreFieldNode) {
-            StoreFieldNode storeField = (StoreFieldNode) n;
-            HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
-            ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object();
-            BarrierType barrierType = getFieldStoreBarrierType(storeField);
-            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field, false), barrierType, storeField.field().getKind() == Kind.Object));
-            tool.createNullCheckGuard(memoryWrite, object);
-            memoryWrite.setStateAfter(storeField.stateAfter());
-            graph.replaceFixedWithFixed(storeField, memoryWrite);
-            FixedWithNextNode last = memoryWrite;
-            FixedWithNextNode first = memoryWrite;
-
-            if (storeField.isVolatile()) {
-                MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
-                graph.addBeforeFixed(first, preMembar);
-                MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
-                graph.addAfterFixed(last, postMembar);
-            }
-        } else if (n instanceof CompareAndSwapNode) {
-            // Separate out GC barrier semantics
-            CompareAndSwapNode cas = (CompareAndSwapNode) n;
-            LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
-            LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, cas.expected(), cas.newValue(), getCompareAndSwapBarrier(cas),
-                            cas.expected().kind() == Kind.Object));
-            atomicNode.setStateAfter(cas.stateAfter());
-            graph.replaceFixedWithFixed(cas, atomicNode);
-        } else if (n instanceof LoadIndexedNode) {
-            LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
-            GuardingNode boundsCheck = createBoundsCheck(loadIndexed, tool);
-            Kind elementKind = loadIndexed.elementKind();
-            LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false);
-            ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object));
-            memoryRead.setGuard(boundsCheck);
-            graph.replaceFixedWithFixed(loadIndexed, memoryRead);
-        } else if (n instanceof StoreIndexedNode) {
-            StoreIndexedNode storeIndexed = (StoreIndexedNode) n;
-            GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool);
-            Kind elementKind = storeIndexed.elementKind();
-            LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false);
-            ValueNode value = storeIndexed.value();
-            ValueNode array = storeIndexed.array();
-
-            CheckCastNode checkcastNode = null;
-            CheckCastDynamicNode checkcastDynamicNode = null;
-            if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) {
-                // Store check!
-                ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array);
-                if (arrayType != null && ObjectStamp.isExactType(array)) {
-                    ResolvedJavaType elementType = arrayType.getComponentType();
-                    if (!MetaUtil.isJavaLangObject(elementType)) {
-                        checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true));
-                        graph.addBeforeFixed(storeIndexed, checkcastNode);
-                        value = checkcastNode;
-                    }
-                } else {
-                    FloatingReadNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck);
-                    LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph);
-                    /*
-                     * Anchor the read of the element klass to the cfg, because it is only valid
-                     * when arrayClass is an object class, which might not be the case in other
-                     * parts of the compiled method.
-                     */
-                    FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed)));
-                    checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true));
-                    graph.addBeforeFixed(storeIndexed, checkcastDynamicNode);
-                    value = checkcastDynamicNode;
-                }
-            }
-            BarrierType barrierType = getArrayStoreBarrierType(storeIndexed);
-            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object));
-            memoryWrite.setGuard(boundsCheck);
-            memoryWrite.setStateAfter(storeIndexed.stateAfter());
-            graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
-
-            // Lower the associated checkcast node.
-            if (checkcastNode != null) {
-                checkcastNode.lower(tool);
-            } else if (checkcastDynamicNode != null) {
-                checkcastDynamicSnippets.lower(checkcastDynamicNode);
-            }
-        } else if (n instanceof UnsafeLoadNode) {
-            UnsafeLoadNode load = (UnsafeLoadNode) n;
-            if (load.getGuardingCondition() != null) {
-                boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
-                ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition()));
-                LocationNode location = createLocation(load);
-                ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), valueAnchorNode, BarrierType.NONE, compressible));
-                load.replaceAtUsages(memoryRead);
-                graph.replaceFixedWithFixed(load, valueAnchorNode);
-                graph.addAfterFixed(valueAnchorNode, memoryRead);
-            } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) {
-                assert load.kind() != Kind.Illegal;
-                boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
-                if (addReadBarrier(load)) {
-                    unsafeLoadSnippets.lower(load, tool);
-                } else {
-                    LocationNode location = createLocation(load);
-                    ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible));
-                    // An unsafe read must not float outside its block otherwise
-                    // it may float above an explicit null check on its object.
-                    memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
-                    graph.replaceFixedWithFixed(load, memoryRead);
-                }
-            }
-        } else if (n instanceof UnsafeStoreNode) {
-            UnsafeStoreNode store = (UnsafeStoreNode) n;
-            LocationNode location = createLocation(store);
-            ValueNode object = store.object();
-            BarrierType barrierType = getUnsafeStoreBarrierType(store);
-            WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object));
-            write.setStateAfter(store.stateAfter());
-            graph.replaceFixedWithFixed(store, write);
-        } else if (n instanceof LoadHubNode) {
-            LoadHubNode loadHub = (LoadHubNode) n;
-            assert loadHub.kind() == wordKind;
-            ValueNode object = loadHub.object();
-            GuardingNode guard = loadHub.getGuard();
-            FloatingReadNode hub = createReadHub(graph, wordKind, object, guard);
-            graph.replaceFloating(loadHub, hub);
-        } else if (n instanceof LoadMethodNode) {
-            LoadMethodNode loadMethodNode = (LoadMethodNode) n;
-            ResolvedJavaMethod method = loadMethodNode.getMethod();
-            ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, loadMethodNode.getHub(), method);
-            graph.replaceFixed(loadMethodNode, metaspaceMethod);
-        } else if (n instanceof StoreHubNode) {
-            StoreHubNode storeHub = (StoreHubNode) n;
-            WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue());
-            graph.replaceFixed(storeHub, hub);
-        } else if (n instanceof CommitAllocationNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-                CommitAllocationNode commit = (CommitAllocationNode) n;
-
-                ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
-                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                    VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
-                    int entryCount = virtual.entryCount();
-
-                    FixedWithNextNode newObject;
-                    if (virtual instanceof VirtualInstanceNode) {
-                        newObject = graph.add(new NewInstanceNode(virtual.type(), true));
-                    } else {
-                        ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType();
-                        newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true));
-                    }
-                    graph.addBeforeFixed(commit, newObject);
-                    allocations[objIndex] = newObject;
-                }
-                int valuePos = 0;
-                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                    VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
-                    int entryCount = virtual.entryCount();
-
-                    ValueNode newObject = allocations[objIndex];
-                    if (virtual instanceof VirtualInstanceNode) {
-                        VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
-                        for (int i = 0; i < entryCount; i++) {
-                            ValueNode value = commit.getValues().get(valuePos++);
-                            if (value instanceof VirtualObjectNode) {
-                                value = allocations[commit.getVirtualObjects().indexOf(value)];
-                            }
-                            if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true),
-                                                (virtualInstance.field(i).getKind() == Kind.Object && !deferInitBarrier(newObject)) ? BarrierType.IMPRECISE : BarrierType.NONE,
-                                                virtualInstance.field(i).getKind() == Kind.Object);
-                                graph.addBeforeFixed(commit, graph.add(write));
-                            }
-                        }
+public interface HotSpotLoweringProvider extends LoweringProvider {
 
-                    } else {
-                        VirtualArrayNode array = (VirtualArrayNode) virtual;
-                        ResolvedJavaType element = array.componentType();
-                        for (int i = 0; i < entryCount; i++) {
-                            ValueNode value = commit.getValues().get(valuePos++);
-                            if (value instanceof VirtualObjectNode) {
-                                int indexOf = commit.getVirtualObjects().indexOf(value);
-                                assert indexOf != -1 : commit + " " + value;
-                                value = allocations[indexOf];
-                            }
-                            if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph), true),
-                                                (value.kind() == Kind.Object && !deferInitBarrier(newObject)) ? BarrierType.PRECISE : BarrierType.NONE, value.kind() == Kind.Object);
-                                graph.addBeforeFixed(commit, graph.add(write));
-                            }
-                        }
-                    }
-                }
-                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                    FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
-                    allocations[objIndex] = anchor;
-                    graph.addBeforeFixed(commit, anchor);
-                }
-                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                    for (int lockDepth : commit.getLocks().get(objIndex)) {
-                        MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth));
-                        graph.addBeforeFixed(commit, enter);
-                        enter.lower(tool);
-                    }
-                }
-                for (Node usage : commit.usages().snapshot()) {
-                    AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
-                    int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
-                    graph.replaceFloating(addObject, allocations[index]);
-                }
-                graph.removeFixed(commit);
-            }
-        } else if (n instanceof OSRStartNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-                OSRStartNode osrStart = (OSRStartNode) n;
-                StartNode newStart = graph.add(new StartNode());
-                LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind)));
-                ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer));
-                migrationEnd.setStateAfter(osrStart.stateAfter());
-
-                newStart.setNext(migrationEnd);
-                FixedNode next = osrStart.next();
-                osrStart.setNext(null);
-                migrationEnd.setNext(next);
-                graph.setStart(newStart);
-
-                // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
-                int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
-                for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
-                    int size = FrameStateBuilder.stackSlots(osrLocal.kind());
-                    int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
-                    IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1);
-                    ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false));
-                    osrLocal.replaceAndDelete(load);
-                    graph.addBeforeFixed(migrationEnd, load);
-                }
-                osrStart.replaceAtUsages(newStart);
-                osrStart.safeDelete();
-            }
-        } else if (n instanceof DynamicCounterNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
-                BenchmarkCounters.lower((DynamicCounterNode) n, runtime.getProviders().getRegisters(), runtime.getConfig(), wordKind);
-            }
-        } else if (n instanceof CheckCastDynamicNode) {
-            checkcastDynamicSnippets.lower((CheckCastDynamicNode) n);
-        } else if (n instanceof InstanceOfNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-                instanceofSnippets.lower((InstanceOfNode) n, tool);
-            }
-        } else if (n instanceof InstanceOfDynamicNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-                instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
-            }
-        } else if (n instanceof NewInstanceNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
-                newObjectSnippets.lower((NewInstanceNode) n);
-            }
-        } else if (n instanceof NewArrayNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
-                newObjectSnippets.lower((NewArrayNode) n);
-            }
-        } else if (n instanceof DynamicNewArrayNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
-                newObjectSnippets.lower((DynamicNewArrayNode) n);
-            }
-        } else if (n instanceof MonitorEnterNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-                monitorSnippets.lower((MonitorEnterNode) n, tool);
-            }
-        } else if (n instanceof MonitorExitNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-                monitorSnippets.lower((MonitorExitNode) n, tool);
-            }
-        } else if (n instanceof G1PreWriteBarrier) {
-            writeBarrierSnippets.lower((G1PreWriteBarrier) n, tool);
-        } else if (n instanceof G1PostWriteBarrier) {
-            writeBarrierSnippets.lower((G1PostWriteBarrier) n, tool);
-        } else if (n instanceof G1ReferentFieldReadBarrier) {
-            writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, tool);
-        } else if (n instanceof SerialWriteBarrier) {
-            writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
-        } else if (n instanceof SerialArrayRangeWriteBarrier) {
-            writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
-        } else if (n instanceof G1ArrayRangePreWriteBarrier) {
-            writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, tool);
-        } else if (n instanceof G1ArrayRangePostWriteBarrier) {
-            writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool);
-        } else if (n instanceof NewMultiArrayNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
-                newObjectSnippets.lower((NewMultiArrayNode) n);
-            }
-        } else if (n instanceof LoadExceptionObjectNode) {
-            exceptionObjectSnippets.lower((LoadExceptionObjectNode) n);
-        } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
-            // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
-            // zero and the MIN_VALUE / -1 cases.
-        } else if (n instanceof BoxNode) {
-            boxingSnippets.lower((BoxNode) n, tool);
-        } else if (n instanceof UnboxNode) {
-            boxingSnippets.lower((UnboxNode) n, tool);
-        } else {
-            assert false : "Node implementing Lowerable not handled: " + n;
-            throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    private static LocationNode createLocation(UnsafeAccessNode access) {
-        ValueNode offset = access.offset();
-        if (offset.isConstant()) {
-            long offsetValue = offset.asConstant().asLong();
-            return ConstantLocationNode.create(access.getLocationIdentity(), access.accessKind(), offsetValue, access.graph());
-        }
-
-        long displacement = 0;
-        int indexScaling = 1;
-        if (offset instanceof IntegerAddNode) {
-            IntegerAddNode integerAddNode = (IntegerAddNode) offset;
-            if (integerAddNode.y() instanceof ConstantNode) {
-                displacement = integerAddNode.y().asConstant().asLong();
-                offset = integerAddNode.x();
-            }
-        }
-
-        if (offset instanceof LeftShiftNode) {
-            LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
-            if (leftShiftNode.y() instanceof ConstantNode) {
-                long shift = leftShiftNode.y().asConstant().asLong();
-                if (shift >= 1 && shift <= 3) {
-                    if (shift == 1) {
-                        indexScaling = 2;
-                    } else if (shift == 2) {
-                        indexScaling = 4;
-                    } else {
-                        indexScaling = 8;
-                    }
-                    offset = leftShiftNode.x();
-                }
-            }
-        }
+    void initialize(HotSpotProviders providers, HotSpotVMConfig config);
 
-        return IndexedLocationNode.create(access.getLocationIdentity(), access.accessKind(), displacement, offset, access.graph(), indexScaling);
-    }
-
-    private static boolean addReadBarrier(UnsafeLoadNode load) {
-        if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object &&
-                        !ObjectStamp.isObjectAlwaysNull(load.object())) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(load.object());
-            if (type != null && !type.isArray()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static ReadNode createReadVirtualMethod(StructuredGraph graph, Kind wordKind, ValueNode hub, ResolvedJavaMethod method) {
-        HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
-        assert !hsMethod.getDeclaringClass().isInterface();
-        assert hsMethod.isInVirtualMethodTable();
-
-        int vtableEntryOffset = hsMethod.vtableEntryOffset();
-        assert vtableEntryOffset > 0;
-        // We use LocationNode.ANY_LOCATION for the reads that access the vtable
-        // entry as HotSpot does not guarantee that this is a final value.
-        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE, false));
-        return metaspaceMethod;
-    }
-
-    private FloatingReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) {
-        HotSpotVMConfig config = runtime.getConfig();
-        LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
-        assert !object.isConstant() || object.asConstant().isNull();
-        return graph.unique(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind), guard, BarrierType.NONE, config.useCompressedClassPointers));
-    }
-
-    private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) {
-        HotSpotVMConfig config = runtime.getConfig();
-        LocationNode location = ConstantLocationNode.create(HUB_LOCATION, wordKind, config.hubOffset, graph);
-        assert !object.isConstant() || object.asConstant().isNull();
-        return graph.add(new WriteNode(object, value, location, BarrierType.NONE, config.useCompressedClassPointers));
-    }
-
-    private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) {
-        BarrierType barrierType = BarrierType.NONE;
-        if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) {
-            barrierType = BarrierType.PRECISE;
-        }
-        return barrierType;
-    }
-
-    private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) {
-        BarrierType barrierType = BarrierType.NONE;
-        if (storeField.field().getKind() == Kind.Object && !deferInitBarrier(storeField.object())) {
-            barrierType = BarrierType.IMPRECISE;
-        }
-        return barrierType;
-    }
-
-    private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) {
-        BarrierType barrierType = BarrierType.NONE;
-        if (store.elementKind() == Kind.Object && !deferInitBarrier(store.array())) {
-            barrierType = BarrierType.PRECISE;
-        }
-        return barrierType;
-    }
-
-    private static boolean deferInitBarrier(ValueNode object) {
-        return useDeferredInitBarriers() && (object instanceof NewInstanceNode || object instanceof NewArrayNode);
-    }
-
-    private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) {
-        BarrierType barrierType = BarrierType.NONE;
-        if (store.value().kind() == Kind.Object) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(store.object());
-            if (type != null && !type.isArray()) {
-                barrierType = BarrierType.IMPRECISE;
-            } else {
-                barrierType = BarrierType.PRECISE;
-            }
-        }
-        return barrierType;
-    }
-
-    private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
-        BarrierType barrierType = BarrierType.NONE;
-        if (cas.expected().kind() == Kind.Object) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(cas.object());
-            if (type != null && !type.isArray()) {
-                barrierType = BarrierType.IMPRECISE;
-            } else {
-                barrierType = BarrierType.PRECISE;
-            }
-        }
-        return barrierType;
-    }
-
-    protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) {
-        LocationIdentity loc = initialization ? INIT_LOCATION : field;
-        return ConstantLocationNode.create(loc, field.getKind(), field.offset(), graph);
-    }
-
-    public int getScalingFactor(Kind kind) {
-        if (useCompressedOops() && kind == Kind.Object) {
-            return this.runtime.getTarget().arch.getSizeInBytes(Kind.Int);
-        } else {
-            return this.runtime.getTarget().arch.getSizeInBytes(kind);
-        }
-    }
-
-    protected IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) {
-        LocationIdentity loc = initialization ? INIT_LOCATION : NamedLocationIdentity.getArrayLocation(elementKind);
-        int scale = getScalingFactor(elementKind);
-        return IndexedLocationNode.create(loc, elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
-    }
-
-    @Override
-    public ValueNode reconstructArrayIndex(LocationNode location) {
-        Kind elementKind = location.getValueKind();
-        assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind));
-
-        long base;
-        ValueNode index;
-        int scale = getScalingFactor(elementKind);
-
-        if (location instanceof ConstantLocationNode) {
-            base = ((ConstantLocationNode) location).getDisplacement();
-            index = null;
-        } else if (location instanceof IndexedLocationNode) {
-            IndexedLocationNode indexedLocation = (IndexedLocationNode) location;
-            assert indexedLocation.getIndexScaling() == scale;
-            base = indexedLocation.getDisplacement();
-            index = indexedLocation.getIndex();
-        } else {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
-        base -= getArrayBaseOffset(elementKind);
-        assert base >= 0 && base % scale == 0;
-
-        base /= scale;
-        assert NumUtil.isInt(base);
-
-        if (index == null) {
-            return ConstantNode.forInt((int) base, location.graph());
-        } else {
-            if (base == 0) {
-                return index;
-            } else {
-                return IntegerArithmeticNode.add(ConstantNode.forInt((int) base, location.graph()), index);
-            }
-        }
-    }
-
-    private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
-        StructuredGraph g = n.graph();
-        ValueNode array = n.array();
-        ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection());
-        if (arrayLength == null) {
-            Stamp stamp = StampFactory.positiveInt();
-            ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false));
-            g.addBeforeFixed(n, readArrayLength);
-            tool.createNullCheckGuard(readArrayLength, array);
-            arrayLength = readArrayLength;
-        }
-
-        return tool.createGuard(g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile);
-    }
-
+    int getScalingFactor(Kind elementKind);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Mon Oct 21 11:07:47 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/HotSpotMethodData.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Mon Oct 21 11:07:47 2013 +0200
@@ -78,7 +78,7 @@
     }
 
     public int getDeoptimizationCount(DeoptimizationReason reason) {
-        int reasonIndex = runtime().getProviders().getMetaAccess().convertDeoptReason(reason);
+        int reasonIndex = runtime().getHostProviders().getMetaAccess().convertDeoptReason(reason);
         return unsafe.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java	Mon Oct 21 11:07:47 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/meta/HotSpotResolvedJavaField.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Oct 21 11:07:47 2013 +0200
@@ -92,7 +92,7 @@
      * only called for snippets or replacements.
      */
     private static boolean isCalledForSnippets() {
-        MetaAccessProvider metaAccess = runtime().getProviders().getMetaAccess();
+        MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
         ResolvedJavaMethod makeGraphMethod = null;
         ResolvedJavaMethod initMethod = null;
         try {
@@ -119,7 +119,7 @@
     private static final Set<ResolvedJavaField> notEmbeddable = new HashSet<>();
 
     private static void addResolvedToSet(Field field) {
-        MetaAccessProvider metaAccess = runtime().getProviders().getMetaAccess();
+        MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
         notEmbeddable.add(metaAccess.lookupJavaField(field));
     }
 
@@ -216,12 +216,12 @@
         if (receiver == null) {
             assert Modifier.isStatic(flags);
             if (holder.isInitialized()) {
-                return runtime().getProviders().getConstantReflection().readUnsafeConstant(getKind(), holder.mirror(), offset, getKind() == Kind.Object);
+                return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), holder.mirror(), offset, getKind() == Kind.Object);
             }
             return null;
         } else {
             assert !Modifier.isStatic(flags);
-            return runtime().getProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver.asObject(), offset, getKind() == Kind.Object);
+            return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver.asObject(), offset, getKind() == Kind.Object);
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Oct 21 11:07:47 2013 +0200
@@ -113,7 +113,7 @@
      * Gets the address of the C++ Method object for this method.
      */
     public Constant getMetaspaceMethodConstant() {
-        return Constant.forIntegerKind(runtime().getTarget().wordKind, metaspaceMethod, this);
+        return Constant.forIntegerKind(getHostWordKind(), metaspaceMethod, this);
     }
 
     @Override
@@ -343,7 +343,7 @@
         // Cannot use toJava() as it ignores the return type
         HotSpotSignature sig = getSignature();
         JavaType[] sigTypes = MetaUtil.signatureToTypes(sig, null);
-        MetaAccessProvider metaAccess = runtime().getProviders().getMetaAccess();
+        MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
         for (Method method : holder.mirror().getDeclaredMethods()) {
             if (method.getName().equals(name)) {
                 if (metaAccess.lookupJavaType(method.getReturnType()).equals(sig.getReturnType(holder))) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Mon Oct 21 11:07:47 2013 +0200
@@ -544,7 +544,7 @@
         Constructor[] constructors = javaMirror.getDeclaredConstructors();
         ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
         for (int i = 0; i < constructors.length; i++) {
-            result[i] = runtime().getProviders().getMetaAccess().lookupJavaConstructor(constructors[i]);
+            result[i] = runtime().getHostProviders().getMetaAccess().lookupJavaConstructor(constructors[i]);
             assert result[i].isConstructor();
         }
         return result;
@@ -555,7 +555,7 @@
         Method[] methods = javaMirror.getDeclaredMethods();
         ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
         for (int i = 0; i < methods.length; i++) {
-            result[i] = runtime().getProviders().getMetaAccess().lookupJavaMethod(methods[i]);
+            result[i] = runtime().getHostProviders().getMetaAccess().lookupJavaMethod(methods[i]);
             assert !result[i].isConstructor();
         }
         return result;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Mon Oct 21 11:07:47 2013 +0200
@@ -41,7 +41,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        Register rawThread = runtime().getProviders().getRegisters().getThreadRegister();
+        Register rawThread = runtime().getHostProviders().getRegisters().getThreadRegister();
         gen.setResult(this, rawThread.asValue(this.kind()));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Oct 21 11:07:47 2013 +0200
@@ -24,7 +24,7 @@
 
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProvider.*;
+import static com.oracle.graal.hotspot.meta.HotSpotHostForeignCallsProvider.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 import sun.misc.*;
 
@@ -203,12 +203,12 @@
 
     @Fold
     public static Register threadRegister() {
-        return runtime().getProviders().getRegisters().getThreadRegister();
+        return runtime().getHostProviders().getRegisters().getThreadRegister();
     }
 
     @Fold
     public static Register stackPointerRegister() {
-        return runtime().getProviders().getRegisters().getStackPointerRegister();
+        return runtime().getHostProviders().getRegisters().getStackPointerRegister();
     }
 
     @Fold
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProvider.*;
+import static com.oracle.graal.hotspot.meta.HotSpotHostForeignCallsProvider.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.PiNode.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Mon Oct 21 11:07:47 2013 +0200
@@ -84,11 +84,13 @@
      */
     public ForeignCallStub(HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, Transition transition, boolean reexecutable,
                     LocationIdentity... killedLocations) {
-        super(providers, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations));
+        super(providers, HotSpotForeignCallLinkage.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getForeignCalls(), descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee,
+                        transition, reexecutable, killedLocations));
         this.prependThread = prependThread;
         Class[] targetParameterTypes = createTargetParameters(descriptor);
         ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes);
-        target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NativeCall, transition, reexecutable, killedLocations);
+        target = HotSpotForeignCallLinkage.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getForeignCalls(), targetSig, address, DESTROYS_REGISTERS, NativeCall, NativeCall,
+                        transition, reexecutable, killedLocations);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java	Mon Oct 21 11:07:47 2013 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.replacements.*;
 
 /**
- * Stub called via {@link HotSpotForeignCallsProvider#VERIFY_OOP}.
+ * Stub called via {@link HotSpotHostForeignCallsProvider#VERIFY_OOP}.
  */
 public class VerifyOopStub extends SnippetStub {
 
--- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java	Mon Oct 21 11:07:47 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.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Oct 21 11:07:47 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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
+/**
+ * This class tests that the canonicalization for constant negate nodes cover all cases.
+ */
+public class NegateNodeCanonicalizationTest {
+
+    private StructuredGraph graph;
+
+    @Before
+    public void before() {
+        graph = new StructuredGraph();
+    }
+
+    @Test
+    public void testByte() {
+        byte[] a = new byte[]{Byte.MIN_VALUE, Byte.MIN_VALUE + 1, -1, 0, 1, Byte.MAX_VALUE - 1, Byte.MAX_VALUE};
+        for (byte i : a) {
+            ConstantNode node = ConstantNode.forByte(i, graph);
+            Constant expected = Constant.forInt(-i);
+            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+        }
+    }
+
+    @Test
+    public void testChar() {
+        char[] a = new char[]{Character.MIN_VALUE, Character.MIN_VALUE + 1, 0, 1, Character.MAX_VALUE - 1, Character.MAX_VALUE};
+        for (char i : a) {
+            ConstantNode node = ConstantNode.forChar(i, graph);
+            Constant expected = Constant.forInt(-i);
+            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+        }
+    }
+
+    @Test
+    public void testShort() {
+        short[] a = new short[]{Short.MIN_VALUE, Short.MIN_VALUE + 1, -1, 0, 1, Short.MAX_VALUE - 1, Short.MAX_VALUE};
+        for (short i : a) {
+            ConstantNode node = ConstantNode.forShort(i, graph);
+            Constant expected = Constant.forInt(-i);
+            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+        }
+    }
+
+    @Test
+    public void testInt() {
+        int[] a = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1, 0, 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE};
+        for (int i : a) {
+            ConstantNode node = ConstantNode.forInt(i, graph);
+            Constant expected = Constant.forInt(-i);
+            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+        }
+    }
+
+    @Test
+    public void testLong() {
+        long[] a = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1, 0, 1, Long.MAX_VALUE - 1, Long.MAX_VALUE};
+        for (long i : a) {
+            ConstantNode node = ConstantNode.forLong(i, graph);
+            Constant expected = Constant.forLong(-i);
+            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+        }
+    }
+
+    @Test
+    public void testFloat() {
+        float[] a = new float[]{Float.MIN_VALUE, Float.MIN_VALUE + 1, -1, 0, 1, Float.MAX_VALUE - 1, Float.MAX_VALUE};
+        for (float i : a) {
+            ConstantNode node = ConstantNode.forFloat(i, graph);
+            Constant expected = Constant.forFloat(-i);
+            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+        }
+    }
+
+    @Test
+    public void testDouble() {
+        double[] a = new double[]{Double.MIN_VALUE, Double.MIN_VALUE + 1, -1, 0, 1, Double.MAX_VALUE - 1, Double.MAX_VALUE};
+        for (double i : a) {
+            ConstantNode node = ConstantNode.forDouble(i, graph);
+            Constant expected = Constant.forDouble(-i);
+            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Oct 21 11:07:47 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/calc/NegateNode.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Oct 21 11:07:47 2013 +0200
@@ -57,17 +57,18 @@
 
     public Constant evalConst(Constant... inputs) {
         assert inputs.length == 1;
-        switch (inputs[0].getKind()) {
+        Constant constant = inputs[0];
+        switch (constant.getKind()) {
             case Int:
-                return Constant.forInt(-inputs[0].asInt());
+                return Constant.forInt(-(constant.asInt()));
             case Long:
-                return Constant.forLong(-inputs[0].asLong());
+                return Constant.forLong(-(constant.asLong()));
             case Float:
-                return Constant.forFloat(-inputs[0].asFloat());
+                return Constant.forFloat(-(constant.asFloat()));
             case Double:
-                return Constant.forDouble(-inputs[0].asDouble());
+                return Constant.forDouble(-(constant.asDouble()));
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("unknown kind " + constant.getKind());
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java	Mon Oct 21 11:07:47 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.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java	Mon Oct 21 11:07:47 2013 +0200
@@ -22,9 +22,10 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import com.oracle.graal.graph.Node.*;
 import com.oracle.graal.nodes.*;
 
-public abstract class EscapeObjectState extends VirtualState {
+public abstract class EscapeObjectState extends VirtualState implements ValueNumberable {
 
     @Input private VirtualObjectNode object;
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 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	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Mon Oct 21 11:07:47 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.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -37,7 +37,7 @@
 public class CompiledExceptionHandlerTest extends GraalCompilerTest {
 
     public CompiledExceptionHandlerTest() {
-        suites.getHighTier().findPhase(AbstractInliningPhase.class).remove();
+        getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove();
     }
 
     @Override
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DeoptimizeOnExceptionTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DeoptimizeOnExceptionTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -33,7 +33,7 @@
 public class DeoptimizeOnExceptionTest extends GraalCompilerTest {
 
     public DeoptimizeOnExceptionTest() {
-        suites.getHighTier().findPhase(AbstractInliningPhase.class).remove();
+        getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove();
     }
 
     private static void raiseException(String m1, String m2, String m3, String m4, String m5) {
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -42,7 +42,7 @@
 public class InstanceOfTest extends TypeCheckTest {
 
     public InstanceOfTest() {
-        suites.getHighTier().findPhase(AbstractInliningPhase.class).remove();
+        getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove();
     }
 
     @Override
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java	Mon Oct 21 11:07:47 2013 +0200
@@ -33,7 +33,7 @@
 public class InvokeTest extends GraalCompilerTest {
 
     public InvokeTest() {
-        suites.getHighTier().findPhase(AbstractInliningPhase.class).remove();
+        getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove();
     }
 
     public interface I {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.runtime/src/com/oracle/graal/runtime/RuntimeProvider.java	Mon Oct 21 11:07:47 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();
+}
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Oct 21 11:07:47 2013 +0200
@@ -29,7 +29,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.hotspot.meta.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
@@ -46,7 +45,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()) {
@@ -54,7 +53,7 @@
         }
     }
 
-    private HotSpotNmethod compiledMethod;
+    private InstalledCode compiledMethod;
     private final TruffleCompiler compiler;
     private final CompilationPolicy compilationPolicy;
 
@@ -129,7 +128,7 @@
     public void compile() {
         CompilerAsserts.neverPartOfCompilation();
         try {
-            compiledMethod = (HotSpotNmethod) compiler.compile(this);
+            compiledMethod = compiler.compile(this);
             if (compiledMethod == null) {
                 throw new BailoutException(String.format("code installation failed (codeSize=%s)", codeSize));
             } else {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Oct 21 11:07:47 2013 +0200
@@ -36,7 +36,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.*;
@@ -45,6 +44,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.*;
@@ -59,7 +59,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 static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class};
@@ -68,18 +68,18 @@
                     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());
 
         final GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault();
         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);
@@ -113,7 +113,10 @@
         final StructuredGraph graph;
         final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault();
         config.setSkippedExceptionTypes(skippedExceptionTypes);
-        runtime.evictDeoptedGraphs();
+        GraphCache graphCache = runtime.getGraphCache();
+        if (graphCache != null) {
+            graphCache.removeStaleGraphs();
+        }
 
         compilable.timeCompilationStarted = System.nanoTime();
         Assumptions assumptions = new Assumptions(true);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Oct 21 11:07:47 2013 +0200
@@ -70,7 +70,12 @@
     @Option(help = "")
     public static final OptionValue<Boolean> TruffleUseTimeForCompilationDecision = new OptionValue<>(false);
     @Option(help = "")
-    public static final OptionValue<Integer> TruffleCompilationDecisionTime = new OptionValue<>(100);
+    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
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleCompilation = new OptionValue<>(true);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Mon Oct 21 11:07:47 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.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Oct 21 11:07:47 2013 +0200
@@ -178,7 +178,7 @@
                         stateAfter.virtualObjectMappings().remove(i);
                     }
                 }
-                stateAfter.addVirtualObjectMapping(graph.addWithoutUnique(state));
+                stateAfter.addVirtualObjectMapping(graph.unique(state));
             }
 
             @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Oct 21 11:07:32 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Oct 21 11:07:47 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/hotspot/.project	Mon Oct 21 11:07:32 2013 +0200
+++ b/hotspot/.project	Mon Oct 21 11:07:47 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/windows/makefiles/projectcreator.make	Mon Oct 21 11:07:32 2013 +0200
+++ b/make/windows/makefiles/projectcreator.make	Mon Oct 21 11:07:47 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/projects	Mon Oct 21 11:07:32 2013 +0200
+++ b/mx/projects	Mon Oct 21 11:07:47 2013 +0200
@@ -28,7 +28,13 @@
 library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.2.jar
 
 distribution@GRAAL@path=graal.jar
-distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.ptx,com.oracle.graal.truffle,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot,com.oracle.graal.compiler.hsail
+distribution@GRAAL@dependencies=\
+com.oracle.graal.hotspot.amd64,\
+com.oracle.graal.hotspot.ptx,\
+com.oracle.graal.truffle,\
+com.oracle.graal.hotspot.sparc,\
+com.oracle.graal.hotspot,\
+com.oracle.graal.hotspot.hsail
 
 # graal.api.runtime
 project@com.oracle.graal.api.runtime@subDir=graal
@@ -55,7 +61,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
@@ -111,7 +117,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
@@ -137,7 +143,7 @@
 # graal.hotspot.ptx
 project@com.oracle.graal.hotspot.ptx@subDir=graal
 project@com.oracle.graal.hotspot.ptx@sourceDirs=src
-project@com.oracle.graal.hotspot.ptx@dependencies=com.oracle.graal.hotspot,com.oracle.graal.ptx
+project@com.oracle.graal.hotspot.ptx@dependencies=com.oracle.graal.ptx,com.oracle.graal.compiler.ptx
 project@com.oracle.graal.hotspot.ptx@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.ptx@annotationProcessors=com.oracle.graal.service.processor
 project@com.oracle.graal.hotspot.ptx@javaCompliance=1.7
@@ -387,7 +393,7 @@
 # graal.compiler.ptx.test
 project@com.oracle.graal.compiler.ptx.test@subDir=graal
 project@com.oracle.graal.compiler.ptx.test@sourceDirs=src
-project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.hotspot.ptx,com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test
+project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.hotspot.ptx,com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7
 project@com.oracle.graal.compiler.ptx.test@workingSets=Graal,PTX,Test
@@ -408,6 +414,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
@@ -434,7 +448,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
@@ -458,7 +472,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
@@ -482,7 +496,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
@@ -622,7 +636,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
--- a/mxtool/mx.py	Mon Oct 21 11:07:32 2013 +0200
+++ b/mxtool/mx.py	Mon Oct 21 11:07:47 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,12 @@
 _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
 
 
 """
@@ -493,41 +497,245 @@
         deps.append(self)
         return deps
 
+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)
+            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 _self_tostring(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  # _hgtip checks current version if not None
+        self.version = _hgtip(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:
                 line = line.strip()
+                if line.endswith('\\'):
+                    prefix = prefix + line[:-1]
+                    continue
+                if len(prefix) != 0:
+                    line = prefix + line
+                    prefix = ''
                 if len(line) != 0 and line[0] != '#':
                     key, value = line.split('=', 1)
 
@@ -537,10 +745,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)
@@ -609,38 +814,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
@@ -654,8 +910,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:
@@ -673,7 +929,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'):
@@ -770,28 +1026,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):
     """
@@ -815,6 +1059,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
@@ -1013,7 +1258,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
@@ -1021,7 +1266,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()
@@ -1034,6 +1278,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>')
@@ -1045,6 +1290,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>')
@@ -1599,7 +1847,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)')
@@ -1796,7 +2044,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)
@@ -2115,7 +2363,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
@@ -2675,8 +2923,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]
@@ -2756,12 +3003,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'})
@@ -3203,18 +3458,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"""
@@ -3618,9 +3879,292 @@
         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"""
+    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"""
+    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 = _hgdefault_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 = _hgtip(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 _hgcanpush(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"""
+    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.nochecks, 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"""
+
+    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 = _hgtip(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 = suite_import._self_tostring()
+        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 _hgtip(s, abortOnError=True):
+    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 _hgcanpush(s):
+    try:
+        output = subprocess.check_output(['hg', '-R', s.dir, 'status'])
+        # super strict
+        return output == ''
+    except subprocess.CalledProcessError:
+        return False
+
+def _hgdefault_push(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
+
+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):
+    # 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 = _hgtip(s)
+        updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n')
+
+def spull(args):
+    """pull primary suite and all its imports"""
+    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'):
@@ -3727,17 +4271,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]'],
@@ -3753,6 +4299,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]'],
@@ -3763,36 +4315,68 @@
 
 _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()
+
+    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	Mon Oct 21 11:07:32 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Mon Oct 21 11:07:47 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/classfile/vmSymbols.hpp	Mon Oct 21 11:07:32 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Oct 21 11:07:47 2013 +0200
@@ -314,9 +314,6 @@
   template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")             \
   template(com_oracle_graal_hotspot_debug_LocalImpl,                 "com/oracle/graal/hotspot/debug/LocalImpl")                      \
   template(com_oracle_graal_hotspot_CompilerThread,                  "com/oracle/graal/hotspot/CompilerThread")                       \
-  template(com_oracle_graal_hotspot_ptx_PTXHotSpotGraalRuntime,      "com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime")\
-  AMD64_ONLY(template(com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime,"com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime"))\
-  SPARC_ONLY(template(com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime,"com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime"))\
   /* graal.api.meta */                                                                                                                \
   template(com_oracle_graal_api_meta_Constant,                       "com/oracle/graal/api/meta/Constant")                            \
   template(com_oracle_graal_api_meta_ConstantPool,                   "com/oracle/graal/api/meta/ConstantPool")                        \
@@ -387,11 +384,11 @@
   template(createConstantObject_signature,        "(Ljava/lang/Object;)Lcom/oracle/graal/api/meta/Constant;")                         \
   template(getVMToCompiler_name,                  "getVMToCompiler")                                                                  \
   template(getVMToCompiler_signature,             "()Lcom/oracle/graal/hotspot/bridge/VMToCompiler;")                                 \
-  template(getInstance_name,                      "getInstance")                                                                      \
-  template(getTruffleRuntimeInstance_signature,   "()Lcom/oracle/graal/truffle/GraalTruffleRuntime;")                                 \
+  template(runtime_name,                          "runtime")                                                                          \
+  template(runtime_signature,                     "()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;")                                 \
   template(makeInstance_name,                     "makeInstance")                                                                     \
+  template(makeInstance_signature,                "()Lcom/oracle/graal/truffle/GraalTruffleRuntime;")                                 \
   template(initialize_name,                       "initialize")                                                                       \
-  template(getInstance_signature,                 "()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;")                                 \
   template(forObject_name,                        "forObject")                                                                        \
   template(callbackInternal_name,                 "callbackInternal")                                                                 \
   template(callback_signature,                    "(Ljava/lang/Object;)Ljava/lang/Object;")                                           \
--- a/src/share/vm/graal/graalCompilerToGPU.cpp	Mon Oct 21 11:07:32 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToGPU.cpp	Mon Oct 21 11:07:47 2013 +0200
@@ -23,6 +23,7 @@
 
 #include "precompiled.hpp"
 
+#include "memory/oopFactory.hpp"
 #include "graal/graalCompiler.hpp"
 #include "graal/graalEnv.hpp"
 #include "graal/graalJavaAccess.hpp"
@@ -205,7 +206,7 @@
 #define CONSTANT_POOL         "Lcom/oracle/graal/api/meta/ConstantPool;"
 #define CONSTANT              "Lcom/oracle/graal/api/meta/Constant;"
 #define KIND                  "Lcom/oracle/graal/api/meta/Kind;"
-#define LOCAL                  "Lcom/oracle/graal/api/meta/Local;"
+#define LOCAL                 "Lcom/oracle/graal/api/meta/Local;"
 #define RUNTIME_CALL          "Lcom/oracle/graal/api/code/RuntimeCall;"
 #define EXCEPTION_HANDLERS    "[Lcom/oracle/graal/api/meta/ExceptionHandler;"
 #define REFLECT_METHOD        "Ljava/lang/reflect/Method;"
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Mon Oct 21 11:07:32 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Mon Oct 21 11:07:47 2013 +0200
@@ -53,32 +53,16 @@
   KlassHandle klass = loadClass(name);
 
   JavaValue result(T_OBJECT);
-  JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::getTruffleRuntimeInstance_signature(), Thread::current());
+  JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::makeInstance_signature(), Thread::current());
   check_pending_exception("Couldn't initialize GraalTruffleRuntime");
   return Handle((oop) result.get_jobject());
 }
 
 Handle VMToCompiler::graalRuntime() {
   if (JNIHandles::resolve(_graalRuntimePermObject) == NULL) {
-#ifdef AMD64
-    Symbol* name = NULL;
-    // Set name to PTXHotSpotRuntime if nVidia GPU was detected.
-    if (UseGPU && (gpu::get_target_il_type() == gpu::PTX) &&
-        gpu::is_available() && gpu::has_gpu_linkage()) {
-      name = vmSymbols::com_oracle_graal_hotspot_ptx_PTXHotSpotGraalRuntime();
-    }
-    
-    if (name == NULL) {
-      name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime();
-    }
-#endif
-#ifdef SPARC
-    Symbol* name = vmSymbols::com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime();
-#endif
-    KlassHandle klass = loadClass(name);
-
+    KlassHandle klass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotGraalRuntime());
     JavaValue result(T_OBJECT);
-    JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::getInstance_signature(), Thread::current());
+    JavaCalls::call_static(&result, klass, vmSymbols::runtime_name(), vmSymbols::runtime_signature(), Thread::current());
     check_pending_exception("Couldn't initialize HotSpotGraalRuntime");
     _graalRuntimePermObject = JNIHandles::make_global((oop) result.get_jobject());
   }
--- a/src/share/vm/runtime/arguments.cpp	Mon Oct 21 11:07:32 2013 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/src/share/vm/runtime/arguments.hpp	Mon Oct 21 11:07:47 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	Mon Oct 21 11:07:32 2013 +0200
+++ b/src/share/vm/runtime/globals.hpp	Mon Oct 21 11:07:47 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")          \
                                                                             \