changeset 12599:faded4a83d63

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 25 Oct 2013 01:39:54 +0200
parents cf6cfa79593d (current diff) 04e51b3026c0 (diff)
children 80bbaf87fc89
files graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java
diffstat 101 files changed, 2862 insertions(+), 1534 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Fri Oct 25 01:39:54 2013 +0200
@@ -42,6 +42,16 @@
     InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult);
 
     /**
+     * Sets the given compilation result as the default implementation of the given method.
+     * 
+     * @param method a method to which the executable code is begin added
+     * @param compResult the compilation result to be added
+     * @return a reference to the compiled and ready-to-run code or null if the code installation
+     *         failed
+     */
+    InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult);
+
+    /**
      * Returns a disassembly of some compiled code.
      * 
      * @param compResult some compiled code
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Fri Oct 25 01:39:54 2013 +0200
@@ -326,6 +326,8 @@
     private int customStackAreaOffset = -1;
     private int registerRestoreEpilogueOffset = -1;
 
+    private final String name;
+
     /**
      * The buffer containing the emitted machine code.
      */
@@ -347,6 +349,14 @@
      */
     private long[] leafGraphIds;
 
+    public CompilationResult() {
+        this(null);
+    }
+
+    public CompilationResult(String name) {
+        this.name = name;
+    }
+
     public void setAssumptions(Assumptions assumptions) {
         this.assumptions = assumptions;
     }
@@ -620,4 +630,8 @@
         }
         return unmodifiableList(marks);
     }
+
+    public String getName() {
+        return name;
+    }
 }
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Fri Oct 25 01:39:54 2013 +0200
@@ -360,18 +360,18 @@
             assert var instanceof Variable;
             assert val instanceof Constant;
             Constant constant = (Constant) val;
-            return ("[" + emitRegister((Variable) var, false) + " + " + constant.asBoxedValue() + "]");
+            return ("[" + ((space == PTXStateSpace.Parameter) ? emitParameter((Variable) var) : emitRegister((Variable) var, false)) + " + " + constant.asBoxedValue() + "]");
         }
 
         @Override
         public String emitRegister(Variable var, boolean comma) {
-            /*
-             * if (space == Parameter) { return ("param" + var.index); } else { return ("%r" +
-             * var.index); }
-             */
             return ("%r" + var.index);
         }
 
+        public String emitParameter(Variable v) {
+            return ("param" + v.index);
+        }
+
         public String emit(boolean isLoad) {
             if (isLoad) {
                 return (space.getStateName() + "." + typeForKind(valueKind) + " " + emitRegister(dest, false) + ", " + emitAddress(source1, source2) + ";");
@@ -671,7 +671,7 @@
         }
 
         public String emitParameter(Variable v) {
-            return (" %r" + v.index);
+            return (" param" + v.index);
         }
 
         public void emit(PTXAssembler asm) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Fri Oct 25 01:39:54 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.compiler.test;
 
+import static com.oracle.graal.nodes.ConstantNode.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 import static org.junit.Assert.*;
 
@@ -144,7 +145,9 @@
         new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
         for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) {
-            assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
+            if (ConstantNodeRecordsUsages || !constant.gatherUsages().isEmpty()) {
+                assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
+            }
         }
     }
 
@@ -176,7 +179,9 @@
         new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
         for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) {
-            assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
+            if (ConstantNodeRecordsUsages || !constant.gatherUsages().isEmpty()) {
+                assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
+            }
         }
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Oct 25 01:39:54 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.test;
 
 import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.nodes.ConstantNode.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.*;
@@ -116,12 +117,32 @@
         assertEquals(expected, graph, false);
     }
 
+    protected int countUnusedConstants(StructuredGraph graph) {
+        int total = 0;
+        for (ConstantNode node : graph.getNodes().filter(ConstantNode.class)) {
+            if (!ConstantNodeRecordsUsages) {
+                if (node.gatherUsages().isEmpty()) {
+                    total++;
+                }
+            } else {
+                if (node.usages().isEmpty()) {
+                    total++;
+                }
+            }
+        }
+        return total;
+    }
+
+    protected int getNodeCountExcludingUnusedConstants(StructuredGraph graph) {
+        return graph.getNodeCount() - countUnusedConstants(graph);
+    }
+
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph, boolean excludeVirtual) {
         String expectedString = getCanonicalGraphString(expected, excludeVirtual);
         String actualString = getCanonicalGraphString(graph, excludeVirtual);
         String mismatchString = "mismatch in graphs:\n========= expected =========\n" + expectedString + "\n\n========= actual =========\n" + actualString;
 
-        if (!excludeVirtual && expected.getNodeCount() != graph.getNodeCount()) {
+        if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
             Debug.dump(expected, "Node count not matching - expected");
             Debug.dump(graph, "Node count not matching - actual");
             Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString);
@@ -161,16 +182,18 @@
             }
             result.append("\n");
             for (Node node : schedule.getBlockToNodesMap().get(block)) {
-                if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) {
-                    int id;
-                    if (canonicalId.get(node) != null) {
-                        id = canonicalId.get(node);
-                    } else {
-                        id = nextId++;
-                        canonicalId.set(node, id);
+                if (node.recordsUsages()) {
+                    if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) {
+                        int id;
+                        if (canonicalId.get(node) != null) {
+                            id = canonicalId.get(node);
+                        } else {
+                            id = nextId++;
+                            canonicalId.set(node, id);
+                        }
+                        String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName();
+                        result.append("  " + id + "|" + name + (excludeVirtual ? "\n" : "    (" + node.usages().count() + ")\n"));
                     }
-                    String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName();
-                    result.append("  " + id + "|" + name + (excludeVirtual ? "\n" : "    (" + node.usages().count() + ")\n"));
                 }
             }
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Fri Oct 25 01:39:54 2013 +0200
@@ -197,7 +197,7 @@
 
     @Override
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
-        if (expected.getNodeCount() != graph.getNodeCount()) {
+        if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
             outputGraph(expected, "expected");
             outputGraph(graph, "actual");
             Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount());
@@ -225,7 +225,7 @@
     }
 
     private static void outputNode(Node node) {
-        TTY.print("  " + node + "    (usage count: " + node.usages().count() + ") (inputs:");
+        TTY.print("  " + node + "    (usage count: " + (node.recordsUsages() ? node.usages().count() : "?") + ") (inputs:");
         for (Node input : node.inputs()) {
             TTY.print(" " + input.toString(Verbosity.Id));
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Fri Oct 25 01:39:54 2013 +0200
@@ -63,7 +63,7 @@
             if (node instanceof ConstantNode) {
                 ConstantNode constant = (ConstantNode) node;
                 if (constant.kind() == Kind.Object && " ".equals(constant.value.asObject())) {
-                    graph.replaceFloating(constant, ConstantNode.forObject("-", getMetaAccess(), graph));
+                    constant.replace(ConstantNode.forObject("-", getMetaAccess(), graph));
                 }
             }
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Oct 25 01:39:54 2013 +0200
@@ -138,32 +138,44 @@
         Debug.scope("GraalCompiler", new Object[]{graph, providers.getCodeCache()}, new Runnable() {
 
             public void run() {
-                final Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
-                final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
+                compileGraphNoScope(graph, cc, installedCodeOwner, providers, backend, target, cache, plan, optimisticOpts, speculationLog, suites, compilationResult);
+            }
+        });
 
-                    public LIR call() {
-                        try (TimerCloseable a = FrontEnd.start()) {
-                            return emitHIR(providers, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog, suites);
-                        }
-                    }
-                });
-                try (TimerCloseable a = BackEnd.start()) {
-                    final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
+        return compilationResult;
+    }
 
-                        public LIRGenerator call() {
-                            return emitLIR(backend, target, lir, graph, cc);
-                        }
-                    });
-                    Debug.scope("CodeGen", lirGen, new Runnable() {
+    /**
+     * Same as {@link #compileGraph} but without entering a
+     * {@linkplain Debug#scope(String, Object[], Runnable) debug scope}.
+     */
+    public static <T extends CompilationResult> T compileGraphNoScope(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 T compilationResult) {
+        final Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
+        final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
-                        public void run() {
-                            emitCode(backend, getLeafGraphIdArray(graph), assumptions, lirGen, compilationResult, installedCodeOwner);
-                        }
-
-                    });
+            public LIR call() {
+                try (TimerCloseable a = FrontEnd.start()) {
+                    return emitHIR(providers, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog, suites);
                 }
             }
         });
+        try (TimerCloseable a = BackEnd.start()) {
+            final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
+
+                public LIRGenerator call() {
+                    return emitLIR(backend, target, lir, graph, cc);
+                }
+            });
+            Debug.scope("CodeGen", lirGen, new Runnable() {
+
+                public void run() {
+                    emitCode(backend, getLeafGraphIdArray(graph), assumptions, lirGen, compilationResult, installedCodeOwner);
+                }
+
+            });
+        }
 
         return compilationResult;
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Fri Oct 25 01:39:54 2013 +0200
@@ -69,7 +69,11 @@
     // @formatter:on
 
     public static boolean areDebugScopePatternsEnabled() {
-        return DumpOnError.getValue() || Dump.getValue() != null || Meter.getValue() != null || Time.getValue() != null || Log.getValue() != null;
+        return DumpOnError.getValue() || Dump.getValue() != null || Log.getValue() != null || areMetricsOrTimersEnabled();
+    }
+
+    public static boolean areMetricsOrTimersEnabled() {
+        return Meter.getValue() != null || Time.getValue() != null;
     }
 
     private final DebugFilter logFilter;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Oct 25 01:39:54 2013 +0200
@@ -869,8 +869,7 @@
 
         // check that the liveIn set of the first block is empty
         Block startBlock = ir.cfg.getStartBlock();
-        BitSet liveInArgs = new BitSet(blockData.get(startBlock).liveIn.size());
-        if (!blockData.get(startBlock).liveIn.equals(liveInArgs)) {
+        if (blockData.get(startBlock).liveIn.cardinality() != 0) {
             if (DetailedAsserts.getValue()) {
                 reportFailure(numBlocks);
             }
@@ -878,73 +877,76 @@
             TTY.println("preds=" + startBlock.getPredecessorCount() + ", succs=" + startBlock.getSuccessorCount());
             TTY.println("startBlock-ID: " + startBlock.getId());
 
-            // bailout of if this occurs in product mode.
-            throw new GraalInternalError("liveIn set of first block must be empty");
+            // bailout if this occurs in product mode.
+            throw new GraalInternalError("liveIn set of first block must be empty: " + blockData.get(startBlock).liveIn);
         }
     }
 
     private void reportFailure(int numBlocks) {
         TTY.println(gen.getGraph().toString());
-        TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined)");
-        TTY.print("affected registers:");
-        TTY.println(blockData.get(ir.cfg.getStartBlock()).liveIn.toString());
+        TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):");
+        BitSet startBlockLiveIn = blockData.get(ir.cfg.getStartBlock()).liveIn;
+        for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) {
+            Value operand = operandFor(operandNum);
+            TTY.println("  var %d; operand=%s; node=%s", operandNum, operand.toString(), gen.valueForOperand(operand));
+        }
 
         // print some additional information to simplify debugging
-        for (int operandNum = 0; operandNum < blockData.get(ir.cfg.getStartBlock()).liveIn.size(); operandNum++) {
-            if (blockData.get(ir.cfg.getStartBlock()).liveIn.get(operandNum)) {
-                Value operand = operandFor(operandNum);
-                TTY.println(" var %d; operand=%s; node=%s", operandNum, operand.toString(), gen.valueForOperand(operand));
+        for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) {
+            Value operand = operandFor(operandNum);
+            TTY.println("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand.toString(), gen.valueForOperand(operand));
+
+            Deque<Block> definedIn = new ArrayDeque<>();
+            HashSet<Block> usedIn = new HashSet<>();
+            for (Block block : sortedBlocks) {
+                if (blockData.get(block).liveGen.get(operandNum)) {
+                    usedIn.add(block);
+                    TTY.println("used in block B%d {", block.getId());
+                    for (LIRInstruction ins : ir.lir(block)) {
+                        TTY.println("  " + ins.id() + ": " + ins.toString());
+                        ins.forEachState(new ValueProcedure() {
 
-                Deque<Block> definedIn = new ArrayDeque<>();
-                HashSet<Block> usedIn = new HashSet<>();
-                for (Block block : sortedBlocks) {
-                    if (blockData.get(block).liveGen.get(operandNum)) {
-                        usedIn.add(block);
-                        TTY.println("  used in block B%d", block.getId());
-                        for (LIRInstruction ins : ir.lir(block)) {
-                            TTY.println(ins.id() + ": " + ins.toString());
-                            ins.forEachState(new ValueProcedure() {
+                            @Override
+                            public Value doValue(Value liveStateOperand) {
+                                TTY.println("    operand=" + liveStateOperand);
+                                return liveStateOperand;
+                            }
+                        });
+                    }
+                    TTY.println("}");
+                }
+                if (blockData.get(block).liveKill.get(operandNum)) {
+                    definedIn.add(block);
+                    TTY.println("defined in block B%d {", block.getId());
+                    for (LIRInstruction ins : ir.lir(block)) {
+                        TTY.println("  " + ins.id() + ": " + ins.toString());
+                    }
+                    TTY.println("}");
+                }
+            }
 
-                                @Override
-                                public Value doValue(Value liveStateOperand) {
-                                    TTY.println("   operand=" + liveStateOperand);
-                                    return liveStateOperand;
-                                }
-                            });
+            int[] hitCount = new int[numBlocks];
+
+            while (!definedIn.isEmpty()) {
+                Block block = definedIn.removeFirst();
+                usedIn.remove(block);
+                for (Block successor : block.getSuccessors()) {
+                    if (successor.isLoopHeader()) {
+                        if (!block.isLoopEnd()) {
+                            definedIn.add(successor);
                         }
-                    }
-                    if (blockData.get(block).liveKill.get(operandNum)) {
-                        definedIn.add(block);
-                        TTY.println("  defined in block B%d", block.getId());
-                        for (LIRInstruction ins : ir.lir(block)) {
-                            TTY.println(ins.id() + ": " + ins.toString());
+                    } else {
+                        if (++hitCount[successor.getId()] == successor.getPredecessorCount()) {
+                            definedIn.add(successor);
                         }
                     }
                 }
-
-                int[] hitCount = new int[numBlocks];
-
-                while (!definedIn.isEmpty()) {
-                    Block block = definedIn.removeFirst();
-                    usedIn.remove(block);
-                    for (Block successor : block.getSuccessors()) {
-                        if (successor.isLoopHeader()) {
-                            if (!block.isLoopEnd()) {
-                                definedIn.add(successor);
-                            }
-                        } else {
-                            if (++hitCount[successor.getId()] == successor.getPredecessorCount()) {
-                                definedIn.add(successor);
-                            }
-                        }
-                    }
-                }
-                TTY.print("  offending usages are in: ");
-                for (Block block : usedIn) {
-                    TTY.print("B%d ", block.getId());
-                }
-                TTY.println();
             }
+            TTY.print("**** offending usages are in: ");
+            for (Block block : usedIn) {
+                TTY.print("B%d ", block.getId());
+            }
+            TTY.println();
         }
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Oct 25 01:39:54 2013 +0200
@@ -26,6 +26,7 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
+import static com.oracle.graal.nodes.ConstantNode.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
@@ -66,6 +67,13 @@
     protected final DebugInfoBuilder debugInfoBuilder;
 
     protected Block currentBlock;
+
+    /**
+     * Maps constants the variables within the scope of a single block to avoid loading a constant
+     * more than once per block.
+     */
+    private Map<Constant, Variable> constantsLoadedInCurrentBlock;
+
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
 
@@ -151,7 +159,38 @@
         if (nodeOperands == null) {
             return null;
         }
-        return nodeOperands.get(node);
+        Value operand = nodeOperands.get(node);
+        if (operand == null) {
+            return getConstantOperand(node);
+        }
+        return operand;
+    }
+
+    private Value getConstantOperand(ValueNode node) {
+        if (!ConstantNodeRecordsUsages) {
+            Constant value = node.asConstant();
+            if (value != null) {
+                if (canInlineConstant(value)) {
+                    return setResult(node, value);
+                } else {
+                    Variable loadedValue;
+                    if (constantsLoadedInCurrentBlock == null) {
+                        constantsLoadedInCurrentBlock = new HashMap<>();
+                        loadedValue = null;
+                    } else {
+                        loadedValue = constantsLoadedInCurrentBlock.get(value);
+                    }
+                    if (loadedValue == null) {
+                        loadedValue = emitMove(value);
+                        constantsLoadedInCurrentBlock.put(value, loadedValue);
+                    }
+                    return loadedValue;
+                }
+            }
+        } else {
+            // Constant is loaded by ConstantNode.generate()
+        }
+        return null;
     }
 
     public ValueNode valueForOperand(Value value) {
@@ -188,7 +227,7 @@
     @Override
     public Value setResult(ValueNode x, Value operand) {
         assert (!isRegister(operand) || !attributes(asRegister(operand)).isAllocatable());
-        assert operand(x) == null : "operand cannot be set twice";
+        assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice";
         assert operand != null && isLegal(operand) : "operand must be legal";
         assert operand.getKind().getStackKind() == x.kind() || x.kind() == Kind.Illegal : operand.getKind().getStackKind() + " must match " + x.kind();
         assert !(x instanceof VirtualObjectNode);
@@ -296,6 +335,8 @@
         }
 
         currentBlock = block;
+        resetLoadedConstants();
+
         // set up the list of LIR instructions
         assert lir.lir(block) == null : "LIR list already computed for this block";
         lir.setLir(block, new ArrayList<LIRInstruction>());
@@ -319,7 +360,9 @@
             if (TraceLIRGeneratorLevel.getValue() >= 3) {
                 TTY.println("LIRGen for " + instr);
             }
-            if (instr instanceof ValueNode) {
+            if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) {
+                // Loading of constants is done lazily by operand()
+            } else if (instr instanceof ValueNode) {
                 ValueNode valueNode = (ValueNode) instr;
                 if (operand(valueNode) == null) {
                     if (!peephole(valueNode)) {
@@ -355,6 +398,12 @@
         }
     }
 
+    private void resetLoadedConstants() {
+        if (constantsLoadedInCurrentBlock != null && !constantsLoadedInCurrentBlock.isEmpty()) {
+            constantsLoadedInCurrentBlock.clear();
+        }
+    }
+
     protected abstract boolean peephole(ValueNode valueNode);
 
     private boolean endsWithJump(Block block) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Fri Oct 25 01:39:54 2013 +0200
@@ -361,7 +361,7 @@
             int minCount = Integer.MAX_VALUE;
             Node minCountNode = null;
             for (Node input : node.inputs()) {
-                if (input != null) {
+                if (input != null && input.recordsUsages()) {
                     int estimate = input.getUsageCountUpperBound();
                     if (estimate == 0) {
                         return null;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Fri Oct 25 01:39:54 2013 +0200
@@ -255,6 +255,7 @@
     }
 
     int getUsageCountUpperBound() {
+        assert recordsUsages();
         if (usage0 == null) {
             return 0;
         }
@@ -265,13 +266,23 @@
     }
 
     /**
-     * Gets the list of nodes that use this node (e.g., as an input).
+     * Gets the list of nodes that use this node (i.e., as an input).
      */
     public final NodeIterable<Node> usages() {
+        assert recordsUsages() : this;
         return new NodeUsageIterable();
     }
 
     /**
+     * Determines if this node records its usages (i.e. the nodes for which it is an input). All
+     * methods in {@link Node} that pertain to querying or updating usage information must not be
+     * called for a {@link Node} instance that returns false for this method.
+     */
+    public boolean recordsUsages() {
+        return true;
+    }
+
+    /**
      * Finds the index of the last non-null entry in a node array. The search assumes that all
      * non-null entries precede the first null entry in the array.
      * 
@@ -311,6 +322,7 @@
      * @param node the node to add
      */
     private void addUsage(Node node) {
+        assert recordsUsages();
         incUsageModCount();
         if (usage0 == null) {
             usage0 = node;
@@ -342,6 +354,7 @@
      * @return whether or not {@code usage} was in the usage list
      */
     private boolean removeUsage(Node node) {
+        assert recordsUsages();
         // It is critical that this method maintains the invariant that
         // the usage list has no null element preceding a non-null element
         incUsageModCount();
@@ -392,6 +405,7 @@
     }
 
     private void clearUsages() {
+        assert recordsUsages();
         incUsageModCount();
         usage0 = null;
         usage1 = null;
@@ -443,16 +457,20 @@
     protected void updateUsages(Node oldInput, Node newInput) {
         if (oldInput != newInput) {
             if (oldInput != null) {
-                boolean result = removeThisFromUsages(oldInput);
-                assert assertTrue(result, "not found in usages, old input: %s", oldInput);
+                if (oldInput.recordsUsages()) {
+                    boolean result = removeThisFromUsages(oldInput);
+                    assert assertTrue(result, "not found in usages, old input: %s", oldInput);
+                }
             }
             if (newInput != null) {
-                NodeChangedListener listener = graph.inputChangedListener;
-                if (listener != null) {
-                    listener.nodeChanged(this);
+                if (newInput.recordsUsages()) {
+                    NodeChangedListener listener = graph.inputChangedListener;
+                    if (listener != null) {
+                        listener.nodeChanged(this);
+                    }
+                    newInput.addUsage(this);
                 }
-                newInput.addUsage(this);
-            } else if (oldInput != null && oldInput.usages().isEmpty()) {
+            } else if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) {
                 NodeChangedListener listener = graph.usagesDroppedToZeroListener;
                 if (listener != null) {
                     listener.nodeChanged(oldInput);
@@ -513,7 +531,9 @@
                 if (listener != null) {
                     listener.nodeChanged(usage);
                 }
-                other.addUsage(usage);
+                if (other.recordsUsages()) {
+                    other.addUsage(usage);
+                }
             }
         }
         clearUsages();
@@ -554,11 +574,13 @@
         assert assertFalse(isDeleted(), "cannot clear inputs of deleted node");
 
         for (Node input : inputs()) {
-            removeThisFromUsages(input);
-            if (input.usages().isEmpty()) {
-                NodeChangedListener listener = graph.usagesDroppedToZeroListener;
-                if (listener != null) {
-                    listener.nodeChanged(input);
+            if (input.recordsUsages()) {
+                removeThisFromUsages(input);
+                if (input.usages().isEmpty()) {
+                    NodeChangedListener listener = graph.usagesDroppedToZeroListener;
+                    if (listener != null) {
+                        listener.nodeChanged(input);
+                    }
                 }
             }
         }
@@ -580,7 +602,9 @@
     }
 
     private boolean checkDeletion() {
-        assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages());
+        if (recordsUsages()) {
+            assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages());
+        }
         assertTrue(predecessor == null, "cannot delete node %s because of predecessor: %s", this, predecessor);
         return true;
     }
@@ -603,7 +627,9 @@
         NodeClass clazz = getNodeClass();
         clazz.copyInputs(this, newNode);
         for (Node input : inputs()) {
-            input.addUsage(newNode);
+            if (input.recordsUsages()) {
+                input.addUsage(newNode);
+            }
         }
         return newNode;
     }
@@ -676,16 +702,18 @@
         assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id);
         assertTrue(graph() != null, "null graph");
         for (Node input : inputs()) {
-            assertTrue(input.usages().contains(this), "missing usage in input %s", input);
+            assertTrue(!input.recordsUsages() || input.usages().contains(this), "missing usage in input %s", input);
             assertTrue(input.graph() == graph(), "mismatching graph in input %s", input);
         }
         for (Node successor : successors()) {
             assertTrue(successor.predecessor() == this, "missing predecessor in %s (actual: %s)", successor, successor.predecessor());
             assertTrue(successor.graph() == graph(), "mismatching graph in successor %s", successor);
         }
-        for (Node usage : usages()) {
-            assertFalse(usage.isDeleted(), "usage must never be deleted");
-            assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage);
+        if (recordsUsages()) {
+            for (Node usage : usages()) {
+                assertFalse(usage.isDeleted(), "usage must never be deleted");
+                assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage);
+            }
         }
         if (predecessor != null) {
             assertFalse(predecessor.isDeleted(), "predecessor must never be deleted");
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Oct 25 01:39:54 2013 +0200
@@ -1189,6 +1189,7 @@
                 return new Iterator<NodeClass.Position>() {
                     int i = 0;
 
+                    @Override
                     public void remove() {
                         throw new UnsupportedOperationException();
                     }
@@ -1219,6 +1220,7 @@
                 return new Iterator<NodeClass.Position>() {
                     int i = 0;
 
+                    @Override
                     public void remove() {
                         throw new UnsupportedOperationException();
                     }
@@ -1313,7 +1315,7 @@
                     newNodes.put(node, replacement);
                 } else {
                     Node newNode = node.clone(graph, false);
-                    assert newNode.usages().count() == 0 || newNode.inputs().count() == 0;
+                    assert newNode.inputs().count() == 0 || newNode.usages().count() == 0;
                     assert newNode.getClass() == node.getClass();
                     newNodes.put(node, newNode);
                 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Oct 25 01:39:54 2013 +0200
@@ -252,7 +252,7 @@
     /**
      * @param installedCodeOwner see {@link Backend#emitCode}
      */
-    protected void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) {
+    public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) {
         HotSpotProviders providers = getProviders();
         if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) {
             tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
@@ -282,14 +282,14 @@
     /**
      * @param installedCodeOwner see {@link Backend#emitCode}
      */
-    protected void emitCodeBody(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen) {
+    public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen) {
         lirGen.lir.emitCode(tasm);
     }
 
     /**
      * @param installedCodeOwner see {@link Backend#emitCode}
      */
-    protected void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen, AMD64MacroAssembler asm, FrameMap frameMap) {
+    public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, LIRGenerator lirGen, AMD64MacroAssembler asm, FrameMap frameMap) {
         HotSpotProviders providers = getProviders();
         HotSpotFrameContext frameContext = (HotSpotFrameContext) tasm.frameContext;
         if (frameContext != null && !frameContext.isStub) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Oct 25 01:39:54 2013 +0200
@@ -265,9 +265,9 @@
         if (linkage.canDeoptimize()) {
             assert info != null || stub != null;
             Register thread = getProviders().getRegisters().getThreadRegister();
-            append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset, thread));
+            append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread));
             result = super.emitForeignCall(linkage, info, args);
-            append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset, config.threadLastJavaFpOffset, thread));
+            append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread));
         } else {
             result = super.emitForeignCall(linkage, null, args);
         }
@@ -521,7 +521,7 @@
     }
 
     private int getLogMinObjectAlignment() {
-        return config.logMinObjAlignment;
+        return config.logMinObjAlignment();
     }
 
     private int getNarrowOopShift() {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Fri Oct 25 01:39:54 2013 +0200
@@ -210,7 +210,7 @@
         }
     }
 
-    private static void decodePointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) {
+    public static void decodePointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) {
         // If the base is zero, the compressed address has to be shifted left
         // in order to be uncompressed.
         if (base == 0) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Fri Oct 25 01:39:54 2013 +0200
@@ -27,6 +27,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
@@ -57,9 +58,19 @@
         emitCode(tasm, asm, config, false, state, scratch.getRegister());
     }
 
+    /**
+     * Tests if the polling page address can be reached from the code cache with 32-bit
+     * displacements.
+     */
+    private static boolean isPollingPageFar(HotSpotVMConfig config) {
+        final long pollingPageAddress = config.safepointPollingAddress;
+        // TODO return ForceUnreachable ||
+        return !NumUtil.isInt(pollingPageAddress - config.codeCacheLowBoundary()) || !NumUtil.isInt(pollingPageAddress - config.codeCacheHighBoundary());
+    }
+
     public static void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
         final int pos = asm.codeBuffer.position();
-        if (config.isPollingPageFar) {
+        if (isPollingPageFar(config)) {
             asm.movq(scratch, config.safepointPollingAddress);
             tasm.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR);
             if (state != null) {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Fri Oct 25 01:39:54 2013 +0200
@@ -60,7 +60,7 @@
         assert access == null || access instanceof HeapAccess;
         if (config.useCompressedOops && isCompressCandidate(access)) {
             Variable scratch = newVariable(Kind.Long);
-            append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment));
+            append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment()));
         } else {
             append(new LoadOp(kind, result, loadAddress, state));
         }
@@ -74,7 +74,7 @@
         Variable input = load(inputVal);
         if (config.useCompressedOops && isCompressCandidate(access)) {
             Variable scratch = newVariable(Kind.Long);
-            append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment));
+            append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment()));
         } else {
             append(new StoreOp(kind, storeAddress, input, state));
         }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Fri Oct 25 01:39:54 2013 +0200
@@ -103,9 +103,9 @@
             HotSpotRegistersProvider registers = getProviders().getRegisters();
             Register thread = registers.getThreadRegister();
             Register stackPointer = registers.getStackPointerRegister();
-            append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset, thread, stackPointer));
+            append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread, stackPointer));
             result = super.emitForeignCall(linkage, info, args);
-            append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset, config.threadLastJavaPcOffset, config.threadJavaFrameAnchorFlagsOffset, thread));
+            append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), thread));
         } else {
             result = super.emitForeignCall(linkage, null, args);
         }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Fri Oct 25 01:39:54 2013 +0200
@@ -61,7 +61,6 @@
     public static void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
         final int pos = masm.codeBuffer.position();
         new Setx(config.safepointPollingAddress, scratch).emit(masm);
-        assert !config.isPollingPageFar;
         tasm.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR);
         if (state != null) {
             tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Fri Oct 25 01:39:54 2013 +0200
@@ -48,7 +48,7 @@
     @Override
     protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
         HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, true);
+        HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, compResult.getName(), true);
         HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(hsMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult);
         CodeInstallResult result = runtime().getCompilerToVM().installCode(compiledNmethod, installedCode, null);
         Assert.assertEquals("Error installing method " + method + ": " + result, result, CodeInstallResult.OK);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Fri Oct 25 01:39:54 2013 +0200
@@ -175,7 +175,7 @@
     }
 
     public static Object test5Snippet() throws Exception {
-        return UnsafeLoadNode.load(wr, useCompressedOops() ? 12 : 16, Kind.Object);
+        return UnsafeLoadNode.load(wr, useCompressedOops() ? 12 : 16, Kind.Object, LocationIdentity.ANY_LOCATION);
     }
 
     /**
@@ -250,7 +250,7 @@
     public static Object testUnsafeLoad(Object a, Object b, Object c) throws Exception {
         final int offset = (c == null ? 0 : ((Integer) c).intValue());
         final long displacement = (b == null ? 0 : ((Long) b).longValue());
-        return UnsafeLoadNode.load(a, offset + displacement, Kind.Object);
+        return UnsafeLoadNode.load(a, offset + displacement, Kind.Object, LocationIdentity.ANY_LOCATION);
     }
 
     private HotSpotInstalledCode getInstalledCode(String name) throws Exception {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Fri Oct 25 01:39:54 2013 +0200
@@ -174,7 +174,7 @@
         if (value != null) {
             OptionValue<?> optionValue = desc.getOptionValue();
             optionValue.setValue(value);
-            // Logger.info("Set option " + fieldName + " to " + value);
+            // Logger.info("Set option " + desc.getName() + " to " + value);
         } else {
             Logger.info("Wrong value \"" + valueString + "\" for option " + optionName);
             return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Oct 25 01:39:54 2013 +0200
@@ -22,274 +22,792 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.graph.UnsafeAccess.*;
+
 import java.lang.reflect.*;
+import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.bridge.*;
-import com.sun.management.HotSpotDiagnosticMXBean;
-
-import sun.management.ManagementFactoryHelper;
 
 /**
  * Used to access native configuration details.
  * 
- * All non-static, public fields in this class are final so that they can be compiled as constants.
+ * All non-static, public fields in this class are so that they can be compiled as constants.
  */
-public final class HotSpotVMConfig extends CompilerObject {
+public class HotSpotVMConfig extends CompilerObject {
 
     private static final long serialVersionUID = -4744897993263044184L;
 
-    private static final HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
+    HotSpotVMConfig(CompilerToVM compilerToVm) {
+        compilerToVm.initializeConfiguration(this);
+
+        // Fill the VM fields hash map.
+        HashMap<String, VMFields.Field> vmFields = new HashMap<>();
+        for (VMFields.Field e : new VMFields(gHotSpotVMStructs)) {
+            vmFields.put(e.getName(), e);
+        }
+
+        // Fill the VM types hash map.
+        HashMap<String, VMTypes.Type> vmTypes = new HashMap<>();
+        for (VMTypes.Type e : new VMTypes(gHotSpotVMTypes)) {
+            vmTypes.put(e.getTypeName(), e);
+        }
+
+        // Fill the VM constants hash map.
+        HashMap<String, AbstractConstant> vmConstants = new HashMap<>();
+        for (AbstractConstant e : new VMIntConstants(gHotSpotVMIntConstants)) {
+            vmConstants.put(e.getName(), e);
+        }
+        for (AbstractConstant e : new VMLongConstants(gHotSpotVMLongConstants)) {
+            vmConstants.put(e.getName(), e);
+        }
+
+        // Fill the flags hash map.
+        HashMap<String, Flags.Flag> flags = new HashMap<>();
+        for (Flags.Flag e : new Flags(vmFields, vmTypes)) {
+            flags.put(e.getName(), e);
+        }
 
-    HotSpotVMConfig(CompilerToVM c2vm) {
-        c2vm.initializeConfiguration(this);
+        for (Field f : HotSpotVMConfig.class.getDeclaredFields()) {
+            if (f.isAnnotationPresent(HotSpotVMField.class)) {
+                HotSpotVMField annotation = f.getAnnotation(HotSpotVMField.class);
+                String name = annotation.name();
+                VMFields.Field entry = vmFields.get(name);
+                if (entry == null) {
+                    if (annotation.optional()) {
+                        continue;
+                    } else {
+                        throw new IllegalArgumentException("field not found: " + name);
+                    }
+                }
+                switch (annotation.get()) {
+                    case OFFSET:
+                        setField(f, entry.getOffset());
+                        break;
+                    case ADDRESS:
+                        setField(f, entry.getAddress());
+                        break;
+                    case VALUE:
+                        setField(f, entry.getValue());
+                        break;
+                    default:
+                        throw GraalInternalError.shouldNotReachHere("unknown kind " + annotation.get());
+                }
+            } else if (f.isAnnotationPresent(HotSpotVMType.class)) {
+                HotSpotVMType annotation = f.getAnnotation(HotSpotVMType.class);
+                String name = annotation.name();
+                VMTypes.Type entry = vmTypes.get(name);
+                if (entry == null) {
+                    throw new IllegalArgumentException("type not found: " + name);
+                }
+                switch (annotation.get()) {
+                    case SIZE:
+                        setField(f, entry.getSize());
+                        break;
+                    default:
+                        throw GraalInternalError.shouldNotReachHere("unknown kind " + annotation.get());
+                }
+            } else if (f.isAnnotationPresent(HotSpotVMConstant.class)) {
+                HotSpotVMConstant annotation = f.getAnnotation(HotSpotVMConstant.class);
+                String name = annotation.name();
+                AbstractConstant entry = vmConstants.get(name);
+                if (entry == null) {
+                    if (annotation.optional()) {
+                        continue;
+                    } else {
+                        throw new IllegalArgumentException("constant not found: " + name);
+                    }
+                }
+                setField(f, entry.getValue());
+            } else if (f.isAnnotationPresent(HotSpotVMFlag.class)) {
+                HotSpotVMFlag annotation = f.getAnnotation(HotSpotVMFlag.class);
+                String name = annotation.name();
+                Flags.Flag entry = flags.get(name);
+                if (entry == null) {
+                    if (annotation.optional()) {
+                        continue;
+                    } else {
+                        throw new IllegalArgumentException("flag not found: " + name);
+                    }
+                }
+                setField(f, entry.getValue());
+            }
+        }
+
         assert check();
     }
 
+    private void setField(Field field, Object value) {
+        try {
+            Class<?> fieldType = field.getType();
+            if (fieldType == boolean.class) {
+                if (value instanceof String) {
+                    field.setBoolean(this, Boolean.valueOf((String) value));
+                } else if (value instanceof Boolean) {
+                    field.setBoolean(this, (boolean) value);
+                } else if (value instanceof Long) {
+                    field.setBoolean(this, ((long) value) != 0);
+                } else {
+                    GraalInternalError.shouldNotReachHere(value.getClass().getSimpleName());
+                }
+            } else if (fieldType == int.class) {
+                if (value instanceof Integer) {
+                    field.setInt(this, (int) value);
+                } else if (value instanceof Long) {
+                    field.setInt(this, (int) (long) value);
+                } else {
+                    GraalInternalError.shouldNotReachHere(value.getClass().getSimpleName());
+                }
+            } else if (fieldType == long.class) {
+                field.setLong(this, (long) value);
+            } else {
+                GraalInternalError.shouldNotReachHere(field.toString());
+            }
+        } catch (IllegalAccessException e) {
+            throw GraalInternalError.shouldNotReachHere(field.toString() + ": " + e);
+        }
+    }
+
     /**
-     * Gets the value of an VM option.
-     * 
-     * @param name option's name
-     * @return value of option
-     * @throws IllegalArgumentException if option doesn't exist
+     * VMStructEntry (see vmStructs.hpp).
      */
-    public static int getVMOptionInt(String name) {
-        String value = diagnostic.getVMOption(name).getValue();
-        return Integer.valueOf(value).intValue();
-    }
+    private long gHotSpotVMStructs;
+    private long gHotSpotVMStructEntryTypeNameOffset;
+    private long gHotSpotVMStructEntryFieldNameOffset;
+    private long gHotSpotVMStructEntryTypeStringOffset;
+    private long gHotSpotVMStructEntryIsStaticOffset;
+    private long gHotSpotVMStructEntryOffsetOffset;
+    private long gHotSpotVMStructEntryAddressOffset;
+    private long gHotSpotVMStructEntryArrayStride;
+
+    class VMFields implements Iterable<VMFields.Field> {
+
+        private long address;
+
+        public VMFields(long address) {
+            this.address = address;
+        }
+
+        public Iterator<VMFields.Field> iterator() {
+            return new Iterator<VMFields.Field>() {
+
+                private int index = 0;
+
+                private Field current() {
+                    return new Field(address + gHotSpotVMStructEntryArrayStride * index);
+                }
+
+                /**
+                 * The last entry is identified by a NULL fieldName.
+                 */
+                public boolean hasNext() {
+                    Field entry = current();
+                    return entry.getFieldName() != null;
+                }
+
+                public Field next() {
+                    Field entry = current();
+                    index++;
+                    return entry;
+                }
+
+                @Override
+                public void remove() {
+                    throw GraalInternalError.unimplemented();
+                }
+            };
+        }
+
+        class Field {
+
+            private long entryAddress;
 
-    /**
-     * Gets the value of an VM option.
-     * 
-     * @param name option's name
-     * @param defaultValue default value if option is not exists (e.g. development options)
-     * @return value of option or defaultValue if option doesn't exist
-     */
-    public static int getVMOption(String name, int defaultValue) {
-        try {
-            return getVMOptionInt(name);
-        } catch (IllegalArgumentException e) {
-            return defaultValue;
+            Field(long address) {
+                this.entryAddress = address;
+            }
+
+            public String getTypeName() {
+                long typeNameAddress = unsafe.getAddress(entryAddress + gHotSpotVMStructEntryTypeNameOffset);
+                return readCStringAsString(typeNameAddress);
+            }
+
+            public String getFieldName() {
+                long fieldNameAddress = unsafe.getAddress(entryAddress + gHotSpotVMStructEntryFieldNameOffset);
+                return readCStringAsString(fieldNameAddress);
+            }
+
+            public String getTypeString() {
+                long typeStringAddress = unsafe.getAddress(entryAddress + gHotSpotVMStructEntryTypeStringOffset);
+                return readCStringAsString(typeStringAddress);
+            }
+
+            public boolean isStatic() {
+                return unsafe.getInt(entryAddress + gHotSpotVMStructEntryIsStaticOffset) != 0;
+            }
+
+            public long getOffset() {
+                return unsafe.getLong(entryAddress + gHotSpotVMStructEntryOffsetOffset);
+            }
+
+            public long getAddress() {
+                return unsafe.getAddress(entryAddress + gHotSpotVMStructEntryAddressOffset);
+            }
+
+            public String getName() {
+                String typeName = getTypeName();
+                String fieldName = getFieldName();
+                return typeName + "::" + fieldName;
+            }
+
+            public long getValue() {
+                String type = getTypeString();
+                switch (type) {
+                    case "int":
+                        return unsafe.getInt(getAddress());
+                    case "address":
+                    case "intptr_t":
+                        return unsafe.getAddress(getAddress());
+                    default:
+                        // All foo* types are addresses.
+                        if (type.endsWith("*")) {
+                            return unsafe.getAddress(getAddress());
+                        }
+                        throw GraalInternalError.shouldNotReachHere(type);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return String.format("Field[typeName=%s, fieldName=%s, typeString=%s, isStatic=%b, offset=%d, address=0x%x]", getTypeName(), getFieldName(), getTypeString(), isStatic(), getOffset(),
+                                getAddress());
+            }
         }
     }
 
     /**
-     * Gets the value of an VM option.
-     * 
-     * @param name option's name
-     * @return value of option
-     * @throws IllegalArgumentException if option doesn't exist
+     * VMTypeEntry (see vmStructs.hpp).
      */
-    public static boolean getVMOption(String name) {
-        String value = diagnostic.getVMOption(name).getValue();
-        return Boolean.valueOf(value).booleanValue();
+    private long gHotSpotVMTypes;
+    private long gHotSpotVMTypeEntryTypeNameOffset;
+    private long gHotSpotVMTypeEntrySuperclassNameOffset;
+    private long gHotSpotVMTypeEntryIsOopTypeOffset;
+    private long gHotSpotVMTypeEntryIsIntegerTypeOffset;
+    private long gHotSpotVMTypeEntryIsUnsignedOffset;
+    private long gHotSpotVMTypeEntrySizeOffset;
+    private long gHotSpotVMTypeEntryArrayStride;
+
+    class VMTypes implements Iterable<VMTypes.Type> {
+
+        private long address;
+
+        public VMTypes(long address) {
+            this.address = address;
+        }
+
+        public Iterator<VMTypes.Type> iterator() {
+            return new Iterator<VMTypes.Type>() {
+
+                private int index = 0;
+
+                private Type current() {
+                    return new Type(address + gHotSpotVMTypeEntryArrayStride * index);
+                }
+
+                /**
+                 * The last entry is identified by a NULL type name.
+                 */
+                public boolean hasNext() {
+                    Type entry = current();
+                    return entry.getTypeName() != null;
+                }
+
+                public Type next() {
+                    Type entry = current();
+                    index++;
+                    return entry;
+                }
+
+                @Override
+                public void remove() {
+                    throw GraalInternalError.unimplemented();
+                }
+            };
+        }
+
+        class Type {
+
+            private long entryAddress;
+
+            Type(long address) {
+                this.entryAddress = address;
+            }
+
+            public String getTypeName() {
+                long typeNameAddress = unsafe.getAddress(entryAddress + gHotSpotVMTypeEntryTypeNameOffset);
+                return readCStringAsString(typeNameAddress);
+            }
+
+            public String getSuperclassName() {
+                long superclassNameAddress = unsafe.getAddress(entryAddress + gHotSpotVMTypeEntrySuperclassNameOffset);
+                return readCStringAsString(superclassNameAddress);
+            }
+
+            public boolean isOopType() {
+                return unsafe.getInt(entryAddress + gHotSpotVMTypeEntryIsOopTypeOffset) != 0;
+            }
+
+            public boolean isIntegerType() {
+                return unsafe.getInt(entryAddress + gHotSpotVMTypeEntryIsIntegerTypeOffset) != 0;
+            }
+
+            public boolean isUnsigned() {
+                return unsafe.getInt(entryAddress + gHotSpotVMTypeEntryIsUnsignedOffset) != 0;
+            }
+
+            public long getSize() {
+                return unsafe.getLong(entryAddress + gHotSpotVMTypeEntrySizeOffset);
+            }
+
+            @Override
+            public String toString() {
+                return String.format("Type[typeName=%s, superclassName=%s, isOopType=%b, isIntegerType=%b, isUnsigned=%b, size=%d]", getTypeName(), getSuperclassName(), isOopType(), isIntegerType(),
+                                isUnsigned(), getSize());
+            }
+        }
+    }
+
+    public abstract class AbstractConstant {
+
+        protected long address;
+        protected long nameOffset;
+        protected long valueOffset;
+
+        AbstractConstant(long address, long nameOffset, long valueOffset) {
+            this.address = address;
+            this.nameOffset = nameOffset;
+            this.valueOffset = valueOffset;
+        }
+
+        public String getName() {
+            long nameAddress = unsafe.getAddress(address + nameOffset);
+            return readCStringAsString(nameAddress);
+        }
+
+        public abstract long getValue();
+    }
+
+    /**
+     * VMIntConstantEntry (see vmStructs.hpp).
+     */
+    private long gHotSpotVMIntConstants;
+    private long gHotSpotVMIntConstantEntryNameOffset;
+    private long gHotSpotVMIntConstantEntryValueOffset;
+    private long gHotSpotVMIntConstantEntryArrayStride;
+
+    class VMIntConstants implements Iterable<VMIntConstants.Constant> {
+
+        private long address;
+
+        public VMIntConstants(long address) {
+            this.address = address;
+        }
+
+        public Iterator<VMIntConstants.Constant> iterator() {
+            return new Iterator<VMIntConstants.Constant>() {
+
+                private int index = 0;
+
+                private Constant current() {
+                    return new Constant(address + gHotSpotVMIntConstantEntryArrayStride * index);
+                }
+
+                /**
+                 * The last entry is identified by a NULL name.
+                 */
+                public boolean hasNext() {
+                    Constant entry = current();
+                    return entry.getName() != null;
+                }
+
+                public Constant next() {
+                    Constant entry = current();
+                    index++;
+                    return entry;
+                }
+
+                @Override
+                public void remove() {
+                    throw GraalInternalError.unimplemented();
+                }
+            };
+        }
+
+        class Constant extends AbstractConstant {
+
+            Constant(long address) {
+                super(address, gHotSpotVMIntConstantEntryNameOffset, gHotSpotVMIntConstantEntryValueOffset);
+            }
+
+            @Override
+            public long getValue() {
+                return unsafe.getInt(address + valueOffset);
+            }
+
+            @Override
+            public String toString() {
+                return String.format("IntConstant[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue());
+            }
+        }
     }
 
     /**
-     * Gets the value of an VM option.
-     * 
-     * @param name option's name
-     * @param defaultValue default value if option is not exists (e.g. development options)
-     * @return value of option or defaultValue if option doesn't exist
+     * VMLongConstantEntry (see vmStructs.hpp).
      */
-    public static boolean getVMOption(String name, boolean defaultValue) {
-        try {
-            return getVMOption(name);
-        } catch (IllegalArgumentException e) {
-            return defaultValue;
+    private long gHotSpotVMLongConstants;
+    private long gHotSpotVMLongConstantEntryNameOffset;
+    private long gHotSpotVMLongConstantEntryValueOffset;
+    private long gHotSpotVMLongConstantEntryArrayStride;
+
+    class VMLongConstants implements Iterable<VMLongConstants.Constant> {
+
+        private long address;
+
+        public VMLongConstants(long address) {
+            this.address = address;
+        }
+
+        public Iterator<VMLongConstants.Constant> iterator() {
+            return new Iterator<VMLongConstants.Constant>() {
+
+                private int index = 0;
+
+                private Constant currentEntry() {
+                    return new Constant(address + gHotSpotVMLongConstantEntryArrayStride * index);
+                }
+
+                /**
+                 * The last entry is identified by a NULL name.
+                 */
+                public boolean hasNext() {
+                    Constant entry = currentEntry();
+                    return entry.getName() != null;
+                }
+
+                public Constant next() {
+                    Constant entry = currentEntry();
+                    index++;
+                    return entry;
+                }
+
+                @Override
+                public void remove() {
+                    throw GraalInternalError.unimplemented();
+                }
+            };
+        }
+
+        class Constant extends AbstractConstant {
+
+            Constant(long address) {
+                super(address, gHotSpotVMLongConstantEntryNameOffset, gHotSpotVMLongConstantEntryValueOffset);
+            }
+
+            @Override
+            public long getValue() {
+                return unsafe.getLong(address + valueOffset);
+            }
+
+            @Override
+            public String toString() {
+                return String.format("LongConstant[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue());
+            }
         }
     }
 
-    // Using systenm properties ensures the Java source compilers can never
-    // optimize away an access to a config field
-    private static final boolean UNINITIALIZED_BOOLEAN = Boolean.getBoolean("graal.config.uninitializedBoolean");
-    private static final long UNINITIALIZED_LONG = Long.getLong("graal.config.uninitializedLong", 0L);
-    private static final int UNINITIALIZED_INT = Integer.getInteger("graal.config.uninitializedInt", 0);
+    class Flags implements Iterable<Flags.Flag> {
+
+        private long address;
+        private long entrySize;
+        private long typeOffset;
+        private long nameOffset;
+        private long addrOffset;
+
+        public Flags(HashMap<String, VMFields.Field> vmStructs, HashMap<String, VMTypes.Type> vmTypes) {
+            address = vmStructs.get("Flag::flags").getValue();
+            entrySize = vmTypes.get("Flag").getSize();
+            typeOffset = vmStructs.get("Flag::_type").getOffset();
+            nameOffset = vmStructs.get("Flag::_name").getOffset();
+            addrOffset = vmStructs.get("Flag::_addr").getOffset();
+
+            // TODO use the following after we switched to JDK 8
+            assert vmTypes.get("bool").getSize() == Byte.SIZE / Byte.SIZE; // TODO Byte.BYTES;
+            assert vmTypes.get("intx").getSize() == Long.SIZE / Byte.SIZE; // TODO Long.BYTES;
+            assert vmTypes.get("uintx").getSize() == Long.SIZE / Byte.SIZE; // TODO Long.BYTES;
+        }
+
+        public Iterator<Flags.Flag> iterator() {
+            return new Iterator<Flags.Flag>() {
+
+                private int index = 0;
+
+                private Flag current() {
+                    return new Flag(address + entrySize * index);
+                }
+
+                /**
+                 * The last entry is identified by a NULL name.
+                 */
+                public boolean hasNext() {
+                    Flag entry = current();
+                    return entry.getName() != null;
+                }
+
+                public Flag next() {
+                    Flag entry = current();
+                    index++;
+                    return entry;
+                }
 
-    private static int getUninitializedInt() {
-        return UNINITIALIZED_INT;
+                @Override
+                public void remove() {
+                    throw GraalInternalError.unimplemented();
+                }
+            };
+        }
+
+        class Flag {
+
+            private long entryAddress;
+
+            Flag(long address) {
+                this.entryAddress = address;
+            }
+
+            public String getType() {
+                long typeAddress = unsafe.getAddress(entryAddress + typeOffset);
+                return readCStringAsString(typeAddress);
+            }
+
+            public String getName() {
+                long nameAddress = unsafe.getAddress(entryAddress + nameOffset);
+                return readCStringAsString(nameAddress);
+            }
+
+            public long getAddr() {
+                return unsafe.getAddress(entryAddress + addrOffset);
+            }
+
+            public Object getValue() {
+                switch (getType()) {
+                    case "bool":
+                        return Boolean.valueOf(unsafe.getByte(getAddr()) != 0);
+                    case "intx":
+                    case "uintx":
+                    case "uint64_t":
+                        return Long.valueOf(unsafe.getLong(getAddr()));
+                    case "double":
+                        return Double.valueOf(unsafe.getDouble(getAddr()));
+                    case "ccstr":
+                    case "ccstrlist":
+                        return readCStringAsString(getAddr());
+                    default:
+                        throw GraalInternalError.shouldNotReachHere(getType());
+                }
+            }
+
+            @Override
+            public String toString() {
+                return String.format("Flag[type=%s, name=%s, value=%s]", getType(), getName(), getValue());
+            }
+        }
     }
 
-    private static long getUninitializedLong() {
-        return UNINITIALIZED_LONG;
-    }
-
-    private static boolean getUninitializedBoolean() {
-        return UNINITIALIZED_BOOLEAN;
+    /**
+     * Read a null-terminated C string from memory and convert it to a Java String.
+     */
+    private static String readCStringAsString(long address) {
+        if (address == 0) {
+            return null;
+        }
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0;; i++) {
+            char c = (char) unsafe.getByte(address + i);
+            if (c == 0) {
+                break;
+            }
+            sb.append(c);
+        }
+        return sb.toString();
     }
 
     // os information, register layout, code generation, ...
-    public final boolean cAssertions = getUninitializedBoolean();
+    @HotSpotVMConstant(name = "ASSERT") @Stable public boolean cAssertions;
     public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
-    public final int codeEntryAlignment = getUninitializedInt();
-    public final boolean verifyOops = getVMOption("VerifyOops", false);
-    public final boolean ciTime = getVMOption("CITime");
-    public final int compileThreshold = getVMOptionInt("CompileThreshold");
-    public final boolean compileTheWorld = getVMOption("CompileTheWorld", false);
-    public final int compileTheWorldStartAt = getVMOption("CompileTheWorldStartAt", 1);
-    public final int compileTheWorldStopAt = getVMOption("CompileTheWorldStopAt", Integer.MAX_VALUE);
-    public final boolean printCompilation = getVMOption("PrintCompilation");
-    public final boolean printInlining = getVMOption("PrintInlining", false);
-    public final boolean useFastLocking = getVMOption("GraalUseFastLocking", true);
-    public final boolean useTLAB = getVMOption("UseTLAB");
-    public final boolean useBiasedLocking = getVMOption("UseBiasedLocking");
-    public final boolean usePopCountInstruction = getVMOption("UsePopCountInstruction");
-    public final boolean useAESIntrinsics = getVMOption("UseAESIntrinsics");
-    public final boolean useCRC32Intrinsics = getVMOption("UseCRC32Intrinsics");
-    public final boolean useG1GC = getVMOption("UseG1GC");
-    public final long gcTotalCollectionsAddress = getUninitializedLong();
-    public final boolean useDeferredInitBarriers = getVMOption("GraalDeferredInitBarriers");
+
+    @HotSpotVMFlag(name = "CodeEntryAlignment") @Stable public int codeEntryAlignment;
+    @HotSpotVMFlag(name = "VerifyOops") @Stable public boolean verifyOops;
+    @HotSpotVMFlag(name = "CITime") @Stable public boolean ciTime;
+    @HotSpotVMFlag(name = "CompileThreshold") @Stable public long compileThreshold;
+    @HotSpotVMFlag(name = "CompileTheWorld") @Stable public boolean compileTheWorld;
+    @HotSpotVMFlag(name = "CompileTheWorldStartAt") @Stable public int compileTheWorldStartAt;
+    @HotSpotVMFlag(name = "CompileTheWorldStopAt") @Stable public int compileTheWorldStopAt;
+    @HotSpotVMFlag(name = "PrintCompilation") @Stable public boolean printCompilation;
+    @HotSpotVMFlag(name = "PrintInlining") @Stable public boolean printInlining;
+    @HotSpotVMFlag(name = "GraalUseFastLocking") @Stable public boolean useFastLocking;
+
+    @HotSpotVMFlag(name = "UseTLAB") @Stable public boolean useTLAB;
+    @HotSpotVMFlag(name = "UseBiasedLocking") @Stable public boolean useBiasedLocking;
+    @HotSpotVMFlag(name = "UsePopCountInstruction") @Stable public boolean usePopCountInstruction;
+    @HotSpotVMFlag(name = "UseAESIntrinsics") @Stable public boolean useAESIntrinsics;
+    @HotSpotVMFlag(name = "UseCRC32Intrinsics") @Stable public boolean useCRC32Intrinsics;
+    @HotSpotVMFlag(name = "UseG1GC") @Stable public boolean useG1GC;
+
+    @HotSpotVMField(name = "Universe::_collectedHeap", get = HotSpotVMField.Type.VALUE) @Stable private long universeCollectedHeap;
+    @HotSpotVMField(name = "CollectedHeap::_total_collections", get = HotSpotVMField.Type.OFFSET) @Stable private int collectedHeapTotalCollectionsOffset;
+
+    public long gcTotalCollectionsAddress() {
+        return universeCollectedHeap + collectedHeapTotalCollectionsOffset;
+    }
+
+    @HotSpotVMFlag(name = "GraalDeferredInitBarriers") @Stable public boolean useDeferredInitBarriers;
 
     // Compressed Oops related values.
-    public final boolean useCompressedOops = getVMOption("UseCompressedOops");
-    public final boolean useCompressedClassPointers = getVMOption("UseCompressedClassPointers");
-    public final long narrowOopBase = getUninitializedLong();
-    public final int narrowOopShift = getUninitializedInt();
-    public final int logMinObjAlignment = (int) (Math.log(getVMOptionInt("ObjectAlignmentInBytes")) / Math.log(2));
-    public final long narrowKlassBase = getUninitializedLong();
-    public final int narrowKlassShift = getUninitializedInt();
-    public final int logKlassAlignment = getUninitializedInt();
+    @HotSpotVMFlag(name = "UseCompressedOops") @Stable public boolean useCompressedOops;
+    @HotSpotVMFlag(name = "UseCompressedClassPointers") @Stable public boolean useCompressedClassPointers;
+
+    @HotSpotVMField(name = "Universe::_narrow_oop._base", get = HotSpotVMField.Type.VALUE) @Stable public long narrowOopBase;
+    @HotSpotVMField(name = "Universe::_narrow_oop._shift", get = HotSpotVMField.Type.VALUE) @Stable public int narrowOopShift;
+    @HotSpotVMFlag(name = "ObjectAlignmentInBytes") @Stable public int objectAlignment;
+
+    public int logMinObjAlignment() {
+        return (int) (Math.log(objectAlignment) / Math.log(2));
+    }
+
+    @HotSpotVMField(name = "Universe::_narrow_klass._base", get = HotSpotVMField.Type.VALUE) @Stable public long narrowKlassBase;
+    @HotSpotVMField(name = "Universe::_narrow_klass._shift", get = HotSpotVMField.Type.VALUE) @Stable public int narrowKlassShift;
+    @HotSpotVMConstant(name = "LogKlassAlignmentInBytes") @Stable public int logKlassAlignment;
 
     // CPU capabilities
-    public final int useSSE = getVMOptionInt("UseSSE");
-    public final int useAVX = getVMOption("UseAVX", 99);
+    @HotSpotVMFlag(name = "UseSSE") @Stable public int useSSE;
+    @HotSpotVMFlag(name = "UseAVX", optional = true) @Stable public int useAVX;
 
     // offsets, ...
-    public final int stackShadowPages = getVMOptionInt("StackShadowPages");
+    @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages;
 
-    /**
-     * The offset of the mark word in an object's header.
-     */
-    public final int markOffset = getUninitializedInt();
-
-    /**
-     * The offset of the hub (i.e. Klass*) in an object's header.
-     */
-    public final int hubOffset = getUninitializedInt();
+    @HotSpotVMField(name = "oopDesc::_mark", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset;
+    @HotSpotVMField(name = "oopDesc::_metadata._klass", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset;
 
-    /**
-     * The offset of the _prototype_header field in a Klass.
-     */
-    public final int prototypeMarkWordOffset = getUninitializedInt();
+    @HotSpotVMField(name = "Klass::_prototype_header", get = HotSpotVMField.Type.OFFSET) @Stable public int prototypeMarkWordOffset;
+    @HotSpotVMField(name = "Klass::_subklass", get = HotSpotVMField.Type.OFFSET) @Stable public int subklassOffset;
+    @HotSpotVMField(name = "Klass::_next_sibling", get = HotSpotVMField.Type.OFFSET) @Stable public int nextSiblingOffset;
+    @HotSpotVMField(name = "Klass::_super_check_offset", get = HotSpotVMField.Type.OFFSET) @Stable public int superCheckOffsetOffset;
+    @HotSpotVMField(name = "Klass::_secondary_super_cache", get = HotSpotVMField.Type.OFFSET) @Stable public int secondarySuperCacheOffset;
+    @HotSpotVMField(name = "Klass::_secondary_supers", get = HotSpotVMField.Type.OFFSET) @Stable public int secondarySupersOffset;
 
-    /**
-     * The offset of the _subklass field in a Klass.
-     */
-    public final int subklassOffset = getUninitializedInt();
-
-    /**
-     * The offset of the _next_sibling field in a Klass.
-     */
-    public final int nextSiblingOffset = getUninitializedInt();
+    @HotSpotVMType(name = "vtableEntry", get = HotSpotVMType.Type.SIZE) @Stable public int vtableEntrySize;
+    @HotSpotVMField(name = "vtableEntry::_method", get = HotSpotVMField.Type.OFFSET) @Stable public int vtableEntryMethodOffset;
+    @Stable public int instanceKlassVtableStartOffset;
 
     /**
      * The offset of the array length word in an array object's header.
      */
-    public final int arrayLengthOffset = getUninitializedInt();
+    @Stable public int arrayLengthOffset;
+
+    @HotSpotVMField(name = "Array<Klass*>::_length", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayLengthOffset;
+    @HotSpotVMField(name = "Array<Klass*>::_data", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayBaseOffset;
 
-    /**
-     * The offset of the _length field in an Array metaspace object (see array.hpp).
-     */
-    public final int metaspaceArrayLengthOffset = getUninitializedInt();
+    @HotSpotVMField(name = "InstanceKlass::_init_state", get = HotSpotVMField.Type.OFFSET) @Stable public int klassStateOffset;
+    @HotSpotVMConstant(name = "InstanceKlass::fully_initialized") @Stable public int klassStateFullyInitialized;
+    @HotSpotVMField(name = "InstanceKlass::_constants", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassConstantsOffset;
+
+    @HotSpotVMField(name = "ObjArrayKlass::_element_klass", get = HotSpotVMField.Type.OFFSET) @Stable public int arrayClassElementOffset;
 
-    /**
-     * The offset of the _data field in an Array metaspace object (see array.hpp).
-     */
-    public final int metaspaceArrayBaseOffset = getUninitializedInt();
+    @HotSpotVMField(name = "Thread::_tlab", get = HotSpotVMField.Type.OFFSET) @Stable public int threadTlabOffset;
 
-    /**
-     * The offset of the _super_check_offset field in a Klass.
-     */
-    public final int superCheckOffsetOffset = getUninitializedInt();
+    @HotSpotVMField(name = "JavaThread::_anchor", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadAnchorOffset;
+    @HotSpotVMField(name = "JavaThread::_threadObj", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectOffset;
+    @HotSpotVMField(name = "JavaThread::_osthread", get = HotSpotVMField.Type.OFFSET) @Stable public int osThreadOffset;
+    @HotSpotVMField(name = "JavaThread::_dirty_card_queue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadDirtyCardQueueOffset;
+    @HotSpotVMField(name = "JavaThread::_is_method_handle_return", get = HotSpotVMField.Type.OFFSET) @Stable public int threadIsMethodHandleReturnOffset;
+    @HotSpotVMField(name = "JavaThread::_satb_mark_queue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadSatbMarkQueueOffset;
+    @HotSpotVMField(name = "JavaThread::_vm_result", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectResultOffset;
+    @HotSpotVMField(name = "JavaThread::_graal_counters[0]", get = HotSpotVMField.Type.OFFSET, optional = true) @Stable public int graalCountersThreadOffset;
 
-    /**
-     * The offset of the _secondary_super_cache field in a Klass.
-     */
-    public final int secondarySuperCacheOffset = getUninitializedInt();
+    @HotSpotVMConstant(name = "GRAAL_COUNTERS_SIZE", optional = true) @Stable public int graalCountersSize;
 
     /**
-     * The offset of the _secondary_supers field in a Klass.
-     */
-    public final int secondarySupersOffset = getUninitializedInt();
-
-    /**
-     * The offset of the _init_state field in an instanceKlass.
+     * This field is used to pass exception objects into and out of the runtime system during
+     * exception handling for compiled code.
+     * <p>
+     * <b>NOTE: This is not the same as {@link #pendingExceptionOffset}.</b>
      */
-    public final int klassStateOffset = getUninitializedInt();
-
-    /**
-     * The value of instanceKlass::fully_initialized.
-     */
-    public final int klassStateFullyInitialized = getUninitializedInt();
+    @HotSpotVMField(name = "JavaThread::_exception_oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadExceptionOopOffset;
+    @HotSpotVMField(name = "JavaThread::_exception_pc", get = HotSpotVMField.Type.OFFSET) @Stable public int threadExceptionPcOffset;
 
-    /**
-     * The value of objArrayKlass::element_klass_offset().
-     */
-    public final int arrayClassElementOffset = getUninitializedInt();
+    @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_sp", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaSpOffset;
+    @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_pc", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaPcOffset;
+    @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", get = HotSpotVMField.Type.OFFSET, optional = true) @Stable private int javaFrameAnchorLastJavaFpOffset;
+    @HotSpotVMField(name = "JavaFrameAnchor::_flags", get = HotSpotVMField.Type.OFFSET, optional = true) @Stable private int javaFrameAnchorFlagsOffset;
 
-    /**
-     * The value of JavaThread::tlab_top_offset().
-     */
-    public final int threadTlabTopOffset = getUninitializedInt();
+    public int threadLastJavaSpOffset() {
+        return javaThreadAnchorOffset + javaFrameAnchorLastJavaSpOffset;
+    }
 
-    /**
-     * The value of JavaThread::tlab_end_offset().
-     */
-    public final int threadTlabEndOffset = getUninitializedInt();
+    public int threadLastJavaPcOffset() {
+        return javaThreadAnchorOffset + javaFrameAnchorLastJavaPcOffset;
+    }
 
     /**
-     * The value of JavaThread::threadObj_offset().
-     */
-    public final int threadObjectOffset = getUninitializedInt();
-
-    /**
-     * The value of JavaThread::osthread_offset().
-     */
-    public final int osThreadOffset = getUninitializedInt();
-
-    /**
-     * The value of JavaThread::graal_counters_offset().
+     * This value is only valid on AMD64.
      */
-    public final int graalCountersThreadOffset = getUninitializedInt();
-
-    /**
-     * The length of the JavaThread::_graal_counters array.
-     */
-    public final int graalCountersSize = getUninitializedInt();
-
-    /**
-     * The value of OSThread::interrupted_offset().
-     */
-    public final int osThreadInterruptedOffset = getUninitializedInt();
+    public int threadLastJavaFpOffset() {
+        // TODO add an assert for AMD64
+        return javaThreadAnchorOffset + javaFrameAnchorLastJavaFpOffset;
+    }
 
     /**
-     * The value of markOopDesc::unlocked_value.
+     * This value is only valid on SPARC.
      */
-    public final int unlockedMask = getUninitializedInt();
+    public int threadJavaFrameAnchorFlagsOffset() {
+        // TODO add an assert for SPARC
+        return javaThreadAnchorOffset + javaFrameAnchorFlagsOffset;
+    }
+
+    @HotSpotVMField(name = "PtrQueue::_active", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueActiveOffset;
+    @HotSpotVMField(name = "PtrQueue::_buf", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueBufferOffset;
+    @HotSpotVMField(name = "PtrQueue::_index", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueIndexOffset;
+
+    @HotSpotVMField(name = "OSThread::_interrupted", get = HotSpotVMField.Type.OFFSET) @Stable public int osThreadInterruptedOffset;
 
-    /**
-     * The value of markOopDesc::biased_lock_mask_in_place.
-     */
-    public final int biasedLockMaskInPlace = getUninitializedInt();
+    @HotSpotVMConstant(name = "markOopDesc::unlocked_value") @Stable public int unlockedMask;
+    @HotSpotVMConstant(name = "markOopDesc::biased_lock_mask_in_place") @Stable public int biasedLockMaskInPlace;
+    @HotSpotVMConstant(name = "markOopDesc::age_mask_in_place") @Stable public int ageMaskInPlace;
+    @HotSpotVMConstant(name = "markOopDesc::epoch_mask_in_place") @Stable public int epochMaskInPlace;
+
+    @HotSpotVMConstant(name = "markOopDesc::hash_shift") @Stable public long markOopDescHashShift;
+    @HotSpotVMConstant(name = "markOopDesc::hash_mask") @Stable public long markOopDescHashMask;
+    @HotSpotVMConstant(name = "markOopDesc::hash_mask_in_place") @Stable public long markOopDescHashMaskInPlace;
+
+    @HotSpotVMConstant(name = "markOopDesc::biased_lock_pattern") @Stable public int biasedLockPattern;
+    @HotSpotVMConstant(name = "markOopDesc::no_hash_in_place") @Stable public int markWordNoHashInPlace;
+    @HotSpotVMConstant(name = "markOopDesc::no_lock_in_place") @Stable public int markWordNoLockInPlace;
 
     /**
-     * The value of markOopDesc::age_mask_in_place.
+     * See markOopDesc::prototype().
      */
-    public final int ageMaskInPlace = getUninitializedInt();
+    public long arrayPrototypeMarkWord() {
+        return markWordNoHashInPlace | markWordNoLockInPlace;
+    }
 
     /**
-     * The value of markOopDesc::epoch_mask_in_place.
-     */
-    public final int epochMaskInPlace = getUninitializedInt();
-
-    /**
-     * The value of markOopDesc::biased_lock_pattern.
+     * See markOopDesc::copy_set_hash().
      */
-    public final int biasedLockPattern = getUninitializedInt();
-
-    /**
-     * Identity hash code value when uninitialized.
-     */
-    public final int uninitializedIdentityHashCodeValue = getUninitializedInt();
+    public long tlabIntArrayMarkWord() {
+        long tmp = arrayPrototypeMarkWord() & (~markOopDescHashMaskInPlace);
+        tmp |= ((0x2 & markOopDescHashMask) << markOopDescHashShift);
+        return tmp;
+    }
 
     /**
      * Offset of the _pending_exception field in ThreadShadow (defined in exceptions.hpp). This
@@ -297,301 +815,344 @@
      * <p>
      * <b>NOTE: This is not the same as {@link #threadExceptionOopOffset}.</b>
      */
-    public final int pendingExceptionOffset = getUninitializedInt();
-
-    /**
-     * Offset of the pending deoptimization field.
-     */
-    public final int pendingDeoptimizationOffset = getUninitializedInt();
+    @HotSpotVMField(name = "ThreadShadow::_pending_exception", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingExceptionOffset;
+    @HotSpotVMField(name = "ThreadShadow::_pending_deoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingDeoptimizationOffset;
 
     /**
      * Mark word right shift to get identity hash code.
      */
-    public final int identityHashCodeShift = getUninitializedInt();
-
-    /**
-     * Offset of _access_flags in a metaspace Method object.
-     */
-    public final int methodAccessFlagsOffset = getUninitializedInt();
-
-    /**
-     * JVM_ACC_QUEUED defined in accessFlags.hpp and used for marking a Method object as queued for
-     * compilation.
-     */
-    public final int methodQueuedForCompilationBit = getUninitializedInt();
+    @HotSpotVMConstant(name = "markOopDesc::hash_shift") @Stable public int identityHashCodeShift;
 
     /**
-     * Offset of _intrinsic_id in a metaspace Method object.
-     */
-    public final int methodIntrinsicIdOffset = getUninitializedInt();
-
-    /**
-     * Offset of _max_locals in a metaspace Method object.
+     * Identity hash code value when uninitialized.
      */
-    public final int methodMaxLocalsOffset = getUninitializedInt();
-
-    /**
-     * Offset of _constMethod in a metaspace Method object.
-     */
-    public final int methodConstMethodOffset = getUninitializedInt();
+    @HotSpotVMConstant(name = "markOopDesc::no_hash") @Stable public int uninitializedIdentityHashCodeValue;
 
     /**
-     * Offset of _max_stack in a metaspace ConstMethod object.
+     * Used for marking a Method object as queued for compilation.
      */
-    public final int constMethodMaxStackOffset = getUninitializedInt();
+    @HotSpotVMConstant(name = "JVM_ACC_QUEUED") @Stable public int methodQueuedForCompilationBit;
 
-    /**
-     * Offset of _constants in a metaspace ConstMethod object.
-     */
-    public final int constMethodConstantsOffset = getUninitializedInt();
+    @HotSpotVMField(name = "Method::_access_flags", get = HotSpotVMField.Type.OFFSET) @Stable public int methodAccessFlagsOffset;
+    @HotSpotVMField(name = "Method::_constMethod", get = HotSpotVMField.Type.OFFSET) @Stable public int methodConstMethodOffset;
+    @HotSpotVMField(name = "Method::_intrinsic_id", get = HotSpotVMField.Type.OFFSET) @Stable public int methodIntrinsicIdOffset;
+    @HotSpotVMField(name = "Method::_vtable_index", get = HotSpotVMField.Type.OFFSET) @Stable public int methodVtableIndexOffset;
 
     /**
-     * Offset of _pool_holder in a metaspace ConstantPool object.
+     * Value of Method::extra_stack_entries().
      */
-    public final int constantPoolHolderOffset = getUninitializedInt();
-
-    /**
-     * Value of extra_stack_entries() in method.hpp.
-     */
-    public final int extraStackEntries = getUninitializedInt();
+    @Stable public int extraStackEntries;
 
-    /**
-     * Value of JVM_ACC_HAS_FINALIZER in accessFlags.hpp.
-     */
-    public final int klassHasFinalizerFlag = getUninitializedInt();
+    @HotSpotVMField(name = "ConstMethod::_max_stack", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodMaxStackOffset;
+    @HotSpotVMField(name = "ConstMethod::_max_locals", get = HotSpotVMField.Type.OFFSET) @Stable public int methodMaxLocalsOffset;
+    @HotSpotVMField(name = "ConstMethod::_constants", get = HotSpotVMField.Type.OFFSET) @Stable public int constMethodConstantsOffset;
 
-    /**
-     * The value of JavaThread::is_method_handle_return_offset().
-     */
-    public final int threadIsMethodHandleReturnOffset = getUninitializedInt();
+    @HotSpotVMField(name = "ConstantPool::_pool_holder", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolHolderOffset;
+    @HotSpotVMField(name = "ConstantPool::_length", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolLengthOffset;
+
+    @HotSpotVMConstant(name = "JVM_ACC_HAS_FINALIZER") @Stable public int klassHasFinalizerFlag;
 
     /**
      * Bit pattern that represents a non-oop. Neither the high bits nor the low bits of this value
      * are allowed to look like (respectively) the high or low bits of a real oop.
      */
-    public final long nonOopBits = getUninitializedLong();
+    @HotSpotVMField(name = "Universe::_non_oop_bits", get = HotSpotVMField.Type.VALUE) @Stable public long nonOopBits;
+
+    @HotSpotVMField(name = "StubRoutines::_verify_oop_count", get = HotSpotVMField.Type.ADDRESS) @Stable public long verifyOopCounterAddress;
+    @Stable public long verifyOopMask;
+    @Stable public long verifyOopBits;
+
+    @HotSpotVMField(name = "CollectedHeap::_barrier_set", get = HotSpotVMField.Type.OFFSET) @Stable public int collectedHeapBarrierSetOffset;
 
-    public final long verifyOopCounterAddress = getUninitializedLong();
-    public final long verifyOopMask = getUninitializedLong();
-    public final long verifyOopBits = getUninitializedLong();
+    @HotSpotVMField(name = "HeapRegion::LogOfHRGrainBytes", get = HotSpotVMField.Type.VALUE) @Stable public int logOfHRGrainBytes;
+
+    @HotSpotVMField(name = "BarrierSet::_kind", get = HotSpotVMField.Type.OFFSET) @Stable public int barrierSetKindOffset;
+    @HotSpotVMConstant(name = "BarrierSet::CardTableModRef") @Stable public int barrierSetCardTableModRef;
+    @HotSpotVMConstant(name = "BarrierSet::CardTableExtension") @Stable public int barrierSetCardTableExtension;
+    @HotSpotVMConstant(name = "BarrierSet::G1SATBCT") @Stable public int barrierSetG1SATBCT;
+    @HotSpotVMConstant(name = "BarrierSet::G1SATBCTLogging") @Stable public int barrierSetG1SATBCTLogging;
+    @HotSpotVMConstant(name = "BarrierSet::ModRef") @Stable public int barrierSetModRef;
+    @HotSpotVMConstant(name = "BarrierSet::Other") @Stable public int barrierSetOther;
 
-    /**
-     * Offset of the _exception_oop field in Thread (defined in thread.hpp). This field is used to
-     * pass exception objects into and out of the runtime system during exception handling for
-     * compiled code.
-     * <p>
-     * <b>NOTE: This is not the same as {@link #pendingExceptionOffset}.</b>
-     */
-    public final int threadExceptionOopOffset = getUninitializedInt();
+    @HotSpotVMField(name = "CardTableModRefBS::byte_map_base", get = HotSpotVMField.Type.OFFSET) @Stable public int cardTableModRefBSByteMapBaseOffset;
+    @HotSpotVMConstant(name = "CardTableModRefBS::card_shift") @Stable public int cardTableModRefBSCardShift;
+
+    public long cardtableStartAddress() {
+        final long barrierSetAddress = unsafe.getAddress(universeCollectedHeap + collectedHeapBarrierSetOffset);
+        final int kind = unsafe.getInt(barrierSetAddress + barrierSetKindOffset);
+        if ((kind == barrierSetCardTableModRef) || (kind == barrierSetCardTableExtension) || (kind == barrierSetG1SATBCT) || (kind == barrierSetG1SATBCTLogging)) {
+            final long base = unsafe.getAddress(barrierSetAddress + cardTableModRefBSByteMapBaseOffset);
+            assert base != 0 : "unexpected byte_map_base: " + base;
+            return base;
+        }
+        if ((kind == barrierSetModRef) || (kind == barrierSetOther)) {
+            // No post barriers
+            return 0;
+        }
+        throw GraalInternalError.shouldNotReachHere("kind: " + kind);
+    }
 
-    public final int threadExceptionPcOffset = getUninitializedInt();
-    public final long cardtableStartAddress = getUninitializedLong();
-    public final int cardtableShift = getUninitializedInt();
-    public final long safepointPollingAddress = getUninitializedLong();
-    public final boolean isPollingPageFar = getUninitializedBoolean();
+    public int cardtableShift() {
+        final long barrierSetAddress = unsafe.getAddress(universeCollectedHeap + collectedHeapBarrierSetOffset);
+        final int kind = unsafe.getInt(barrierSetAddress + barrierSetKindOffset);
+        if ((kind == barrierSetCardTableModRef) || (kind == barrierSetCardTableExtension) || (kind == barrierSetG1SATBCT) || (kind == barrierSetG1SATBCTLogging)) {
+            return cardTableModRefBSCardShift;
+        }
+        if ((kind == barrierSetModRef) || (kind == barrierSetOther)) {
+            // No post barriers
+            return 0;
+        }
+        throw GraalInternalError.shouldNotReachHere("kind: " + kind);
+    }
+
+    @HotSpotVMField(name = "os::_polling_page", get = HotSpotVMField.Type.VALUE) @Stable public long safepointPollingAddress;
+
+    // G1 Collector Related Values.
 
-    /**
-     * G1 Collector Related Values.
-     */
-    public final int g1CardQueueIndexOffset = getUninitializedInt();
-    public final int g1CardQueueBufferOffset = getUninitializedInt();
-    public final int logOfHRGrainBytes = getUninitializedInt();
-    public final int g1SATBQueueMarkingOffset = getUninitializedInt();
-    public final int g1SATBQueueIndexOffset = getUninitializedInt();
-    public final int g1SATBQueueBufferOffset = getUninitializedInt();
+    public int g1CardQueueIndexOffset() {
+        return javaThreadDirtyCardQueueOffset + ptrQueueIndexOffset;
+    }
+
+    public int g1CardQueueBufferOffset() {
+        return javaThreadDirtyCardQueueOffset + ptrQueueBufferOffset;
+    }
+
+    public int g1SATBQueueMarkingOffset() {
+        return javaThreadSatbMarkQueueOffset + ptrQueueActiveOffset;
+    }
+
+    public int g1SATBQueueIndexOffset() {
+        return javaThreadSatbMarkQueueOffset + ptrQueueIndexOffset;
+    }
+
+    public int g1SATBQueueBufferOffset() {
+        return javaThreadSatbMarkQueueOffset + ptrQueueBufferOffset;
+    }
 
     /**
      * The offset of the _java_mirror field (of type {@link Class}) in a Klass.
      */
-    public final int classMirrorOffset = getUninitializedInt();
-
-    public final int runtimeCallStackSize = getUninitializedInt();
+    @HotSpotVMField(name = "Klass::_java_mirror", get = HotSpotVMField.Type.OFFSET) @Stable public int classMirrorOffset;
 
-    /**
-     * The offset of the _modifier_flags field in a Klass.
-     */
-    public final int klassModifierFlagsOffset = getUninitializedInt();
+    @HotSpotVMConstant(name = "frame::arg_reg_save_area_bytes", optional = true) @Stable public int runtimeCallStackSize;
 
-    /**
-     * The offset of the _access_flags field in a Klass.
-     */
-    public final int klassAccessFlagsOffset = getUninitializedInt();
-
-    /**
-     * The offset of the _layout_helper field in a Klass.
-     */
-    public final int klassLayoutHelperOffset = getUninitializedInt();
+    @HotSpotVMField(name = "Klass::_super", get = HotSpotVMField.Type.OFFSET) @Stable public int klassSuperKlassOffset;
+    @HotSpotVMField(name = "Klass::_modifier_flags", get = HotSpotVMField.Type.OFFSET) @Stable public int klassModifierFlagsOffset;
+    @HotSpotVMField(name = "Klass::_access_flags", get = HotSpotVMField.Type.OFFSET) @Stable public int klassAccessFlagsOffset;
+    @HotSpotVMField(name = "Klass::_layout_helper", get = HotSpotVMField.Type.OFFSET) @Stable public int klassLayoutHelperOffset;
+    @HotSpotVMField(name = "Klass::_layout_helper", get = HotSpotVMField.Type.OFFSET) @Stable public int klassInstanceSizeOffset;
 
     /**
      * Bit pattern in the klass layout helper that can be used to identify arrays.
      */
-    public final int arrayKlassLayoutHelperIdentifier = getUninitializedInt();
+    public final int arrayKlassLayoutHelperIdentifier = 0x80000000;
+
+    @HotSpotVMField(name = "ArrayKlass::_component_mirror", get = HotSpotVMField.Type.OFFSET) @Stable public int arrayKlassComponentMirrorOffset;
+
+    @HotSpotVMField(name = "java_lang_Class::_klass_offset", get = HotSpotVMField.Type.VALUE) @Stable public int klassOffset;
+    @HotSpotVMField(name = "java_lang_Class::_array_klass_offset", get = HotSpotVMField.Type.VALUE) @Stable public int arrayKlassOffset;
+    @HotSpotVMField(name = "java_lang_Class::_graal_mirror_offset", get = HotSpotVMField.Type.VALUE) @Stable public int graalMirrorInClassOffset;
+
+    @HotSpotVMField(name = "Method::_method_data", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOffset;
+    @HotSpotVMField(name = "Method::_from_compiled_entry", get = HotSpotVMField.Type.OFFSET) @Stable public int methodCompiledEntryOffset;
+
+    @HotSpotVMField(name = "nmethod::_verified_entry_point", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodEntryOffset;
+
+    @HotSpotVMType(name = "BasicLock", get = HotSpotVMType.Type.SIZE) @Stable public int basicLockSize;
+    @HotSpotVMField(name = "BasicLock::_displaced_header", get = HotSpotVMField.Type.OFFSET) @Stable public int basicLockDisplacedHeaderOffset;
 
-    /**
-     * The offset of the _componentMirror field in an ArrayKlass.
-     */
-    public final int arrayKlassComponentMirrorOffset = getUninitializedInt();
+    @Stable public long heapEndAddress;
+    @Stable public long heapTopAddress;
+
+    @HotSpotVMField(name = "Thread::_allocated_bytes", get = HotSpotVMField.Type.OFFSET) @Stable public int threadAllocatedBytesOffset;
+
+    @HotSpotVMFlag(name = "TLABWasteIncrement") @Stable public int tlabRefillWasteIncrement;
+    @Stable public int tlabAlignmentReserve;
+
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_start", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferStartOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_end", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferEndOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_top", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferTopOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_slow_allocations", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferSlowAllocationsOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_fast_refill_waste", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferFastRefillWasteOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_number_of_refills", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferNumberOfRefillsOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_refill_waste_limit", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferRefillWasteLimitOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_desired_size", get = HotSpotVMField.Type.OFFSET) @Stable public int threadLocalAllocBufferDesiredSizeOffset;
+
+    public int tlabSlowAllocationsOffset() {
+        return threadTlabOffset + threadLocalAllocBufferSlowAllocationsOffset;
+    }
 
-    /**
-     * The offset of the _super field in a Klass.
-     */
-    public final int klassSuperKlassOffset = getUninitializedInt();
+    public int tlabFastRefillWasteOffset() {
+        return threadTlabOffset + threadLocalAllocBufferFastRefillWasteOffset;
+    }
+
+    public int tlabNumberOfRefillsOffset() {
+        return threadTlabOffset + threadLocalAllocBufferNumberOfRefillsOffset;
+    }
+
+    public int tlabRefillWasteLimitOffset() {
+        return threadTlabOffset + threadLocalAllocBufferRefillWasteLimitOffset;
+    }
+
+    public int threadTlabSizeOffset() {
+        return threadTlabOffset + threadLocalAllocBufferDesiredSizeOffset;
+    }
+
+    public int threadTlabStartOffset() {
+        return threadTlabOffset + threadLocalAllocBufferStartOffset;
+    }
 
-    /**
-     * The offset of the injected klass field in a {@link Class}.
-     */
-    public final int klassOffset = getUninitializedInt();
+    public int threadTlabEndOffset() {
+        return threadTlabOffset + threadLocalAllocBufferEndOffset;
+    }
+
+    public int threadTlabTopOffset() {
+        return threadTlabOffset + threadLocalAllocBufferTopOffset;
+    }
+
+    @HotSpotVMFlag(name = "TLABStats") @Stable public boolean tlabStats;
+    @Stable public boolean inlineContiguousAllocationSupported;
 
-    /**
-     * The offset of the injected array klass field in a {@link Class}.
-     */
-    public final int arrayKlassOffset = getUninitializedInt();
+    @HotSpotVMField(name = "Klass::_layout_helper", get = HotSpotVMField.Type.OFFSET) @Stable public int layoutHelperOffset;
+    @HotSpotVMConstant(name = "Klass::_lh_log2_element_size_shift") @Stable public int layoutHelperLog2ElementSizeShift;
+    @HotSpotVMConstant(name = "Klass::_lh_log2_element_size_mask") @Stable public int layoutHelperLog2ElementSizeMask;
+    @HotSpotVMConstant(name = "Klass::_lh_element_type_shift") @Stable public int layoutHelperElementTypeShift;
+    @HotSpotVMConstant(name = "Klass::_lh_element_type_mask") @Stable public int layoutHelperElementTypeMask;
+    @HotSpotVMConstant(name = "Klass::_lh_header_size_shift") @Stable public int layoutHelperHeaderSizeShift;
+    @HotSpotVMConstant(name = "Klass::_lh_header_size_mask") @Stable public int layoutHelperHeaderSizeMask;
+    @HotSpotVMConstant(name = "Klass::_lh_array_tag_shift") @Stable public int layoutHelperArrayTagShift;
+    @HotSpotVMConstant(name = "Klass::_lh_array_tag_type_value") @Stable public int layoutHelperArrayTagTypeValue;
+    @HotSpotVMConstant(name = "Klass::_lh_array_tag_obj_value") @Stable public int layoutHelperArrayTagObjectValue;
 
     /**
-     * The offset of the injected graal_mirror field in a {@link Class}.
+     * This filters out the bit that differentiates a type array from an object array.
      */
-    public final int graalMirrorInClassOffset = getUninitializedInt();
-
-    /**
-     * The offset of the _method_data field in a metaspace Method.
-     */
-    public final int methodDataOffset = getUninitializedInt();
+    public int layoutHelperElementTypePrimitiveInPlace() {
+        return (layoutHelperArrayTagTypeValue & ~layoutHelperArrayTagObjectValue) << layoutHelperArrayTagShift;
+    }
 
-    public final int nmethodEntryOffset = getUninitializedInt();
-    public final int methodCompiledEntryOffset = getUninitializedInt();
-    public final int basicLockSize = getUninitializedInt();
-    public final int basicLockDisplacedHeaderOffset = getUninitializedInt();
-    public final long tlabIntArrayMarkWord = getUninitializedLong();
-    public final long heapEndAddress = getUninitializedLong();
-    public final long heapTopAddress = getUninitializedLong();
-    public final int threadTlabStartOffset = getUninitializedInt();
-    public final int threadTlabSizeOffset = getUninitializedInt();
-    public final int threadAllocatedBytesOffset = getUninitializedInt();
-    public final int threadLastJavaSpOffset = getUninitializedInt();
-    public final int threadLastJavaPcOffset = getUninitializedInt();
-
-    /**
-     * This value is only valid on AMD64.
-     */
-    public final int threadLastJavaFpOffset = getUninitializedInt();
+    @HotSpotVMField(name = "MethodData::_data[0]", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopDataOffset;
+    @HotSpotVMField(name = "MethodData::_trap_hist._array[0]", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopTrapHistoryOffset;
 
     /**
-     * This value is only valid on SPARC.
+     * The DataLayout header size is the same as the cell size.
      */
-    public final int threadJavaFrameAnchorFlagsOffset = getUninitializedInt();
+    @HotSpotVMConstant(name = "DataLayout::cell_size") @Stable public int dataLayoutHeaderSize;
+    @HotSpotVMField(name = "DataLayout::_header._struct._tag", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutTagOffset;
+    @HotSpotVMField(name = "DataLayout::_header._struct._flags", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutFlagsOffset;
+    @HotSpotVMField(name = "DataLayout::_header._struct._bci", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutBCIOffset;
+    @HotSpotVMField(name = "DataLayout::_cells[0]", get = HotSpotVMField.Type.OFFSET) @Stable public int dataLayoutCellsOffset;
+    @HotSpotVMConstant(name = "DataLayout::cell_size") @Stable public int dataLayoutCellSize;
 
-    public final int threadObjectResultOffset = getUninitializedInt();
-    public final int tlabRefillWasteLimitOffset = getUninitializedInt();
-    public final int tlabRefillWasteIncrement = getUninitializedInt();
-    public final int tlabAlignmentReserve = getUninitializedInt();
-    public final int tlabSlowAllocationsOffset = getUninitializedInt();
-    public final int tlabFastRefillWasteOffset = getUninitializedInt();
-    public final int tlabNumberOfRefillsOffset = getUninitializedInt();
-    public final boolean tlabStats = getVMOption("TLABStats");
-    public final int klassInstanceSizeOffset = getUninitializedInt();
-    public final boolean inlineContiguousAllocationSupported = getUninitializedBoolean();
-    public final long arrayPrototypeMarkWord = getUninitializedLong();
-    public final int layoutHelperLog2ElementSizeShift = getUninitializedInt();
-    public final int layoutHelperLog2ElementSizeMask = getUninitializedInt();
-    public final int layoutHelperElementTypeShift = getUninitializedInt();
-    public final int layoutHelperElementTypeMask = getUninitializedInt();
-    public final int layoutHelperElementTypePrimitiveInPlace = getUninitializedInt();
-    public final int layoutHelperHeaderSizeShift = getUninitializedInt();
-    public final int layoutHelperHeaderSizeMask = getUninitializedInt();
-    public final int layoutHelperOffset = getUninitializedInt();
+    @HotSpotVMFlag(name = "BciProfileWidth") @Stable public int bciProfileWidth;
+    @HotSpotVMFlag(name = "TypeProfileWidth") @Stable public int typeProfileWidth;
+    @HotSpotVMFlag(name = "MethodProfileWidth") @Stable public int methodProfileWidth;
+
+    @HotSpotVMField(name = "CodeBlob::_code_offset", get = HotSpotVMField.Type.OFFSET) @Stable private int codeBlobCodeOffsetOffset;
+    @HotSpotVMField(name = "SharedRuntime::_ic_miss_blob", get = HotSpotVMField.Type.VALUE) @Stable private long inlineCacheMissBlob;
+
+    public long inlineCacheMissStub() {
+        return inlineCacheMissBlob + unsafe.getInt(inlineCacheMissBlob + codeBlobCodeOffsetOffset);
+    }
 
-    // methodData information
-    public final int methodDataOopDataOffset = getUninitializedInt();
-    public final int methodDataOopTrapHistoryOffset = getUninitializedInt();
-    public final int dataLayoutHeaderSize = getUninitializedInt();
-    public final int dataLayoutTagOffset = getUninitializedInt();
-    public final int dataLayoutFlagsOffset = getUninitializedInt();
-    public final int dataLayoutBCIOffset = getUninitializedInt();
-    public final int dataLayoutCellsOffset = getUninitializedInt();
-    public final int dataLayoutCellSize = getUninitializedInt();
+    @HotSpotVMField(name = "CodeCache::_heap", get = HotSpotVMField.Type.VALUE) @Stable private long codeCacheHeap;
+    @HotSpotVMField(name = "CodeHeap::_memory", get = HotSpotVMField.Type.OFFSET) @Stable private int codeHeapMemoryOffset;
+    @HotSpotVMField(name = "VirtualSpace::_low_boundary", get = HotSpotVMField.Type.OFFSET) @Stable private int virtualSpaceLowBoundaryOffset;
+    @HotSpotVMField(name = "VirtualSpace::_high_boundary", get = HotSpotVMField.Type.OFFSET) @Stable private int virtualSpaceHighBoundaryOffset;
 
-    // develop flag; might change
-    public final int bciProfileWidth = getVMOption("BciProfileWidth", 2);
+    /**
+     * @return CodeCache::_heap->_memory._low_boundary
+     */
+    public long codeCacheLowBoundary() {
+        return unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceLowBoundaryOffset);
+    }
 
-    public final int typeProfileWidth = getVMOptionInt("TypeProfileWidth");
-    public final int methodProfileWidth = getVMOptionInt("MethodProfileWidth");
+    /**
+     * @return CodeCache::_heap->_memory._high_boundary
+     */
+    public long codeCacheHighBoundary() {
+        return unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceHighBoundaryOffset);
+    }
 
-    public final long inlineCacheMissStub = getUninitializedLong();
-    public final long handleDeoptStub = getUninitializedLong();
-    public final long uncommonTrapStub = getUninitializedLong();
+    @Stable public long handleDeoptStub;
+    @Stable public long uncommonTrapStub;
 
-    public final long aescryptEncryptBlockStub = getUninitializedLong();
-    public final long aescryptDecryptBlockStub = getUninitializedLong();
-    public final long cipherBlockChainingEncryptAESCryptStub = getUninitializedLong();
-    public final long cipherBlockChainingDecryptAESCryptStub = getUninitializedLong();
-    public final long updateBytesCRC32Stub = getUninitializedLong();
+    @HotSpotVMField(name = "StubRoutines::_aescrypt_encryptBlock", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptEncryptBlockStub;
+    @HotSpotVMField(name = "StubRoutines::_aescrypt_decryptBlock", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptDecryptBlockStub;
+    @HotSpotVMField(name = "StubRoutines::_cipherBlockChaining_encryptAESCrypt", get = HotSpotVMField.Type.VALUE) @Stable public long cipherBlockChainingEncryptAESCryptStub;
+    @HotSpotVMField(name = "StubRoutines::_cipherBlockChaining_decryptAESCrypt", get = HotSpotVMField.Type.VALUE) @Stable public long cipherBlockChainingDecryptAESCryptStub;
+    @HotSpotVMField(name = "StubRoutines::_updateBytesCRC32", get = HotSpotVMField.Type.VALUE) @Stable public long updateBytesCRC32Stub;
+    @HotSpotVMField(name = "StubRoutines::_crc_table_adr", get = HotSpotVMField.Type.VALUE) @Stable public long crcTableAddress;
 
-    public final long newInstanceAddress = getUninitializedLong();
-    public final long newArrayAddress = getUninitializedLong();
-    public final long newMultiArrayAddress = getUninitializedLong();
-    public final long dynamicNewArrayAddress = getUninitializedLong();
-    public final long registerFinalizerAddress = getUninitializedLong();
-    public final long threadIsInterruptedAddress = getUninitializedLong();
-    public final long vmMessageAddress = getUninitializedLong();
-    public final long identityHashCodeAddress = getUninitializedLong();
-    public final long exceptionHandlerForPcAddress = getUninitializedLong();
-    public final long exceptionHandlerForReturnAddressAddress = getUninitializedLong();
-    public final long osrMigrationEndAddress = getUninitializedLong();
-    public final long monitorenterAddress = getUninitializedLong();
-    public final long monitorexitAddress = getUninitializedLong();
-    public final long createNullPointerExceptionAddress = getUninitializedLong();
-    public final long createOutOfBoundsExceptionAddress = getUninitializedLong();
-    public final long logPrimitiveAddress = getUninitializedLong();
-    public final long logObjectAddress = getUninitializedLong();
-    public final long logPrintfAddress = getUninitializedLong();
-    public final long vmErrorAddress = getUninitializedLong();
-    public final long writeBarrierPreAddress = getUninitializedLong();
-    public final long writeBarrierPostAddress = getUninitializedLong();
-    public final long validateObject = getUninitializedLong();
-    public final long javaTimeMillisAddress = getUninitializedLong();
-    public final long javaTimeNanosAddress = getUninitializedLong();
-    public final long arithmeticSinAddress = getUninitializedLong();
-    public final long arithmeticCosAddress = getUninitializedLong();
-    public final long arithmeticTanAddress = getUninitializedLong();
-    public final long loadAndClearExceptionAddress = getUninitializedLong();
-    public final long crcTableAddress = getUninitializedLong();
+    @Stable public long newInstanceAddress;
+    @Stable public long newArrayAddress;
+    @Stable public long newMultiArrayAddress;
+    @Stable public long dynamicNewArrayAddress;
+    @Stable public long registerFinalizerAddress;
+    @Stable public long threadIsInterruptedAddress;
+    @Stable public long vmMessageAddress;
+    @Stable public long identityHashCodeAddress;
+    @Stable public long exceptionHandlerForPcAddress;
+    @Stable public long exceptionHandlerForReturnAddressAddress;
+    @Stable public long osrMigrationEndAddress;
+    @Stable public long monitorenterAddress;
+    @Stable public long monitorexitAddress;
+    @Stable public long createNullPointerExceptionAddress;
+    @Stable public long createOutOfBoundsExceptionAddress;
+    @Stable public long logPrimitiveAddress;
+    @Stable public long logObjectAddress;
+    @Stable public long logPrintfAddress;
+    @Stable public long vmErrorAddress;
+    @Stable public long writeBarrierPreAddress;
+    @Stable public long writeBarrierPostAddress;
+    @Stable public long validateObject;
+    @Stable public long javaTimeMillisAddress;
+    @Stable public long javaTimeNanosAddress;
+    @Stable public long arithmeticSinAddress;
+    @Stable public long arithmeticCosAddress;
+    @Stable public long arithmeticTanAddress;
+    @Stable public long loadAndClearExceptionAddress;
 
-    public final int deoptReasonNone = getUninitializedInt();
-    public final int deoptReasonNullCheck = getUninitializedInt();
-    public final int deoptReasonRangeCheck = getUninitializedInt();
-    public final int deoptReasonClassCheck = getUninitializedInt();
-    public final int deoptReasonArrayCheck = getUninitializedInt();
-    public final int deoptReasonUnreached0 = getUninitializedInt();
-    public final int deoptReasonTypeCheckInlining = getUninitializedInt();
-    public final int deoptReasonOptimizedTypeCheck = getUninitializedInt();
-    public final int deoptReasonNotCompiledExceptionHandler = getUninitializedInt();
-    public final int deoptReasonUnresolved = getUninitializedInt();
-    public final int deoptReasonJsrMismatch = getUninitializedInt();
-    public final int deoptReasonDiv0Check = getUninitializedInt();
-    public final int deoptReasonConstraint = getUninitializedInt();
-    public final int deoptReasonLoopLimitCheck = getUninitializedInt();
+    @HotSpotVMConstant(name = "Deoptimization::Reason_none") @Stable public int deoptReasonNone;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_null_check") @Stable public int deoptReasonNullCheck;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_range_check") @Stable public int deoptReasonRangeCheck;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_class_check") @Stable public int deoptReasonClassCheck;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_array_check") @Stable public int deoptReasonArrayCheck;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_null_assert") @Stable public int deoptReasonUnreached0;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_intrinsic") @Stable public int deoptReasonTypeCheckInlining;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_bimorphic") @Stable public int deoptReasonOptimizedTypeCheck;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_unhandled") @Stable public int deoptReasonNotCompiledExceptionHandler;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_uninitialized") @Stable public int deoptReasonUnresolved;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_age") @Stable public int deoptReasonJsrMismatch;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_div0_check") @Stable public int deoptReasonDiv0Check;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_constraint") @Stable public int deoptReasonConstraint;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_loop_limit_check") @Stable public int deoptReasonLoopLimitCheck;
 
-    public final int deoptActionNone = getUninitializedInt();
-    public final int deoptActionMaybeRecompile = getUninitializedInt();
-    public final int deoptActionReinterpret = getUninitializedInt();
-    public final int deoptActionMakeNotEntrant = getUninitializedInt();
-    public final int deoptActionMakeNotCompilable = getUninitializedInt();
+    @HotSpotVMConstant(name = "Deoptimization::Action_none") @Stable public int deoptActionNone;
+    @HotSpotVMConstant(name = "Deoptimization::Action_maybe_recompile") @Stable public int deoptActionMaybeRecompile;
+    @HotSpotVMConstant(name = "Deoptimization::Action_reinterpret") @Stable public int deoptActionReinterpret;
+    @HotSpotVMConstant(name = "Deoptimization::Action_make_not_entrant") @Stable public int deoptActionMakeNotEntrant;
+    @HotSpotVMConstant(name = "Deoptimization::Action_make_not_compilable") @Stable public int deoptActionMakeNotCompilable;
 
-    public final int vmIntrinsicInvokeBasic = getUninitializedInt();
-    public final int vmIntrinsicLinkToVirtual = getUninitializedInt();
-    public final int vmIntrinsicLinkToStatic = getUninitializedInt();
-    public final int vmIntrinsicLinkToSpecial = getUninitializedInt();
-    public final int vmIntrinsicLinkToInterface = getUninitializedInt();
+    @HotSpotVMConstant(name = "vmIntrinsics::_invokeBasic") @Stable public int vmIntrinsicInvokeBasic;
+    @HotSpotVMConstant(name = "vmIntrinsics::_linkToVirtual") @Stable public int vmIntrinsicLinkToVirtual;
+    @HotSpotVMConstant(name = "vmIntrinsics::_linkToStatic") @Stable public int vmIntrinsicLinkToStatic;
+    @HotSpotVMConstant(name = "vmIntrinsics::_linkToSpecial") @Stable public int vmIntrinsicLinkToSpecial;
+    @HotSpotVMConstant(name = "vmIntrinsics::_linkToInterface") @Stable public int vmIntrinsicLinkToInterface;
 
     public boolean check() {
-        assert codeEntryAlignment > 0 : codeEntryAlignment;
-        assert stackShadowPages > 0;
         for (Field f : getClass().getDeclaredFields()) {
             int modifiers = f.getModifiers();
             if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
-                assert Modifier.isFinal(modifiers) : "field should be final: " + f;
+                assert Modifier.isFinal(modifiers) || f.getAnnotation(Stable.class) != null : "field should either be final or @Stable: " + f;
             }
         }
+
+        assert codeEntryAlignment > 0 : codeEntryAlignment;
+        assert stackShadowPages > 0 : stackShadowPages;
+
+        assert (layoutHelperArrayTagObjectValue & layoutHelperArrayTagTypeValue & arrayKlassLayoutHelperIdentifier) != 0 : "object array and type array must have first bit set";
+
         return true;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConstant.java	Fri Oct 25 01:39:54 2013 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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 java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMConstant {
+
+    String name();
+
+    boolean optional() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMField.java	Fri Oct 25 01:39:54 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMField {
+
+    enum Type {
+        OFFSET, ADDRESS, VALUE;
+    }
+
+    String name();
+
+    Type get();
+
+    boolean optional() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMFlag.java	Fri Oct 25 01:39:54 2013 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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 java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMFlag {
+
+    String name();
+
+    boolean optional() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMType.java	Fri Oct 25 01:39:54 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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 java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotSpotVMType {
+
+    enum Type {
+        SIZE;
+    }
+
+    String name();
+
+    Type get();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/Stable.java	Fri Oct 25 01:39:54 2013 +0200
@@ -0,0 +1,33 @@
+/*
+ * 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 java.lang.annotation.*;
+
+// TODO remove this annotation after we moved to JDK 8 and use sun.invoke.Stable instead
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Stable {
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Oct 25 01:39:54 2013 +0200
@@ -120,8 +120,6 @@
      */
     JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve);
 
-    int constantPoolLength(HotSpotResolvedObjectType pool);
-
     Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi);
 
     JavaMethod lookupMethodInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
@@ -202,10 +200,6 @@
 
     Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
-    int getVtableEntryOffset(long metaspaceMethod);
-
-    boolean hasVtableEntry(long metaspaceMethod);
-
     long[] getDeoptedLeafGraphIds();
 
     long[] getLineNumberTable(HotSpotResolvedJavaMethod method);
@@ -218,6 +212,8 @@
 
     long readUnsafeKlassPointer(Object o);
 
+    void doNotInlineOrCompile(long metaspaceMethod);
+
     /**
      * Invalidates the profiling information and restarts profiling upon the next invocation.
      * 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Oct 25 01:39:54 2013 +0200
@@ -76,9 +76,6 @@
     public native JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve);
 
     @Override
-    public native int constantPoolLength(HotSpotResolvedObjectType pool);
-
-    @Override
     public native Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi);
 
     @Override
@@ -145,12 +142,6 @@
     public native Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode);
 
     @Override
-    public native int getVtableEntryOffset(long metaspaceMethod);
-
-    @Override
-    public native boolean hasVtableEntry(long metaspaceMethod);
-
-    @Override
     public native long[] getDeoptedLeafGraphIds();
 
     @Override
@@ -178,6 +169,9 @@
     public native long readUnsafeKlassPointer(Object o);
 
     @Override
+    public native void doNotInlineOrCompile(long metaspaceMethod);
+
+    @Override
     public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
         return executeCompiledMethodIntrinsic(arg1, arg2, arg3, hotspotInstalledCode);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Oct 25 01:39:54 2013 +0200
@@ -401,7 +401,7 @@
             CompilationTask.withinEnqueue.set(Boolean.FALSE);
         }
 
-        if (Debug.isEnabled() && areDebugScopePatternsEnabled()) {
+        if (Debug.isEnabled() && areMetricsOrTimersEnabled()) {
             List<DebugValueMap> topLevelMaps = DebugValueMap.getTopLevelMaps();
             List<DebugValue> debugValues = KeyRegistry.getDebugValues();
             if (debugValues.size() > 0) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Fri Oct 25 01:39:54 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
 import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.printer.*;
 
 /**
@@ -157,7 +158,7 @@
     }
 
     public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) {
-        HotSpotInstalledCode installedCode = new HotSpotNmethod(method, true);
+        HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), true);
         runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(method, entryBCI, compResult), installedCode, method.getSpeculationLog());
         return installedCode;
     }
@@ -165,7 +166,7 @@
     @Override
     public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, false);
+        HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
         CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(hotspotMethod, -1, compResult), code, null);
         if (result != CodeInstallResult.OK) {
             return null;
@@ -173,10 +174,15 @@
         return code;
     }
 
+    public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+        HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
+        return installMethod(hotspotMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult);
+    }
+
     public InstalledCode addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
 
         HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotInstalledCode icode = new HotSpotNmethod(javaMethod, false, true);
+        HotSpotInstalledCode icode = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
         HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, -1, compResult);
         CompilerToVM vm = runtime.getCompilerToVM();
         CodeInstallResult result = vm.installCode(compiled, icode, null);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Fri Oct 25 01:39:54 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import com.oracle.graal.api.meta.*;
@@ -43,7 +44,9 @@
 
     @Override
     public int length() {
-        return runtime().getCompilerToVM().constantPoolLength(type);
+        HotSpotVMConfig config = runtime().getConfig();
+        long constantPoolAddress = unsafe.getAddress(type.metaspaceKlass() + config.instanceKlassConstantsOffset);
+        return unsafe.getInt(constantPoolAddress + config.constantPoolLengthOffset);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Fri Oct 25 01:39:54 2013 +0200
@@ -164,7 +164,7 @@
 
         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(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);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Fri Oct 25 01:39:54 2013 +0200
@@ -46,17 +46,17 @@
     private final HotSpotResolvedJavaMethod method;
     private final boolean isDefault;
     private final boolean isExternal;
+    private final String name;
 
-    public HotSpotNmethod(HotSpotResolvedJavaMethod method, boolean isDefault) {
-        this.method = method;
-        this.isDefault = isDefault;
-        this.isExternal = false;
+    public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault) {
+        this(method, name, isDefault, false);
     }
 
-    public HotSpotNmethod(HotSpotResolvedJavaMethod method, boolean isDefault, boolean isExternal) {
+    public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault, boolean isExternal) {
         this.method = method;
         this.isDefault = isDefault;
         this.isExternal = isExternal;
+        this.name = name;
     }
 
     public boolean isDefault() {
@@ -84,7 +84,7 @@
 
     @Override
     public String toString() {
-        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b]", method, getCodeBlob(), isDefault);
+        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=]", method, getCodeBlob(), isDefault, name);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Fri Oct 25 01:39:54 2013 +0200
@@ -199,6 +199,11 @@
                 if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) {
                     return value;
                 }
+            } else if (isStable()) {
+                Constant value = readValue(receiver);
+                if (assumeDefaultStableFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) {
+                    return value;
+                }
             } else {
                 Class<?> clazz = object.getClass();
                 if (StableOptionValue.class.isAssignableFrom(clazz)) {
@@ -229,6 +234,20 @@
         return clazz == SnippetCounter.class;
     }
 
+    /**
+     * Usually {@link Stable} fields are not considered constant if the value is the
+     * {@link Constant#isDefaultForKind default value}. For some special classes we want to override
+     * this behavior.
+     */
+    private static boolean assumeDefaultStableFieldsAsFinal(Class<?> clazz) {
+        // HotSpotVMConfig has a lot of zero-value fields which we know are stable and want to be
+        // considered as constants.
+        if (clazz == HotSpotVMConfig.class) {
+            return true;
+        }
+        return false;
+    }
+
     @Override
     public HotSpotResolvedObjectType getDeclaringClass() {
         return holder;
@@ -267,6 +286,16 @@
         return false;
     }
 
+    /**
+     * Checks if this field has the {@link Stable} annotation.
+     * 
+     * @return true if field has {@link Stable} annotation, false otherwise
+     */
+    public boolean isStable() {
+        Annotation annotation = getAnnotation(Stable.class);
+        return annotation != null;
+    }
+
     @Override
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         Field javaField = toJava();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri Oct 25 01:39:54 2013 +0200
@@ -190,6 +190,14 @@
     }
 
     /**
+     * Manually adds a DontInline annotation to this method.
+     */
+    public void setDontInline() {
+        dontInline = true;
+        runtime().getCompilerToVM().doNotInlineOrCompile(metaspaceMethod);
+    }
+
+    /**
      * Returns true if this method is one of the special methods that is ignored by security stack
      * walks.
      * 
@@ -440,7 +448,7 @@
     }
 
     /**
-     * Returns the offset of this method into the v-table. The method must have a v-table entry has
+     * Returns the offset of this method into the v-table. The method must have a v-table entry as
      * indicated by {@link #isInVirtualMethodTable()}, otherwise an exception is thrown.
      * 
      * @return the offset of this method into the v-table
@@ -449,12 +457,19 @@
         if (!isInVirtualMethodTable() || !holder.isInitialized()) {
             throw new GraalInternalError("%s does not have a vtable entry", this);
         }
-        return runtime().getCompilerToVM().getVtableEntryOffset(metaspaceMethod);
+        HotSpotVMConfig config = runtime().getConfig();
+        final int vtableIndex = getVtableIndex();
+        return config.instanceKlassVtableStartOffset + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset;
     }
 
     @Override
     public boolean isInVirtualMethodTable() {
-        return runtime().getCompilerToVM().hasVtableEntry(metaspaceMethod);
+        return getVtableIndex() >= 0;
+    }
+
+    private int getVtableIndex() {
+        HotSpotVMConfig config = runtime().getConfig();
+        return unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset);
     }
 
     public void setCurrentTask(CompilationTask task) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Fri Oct 25 01:39:54 2013 +0200
@@ -488,6 +488,13 @@
         return Constant.forIntegerKind(runtime().getTarget().wordKind, metaspaceKlass, this);
     }
 
+    /**
+     * Gets the address of the C++ Klass object for this type.
+     */
+    public long metaspaceKlass() {
+        return metaspaceKlass;
+    }
+
     public boolean isPrimaryType() {
         return runtime().getConfig().secondarySuperCacheOffset != superCheckOffset();
     }
@@ -500,7 +507,7 @@
     public long prototypeMarkWord() {
         HotSpotVMConfig config = runtime().getConfig();
         if (isArray()) {
-            return config.arrayPrototypeMarkWord;
+            return config.arrayPrototypeMarkWord();
         } else {
             return unsafeReadWord(metaspaceKlass + config.prototypeMarkWordOffset);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Fri Oct 25 01:39:54 2013 +0200
@@ -39,7 +39,9 @@
     @Override
     protected boolean verify(StructuredGraph graph, PhaseContext context) {
         for (ConstantNode node : graph.getNodes().filter(ConstantNode.class)) {
-            assert !isObject(node) || isNullReference(node) || isInternedString(node) : "illegal object constant: " + node;
+            if (node.recordsUsages() || !node.gatherUsages().isEmpty()) {
+                assert !isObject(node) || isNullReference(node) || isInternedString(node) : "illegal object constant: " + node;
+            }
         }
         return true;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Fri Oct 25 01:39:54 2013 +0200
@@ -68,7 +68,7 @@
                 LocationNode location = graph.unique(ConstantLocationNode.create(FINAL_LOCATION, stamp.kind(), classMirrorOffset, graph));
                 FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp));
 
-                graph.replaceFloating(node, freadNode);
+                node.replace(freadNode);
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Fri Oct 25 01:39:54 2013 +0200
@@ -66,7 +66,7 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
-        Object kObject = UnsafeLoadNode.load(rcvr, kOffset, Kind.Object);
+        Object kObject = UnsafeLoadNode.load(rcvr, kOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
         Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Oct 25 01:39:54 2013 +0200
@@ -78,9 +78,6 @@
         return arraycopyMethods.get(kind);
     }
 
-    private static final Kind VECTOR_KIND = Kind.Long;
-    private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
-
     private static void checkedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
         Object nonNullSrc = guardingNonNull(src);
         Object nonNullDest = guardingNonNull(dest);
@@ -88,32 +85,32 @@
         UnsafeArrayCopyNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, baseKind);
     }
 
-    public static int checkArrayType(Word hub) {
+    private static int checkArrayType(Word hub) {
         int layoutHelper = readLayoutHelper(hub);
-        if (layoutHelper >= 0) {
+        if (probability(SLOW_PATH_PROBABILITY, layoutHelper >= 0)) {
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
         return layoutHelper;
     }
 
-    public static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) {
-        if (srcPos < 0) {
+    private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) {
+        if (probability(SLOW_PATH_PROBABILITY, srcPos < 0)) {
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
-        if (destPos < 0) {
+        if (probability(SLOW_PATH_PROBABILITY, destPos < 0)) {
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
-        if (length < 0) {
+        if (probability(SLOW_PATH_PROBABILITY, length < 0)) {
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
-        if (srcPos + length > ArrayLengthNode.arrayLength(src)) {
+        if (probability(SLOW_PATH_PROBABILITY, srcPos + length > ArrayLengthNode.arrayLength(src))) {
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
-        if (destPos + length > ArrayLengthNode.arrayLength(dest)) {
+        if (probability(SLOW_PATH_PROBABILITY, destPos + length > ArrayLengthNode.arrayLength(dest))) {
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
@@ -170,12 +167,6 @@
 
     @Snippet
     public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
-        arrayObjectCopy(src, srcPos, dest, destPos, length);
-    }
-
-    // Does NOT perform store checks
-    @Snippet
-    public static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) {
         objectCounter.inc();
         checkedCopy(src, srcPos, dest, destPos, length, Kind.Object);
     }
@@ -193,7 +184,7 @@
             checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length);
             if (probability(FAST_PATH_PROBABILITY, isObjectArray)) {
                 genericObjectExactCallCounter.inc();
-                arrayObjectCopy(nonNullSrc, srcPos, nonNullDest, destPos, length);
+                UnsafeArrayCopyNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, Kind.Object);
             } else {
                 genericPrimitiveCallCounter.inc();
                 UnsafeArrayCopyNode.arraycopyPrimitive(nonNullSrc, srcPos, nonNullDest, destPos, length, layoutHelper);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Fri Oct 25 01:39:54 2013 +0200
@@ -62,7 +62,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true);
         } else {
@@ -72,7 +72,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, embeddedCipherOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false);
         } else {
@@ -81,8 +81,8 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, Kind.Object);
-        Object rObject = UnsafeLoadNode.load(rcvr, rOffset, Kind.Object);
+        Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
+        Object rObject = UnsafeLoadNode.load(rcvr, rOffset, Kind.Object, LocationIdentity.ANY_LOCATION);
         Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
         Word rAddr = (Word) Word.fromObject(rObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri Oct 25 01:39:54 2013 +0200
@@ -81,21 +81,21 @@
 
     @Fold
     public static int threadTlabTopOffset() {
-        return config().threadTlabTopOffset;
+        return config().threadTlabTopOffset();
     }
 
     public static final LocationIdentity TLAB_END_LOCATION = new NamedLocationIdentity("TlabEnd");
 
     @Fold
     private static int threadTlabEndOffset() {
-        return config().threadTlabEndOffset;
+        return config().threadTlabEndOffset();
     }
 
     public static final LocationIdentity TLAB_START_LOCATION = new NamedLocationIdentity("TlabStart");
 
     @Fold
     private static int threadTlabStartOffset() {
-        return config().threadTlabStartOffset;
+        return config().threadTlabStartOffset();
     }
 
     public static final LocationIdentity PENDING_EXCEPTION_LOCATION = new NamedLocationIdentity("PendingException");
@@ -230,7 +230,7 @@
 
     @Fold
     public static long arrayPrototypeMarkWord() {
-        return config().arrayPrototypeMarkWord;
+        return config().arrayPrototypeMarkWord();
     }
 
     @Fold
@@ -358,22 +358,22 @@
 
     @Fold
     public static int cardTableShift() {
-        return config().cardtableShift;
+        return config().cardtableShift();
     }
 
     @Fold
     public static long cardTableStart() {
-        return config().cardtableStartAddress;
+        return config().cardtableStartAddress();
     }
 
     @Fold
     public static int g1CardQueueIndexOffset() {
-        return config().g1CardQueueIndexOffset;
+        return config().g1CardQueueIndexOffset();
     }
 
     @Fold
     public static int g1CardQueueBufferOffset() {
-        return config().g1CardQueueBufferOffset;
+        return config().g1CardQueueBufferOffset();
     }
 
     @Fold
@@ -383,17 +383,17 @@
 
     @Fold
     public static int g1SATBQueueMarkingOffset() {
-        return config().g1SATBQueueMarkingOffset;
+        return config().g1SATBQueueMarkingOffset();
     }
 
     @Fold
     public static int g1SATBQueueIndexOffset() {
-        return config().g1SATBQueueIndexOffset;
+        return config().g1SATBQueueIndexOffset();
     }
 
     @Fold
     public static int g1SATBQueueBufferOffset() {
-        return config().g1SATBQueueBufferOffset;
+        return config().g1SATBQueueBufferOffset();
     }
 
     @Fold
@@ -485,7 +485,7 @@
 
     public static Word loadWordFromObject(Object object, int offset) {
         assert offset != hubOffset() : "Use loadHubIntrinsic instead";
-        return loadWordFromObjectIntrinsic(object, offset, getWordKind());
+        return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.ANY_LOCATION);
     }
 
     @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
@@ -493,7 +493,7 @@
 
     @SuppressWarnings("unused")
     @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
-    private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind) {
+    private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         return Word.unsigned(unsafeReadWord(object, offset));
     }
 
@@ -561,7 +561,7 @@
 
     @Fold
     public static long tlabIntArrayMarkWord() {
-        return config().tlabIntArrayMarkWord;
+        return config().tlabIntArrayMarkWord();
     }
 
     @Fold
@@ -578,7 +578,7 @@
 
     @Fold
     public static int threadTlabSizeOffset() {
-        return config().threadTlabSizeOffset;
+        return config().threadTlabSizeOffset();
     }
 
     public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = new NamedLocationIdentity("TlabThreadAllocatedBytes");
@@ -592,28 +592,28 @@
 
     @Fold
     public static int tlabRefillWasteLimitOffset() {
-        return config().tlabRefillWasteLimitOffset;
+        return config().tlabRefillWasteLimitOffset();
     }
 
     public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = new NamedLocationIdentity("TlabNOfRefills");
 
     @Fold
     public static int tlabNumberOfRefillsOffset() {
-        return config().tlabNumberOfRefillsOffset;
+        return config().tlabNumberOfRefillsOffset();
     }
 
     public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = new NamedLocationIdentity("TlabFastRefillWaste");
 
     @Fold
     public static int tlabFastRefillWasteOffset() {
-        return config().tlabFastRefillWasteOffset;
+        return config().tlabFastRefillWasteOffset();
     }
 
     public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = new NamedLocationIdentity("TlabSlowAllocations");
 
     @Fold
     public static int tlabSlowAllocationsOffset() {
-        return config().tlabSlowAllocationsOffset;
+        return config().tlabSlowAllocationsOffset();
     }
 
     @Fold
@@ -663,7 +663,7 @@
 
     @Fold
     public static int layoutHelperElementTypePrimitiveInPlace() {
-        return config().layoutHelperElementTypePrimitiveInPlace;
+        return config().layoutHelperElementTypePrimitiveInPlace();
     }
 
     static {
@@ -705,7 +705,7 @@
 
     @Fold
     public static long gcTotalCollectionsAddress() {
-        return config().gcTotalCollectionsAddress;
+        return config().gcTotalCollectionsAddress();
     }
 
     @Fold
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -112,6 +112,9 @@
 
     @Override
     public LocationIdentity getLocationIdentity() {
+        if (elementKind != null) {
+            return NamedLocationIdentity.getArrayLocation(elementKind);
+        }
         return ANY_LOCATION;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Fri Oct 25 01:39:54 2013 +0200
@@ -34,20 +34,24 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
-import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
+/**
+ * As opposed to {@link ArrayCopySnippets}, these Snippets do <b>not</b> perform store checks.
+ */
 public class UnsafeArrayCopySnippets implements Snippets {
 
     private static final boolean supportsUnalignedMemoryAccess = runtime().getTarget().arch.supportsUnalignedMemoryAccess();
 
+    // TODO: make vector kind architecture dependent
     private static final Kind VECTOR_KIND = Kind.Long;
-    private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
+    private static final long VECTOR_SIZE = arrayIndexScale(VECTOR_KIND);
 
-    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
+    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind, LocationIdentity locationIdentity) {
         int arrayBaseOffset = arrayBaseOffset(baseKind);
         int elementSize = arrayIndexScale(baseKind);
         long byteLength = (long) length * elementSize;
@@ -86,143 +90,101 @@
             for (long i = 0; i < postLoopBytes; i += elementSize) {
                 srcOffset -= elementSize;
                 destOffset -= elementSize;
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity);
             }
             // Main-loop
             for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) {
                 srcOffset -= VECTOR_SIZE;
                 destOffset -= VECTOR_SIZE;
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND);
+                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND, locationIdentity);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND, locationIdentity);
             }
             // Pre-loop
             for (long i = 0; i < preLoopBytes; i += elementSize) {
                 srcOffset -= elementSize;
                 destOffset -= elementSize;
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity);
             }
         } else {
             // Pre-loop
             for (long i = 0; i < preLoopBytes; i += elementSize) {
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity);
                 srcOffset += elementSize;
                 destOffset += elementSize;
             }
             // Main-loop
             for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND);
+                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND, locationIdentity);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a.longValue(), VECTOR_KIND, locationIdentity);
                 srcOffset += VECTOR_SIZE;
                 destOffset += VECTOR_SIZE;
             }
             // Post-loop
             for (long i = 0; i < postLoopBytes; i += elementSize) {
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind);
+                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity);
+                UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity);
                 srcOffset += elementSize;
                 destOffset += elementSize;
             }
         }
     }
 
+    @Fold
+    private static LocationIdentity getArrayLocation(Kind kind) {
+        return NamedLocationIdentity.getArrayLocation(kind);
+    }
+
     @Snippet
     public static void arraycopyByte(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte, getArrayLocation(Kind.Byte));
     }
 
     @Snippet
     public static void arraycopyBoolean(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte, getArrayLocation(Kind.Boolean));
     }
 
     @Snippet
     public static void arraycopyChar(char[] src, int srcPos, char[] dest, int destPos, int length) {
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char);
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char, getArrayLocation(Kind.Char));
     }
 
     @Snippet
     public static void arraycopyShort(short[] src, int srcPos, short[] dest, int destPos, int length) {
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short);
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short, getArrayLocation(Kind.Short));
     }
 
     @Snippet
     public static void arraycopyInt(int[] src, int srcPos, int[] dest, int destPos, int length) {
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int);
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int, getArrayLocation(Kind.Int));
     }
 
     @Snippet
     public static void arraycopyFloat(float[] src, int srcPos, float[] dest, int destPos, int length) {
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float);
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float, getArrayLocation(Kind.Float));
     }
 
     @Snippet
     public static void arraycopyLong(long[] src, int srcPos, long[] dest, int destPos, int length) {
-        Kind baseKind = Kind.Long;
-        int arrayBaseOffset = arrayBaseOffset(baseKind);
-        long byteLength = (long) length * arrayIndexScale(baseKind);
-        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
-        long destOffset = (long) destPos * arrayIndexScale(baseKind);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        } else {
-            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        }
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Long, getArrayLocation(Kind.Long));
     }
 
     @Snippet
     public static void arraycopyDouble(double[] src, int srcPos, double[] dest, int destPos, int length) {
-        Kind baseKind = Kind.Double;
-        int arrayBaseOffset = arrayBaseOffset(baseKind);
-        long byteLength = (long) length * arrayIndexScale(baseKind);
-        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
-        long destOffset = (long) destPos * arrayIndexScale(baseKind);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        } else {
-            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
-                /*
-                 * TODO atomicity problem on 32-bit architectures: The JVM spec requires double
-                 * values to be copied atomically, but not long values. For example, on Intel 32-bit
-                 * this code is not atomic as long as the vector kind remains Kind.Long.
-                 */
-                Long a = UnsafeLoadNode.load(src, arrayBaseOffset + i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, arrayBaseOffset + i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        }
+        /*
+         * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values to be
+         * copied atomically, but not long values. For example, on Intel 32-bit this code is not
+         * atomic as long as the vector kind remains Kind.Long.
+         */
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Double, getArrayLocation(Kind.Double));
     }
 
-    /**
-     * Does NOT perform store checks.
-     */
     @Snippet
     public static void arraycopyObject(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
-        final int scale = arrayIndexScale(Kind.Object);
-        int arrayBaseOffset = arrayBaseOffset(Kind.Object);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            long start = (long) (length - 1) * scale;
-            for (long i = start; i >= 0; i -= scale) {
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, Kind.Object);
-                DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a);
-            }
-        } else {
-            long end = (long) length * scale;
-            for (long i = 0; i < end; i += scale) {
-                Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, Kind.Object);
-                DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a);
-            }
-        }
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Object, getArrayLocation(Kind.Object));
     }
 
     @Snippet
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Fri Oct 25 01:39:54 2013 +0200
@@ -174,6 +174,13 @@
                         StampTool.add(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE + 1), StampFactory.forInteger(Kind.Long, Integer.MIN_VALUE, Integer.MAX_VALUE)));
         assertEquals(StampFactory.forInteger(Kind.Int, -2147483647, 31 - 2147483647),
                         StampTool.add(StampFactory.forInteger(Kind.Int, 0, 31), StampFactory.forInteger(Kind.Int, -2147483647, -2147483647)));
+
+        assertEquals(StampFactory.forInteger(Kind.Int, 0x8000007e, 0x8000007f, 0x8000007eL, 0x8000007fL),
+                        StampTool.add(StampFactory.forInteger(Kind.Int, 0x7ffffffe, 0x7fffffff, 0x7ffffffeL, 0x7fffffffL), StampFactory.forInteger(Kind.Int, 128, 128)));
+
+        assertEquals(StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL),
+                        StampTool.add(StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL),
+                                        StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL)));
     }
 
     @Test
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -45,6 +45,17 @@
     }
 
     /**
+     * Used to measure the impact of ConstantNodes not recording their usages. This and all code
+     * predicated on this value being true will be removed at some point.
+     */
+    public static final boolean ConstantNodeRecordsUsages = Boolean.getBoolean("graal.constantNodeRecordsUsages");
+
+    @Override
+    public boolean recordsUsages() {
+        return ConstantNodeRecordsUsages;
+    }
+
+    /**
      * Constructs a new ConstantNode representing the specified constant.
      * 
      * @param value the constant
@@ -54,6 +65,35 @@
         this.value = value;
     }
 
+    /**
+     * Computes the usages of this node by iterating over all the nodes in the graph, searching for
+     * those that have this node as an input.
+     */
+    public List<Node> gatherUsages() {
+        assert !ConstantNodeRecordsUsages;
+        List<Node> usages = new ArrayList<>();
+        for (Node node : graph().getNodes()) {
+            for (Node input : node.inputs()) {
+                if (input == this) {
+                    usages.add(node);
+                }
+            }
+        }
+        return usages;
+    }
+
+    public void replace(Node replacement) {
+        if (!recordsUsages()) {
+            List<Node> usages = gatherUsages();
+            for (Node usage : usages) {
+                usage.replaceFirstInput(this, replacement);
+            }
+            graph().removeFloating(this);
+        } else {
+            graph().replaceFloating(this, replacement);
+        }
+    }
+
     @Override
     public void generate(LIRGeneratorTool gen) {
         if (gen.canInlineConstant(value) || onlyUsedInVirtualState()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -99,9 +99,8 @@
                 DeoptimizeNode deopt = graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason));
                 deopt.setDeoptimizationState(getDeoptimizationState());
                 setNext(deopt);
-            } else {
-                this.replaceAtUsages(null);
             }
+            this.replaceAtUsages(null);
             graph().removeFixed(this);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -45,7 +45,7 @@
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
-    private final DeoptimizationAction action;
+    private DeoptimizationAction action;
     private boolean negated;
 
     public GuardNode(LogicNode condition, GuardingNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated) {
@@ -107,4 +107,8 @@
     public void negate() {
         negated = !negated;
     }
+
+    public void setAction(DeoptimizationAction invalidaterecompile) {
+        this.action = invalidaterecompile;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -90,7 +90,7 @@
             }
             ValueNode removedValue = phi.valueAt(predIndex);
             phi.removeInput(predIndex);
-            if (removedValue != null && removedValue.isAlive() && removedValue.usages().isEmpty() && GraphUtil.isFloatingNode().apply(removedValue)) {
+            if (removedValue != null && removedValue.isAlive() && removedValue.recordsUsages() && removedValue.usages().isEmpty() && GraphUtil.isFloatingNode().apply(removedValue)) {
                 GraphUtil.killWithUnusedFloatingInputs(removedValue);
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -37,8 +37,8 @@
 public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable {
     @Input private LogicNode guardingCondition;
 
-    public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind) {
-        this(object, offset, accessKind, LocationIdentity.ANY_LOCATION, null);
+    public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) {
+        this(object, offset, accessKind, locationIdentity, null);
     }
 
     public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) {
@@ -78,9 +78,9 @@
         return this.graph().add(new LoadFieldNode(object(), field));
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "unused"})
     @NodeIntrinsic
-    public static <T> T load(Object object, long offset, @ConstantNodeParameter Kind kind) {
+    public static <T> T load(Object object, long offset, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         if (kind == Kind.Boolean) {
             return (T) (Boolean) unsafe.getBoolean(object, offset);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -39,10 +39,6 @@
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
 
-    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind) {
-        this(object, offset, value, accessKind, LocationIdentity.ANY_LOCATION);
-    }
-
     public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) {
         super(StampFactory.forVoid(), object, offset, accessKind, locationIdentity);
         assert accessKind != Kind.Void && accessKind != Kind.Illegal;
@@ -106,55 +102,55 @@
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, Object value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, Object value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putObject(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, boolean value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, boolean value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putBoolean(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, byte value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, byte value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putByte(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, char value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, char value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putChar(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, double value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, double value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putDouble(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, float value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, float value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putFloat(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, int value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, int value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putInt(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, long value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, long value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putLong(object, offset, value);
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object object, long offset, short value, @ConstantNodeParameter Kind kind) {
+    public static void store(Object object, long offset, short value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) {
         unsafe.putShort(object, offset, value);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Fri Oct 25 01:39:54 2013 +0200
@@ -185,7 +185,9 @@
             return StampFactory.illegal(Kind.Illegal);
         }
         IntegerStamp other = (IntegerStamp) otherStamp;
-        return createStamp(other, Math.min(upperBound, other.upperBound), Math.max(lowerBound, other.lowerBound), downMask | other.downMask, upMask & other.upMask);
+        long newDownMask = downMask | other.downMask;
+        long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask;
+        return createStamp(other, Math.min(upperBound, other.upperBound), newLowerBound, newDownMask, upMask & other.upMask);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Fri Oct 25 01:39:54 2013 +0200
@@ -114,13 +114,23 @@
         return StampFactory.forKind(kind);
     }
 
-    private static boolean addOverflows(long x, long y, Kind kind) {
+    private static boolean addOverflowsPositively(long x, long y, Kind kind) {
         long result = x + y;
         if (kind == Kind.Long) {
-            return ((x ^ result) & (y ^ result)) < 0;
+            return (~x & ~y & result) < 0;
         } else {
             assert kind == Kind.Int;
-            return result > Integer.MAX_VALUE || result < Integer.MIN_VALUE;
+            return result > Integer.MAX_VALUE;
+        }
+    }
+
+    private static boolean addOverflowsNegatively(long x, long y, Kind kind) {
+        long result = x + y;
+        if (kind == Kind.Long) {
+            return (x & y & ~result) < 0;
+        } else {
+            assert kind == Kind.Int;
+            return result < Integer.MIN_VALUE;
         }
     }
 
@@ -142,16 +152,22 @@
 
             long lowerBound;
             long upperBound;
-            if (addOverflows(stamp1.lowerBound(), stamp2.lowerBound(), kind) || addOverflows(stamp1.upperBound(), stamp2.upperBound(), kind)) {
+            boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), kind);
+            boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), kind);
+            boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), kind);
+            boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), kind);
+            if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsNegatively && !lowerOverflowsPositively && upperOverflowsPositively)) {
                 lowerBound = kind.getMinValue();
                 upperBound = kind.getMaxValue();
             } else {
-                lowerBound = stamp1.lowerBound() + stamp2.lowerBound();
-                upperBound = stamp1.upperBound() + stamp2.upperBound();
+                lowerBound = signExtend(stamp1.lowerBound() + stamp2.lowerBound(), kind);
+                upperBound = signExtend(stamp1.upperBound() + stamp2.upperBound(), kind);
             }
             IntegerStamp limit = StampFactory.forInteger(kind, lowerBound, upperBound);
             newUpMask &= limit.upMask();
-            return new IntegerStamp(kind, lowerBound | newDownMask, signExtend(upperBound & newUpMask, kind), newDownMask, newUpMask);
+            upperBound = signExtend(upperBound & newUpMask, kind);
+            lowerBound |= newDownMask;
+            return new IntegerStamp(kind, lowerBound, upperBound, newDownMask, newUpMask);
         } catch (Throwable e) {
             throw new RuntimeException(stamp1 + " + " + stamp2, e);
         }
@@ -238,14 +254,16 @@
             if (shiftCount != 0) {
                 long lowerBound;
                 long upperBound;
+                long downMask = value.downMask() >>> shiftCount;
+                long upMask = value.upMask() >>> shiftCount;
                 if (value.lowerBound() < 0) {
-                    lowerBound = 0;
-                    upperBound = IntegerStamp.defaultMask(kind) >>> shiftCount;
+                    lowerBound = downMask;
+                    upperBound = upMask;
                 } else {
                     lowerBound = value.lowerBound() >>> shiftCount;
                     upperBound = value.upperBound() >>> shiftCount;
                 }
-                return new IntegerStamp(kind, lowerBound, upperBound, value.downMask() >>> shiftCount, value.upMask() >>> shiftCount);
+                return new IntegerStamp(kind, lowerBound, upperBound, downMask, upMask);
             }
         }
         long mask = IntegerStamp.upMaskFor(kind, value.lowerBound(), value.upperBound());
@@ -309,7 +327,7 @@
     }
 
     private static long signExtend(long value, Kind valueKind) {
-        if (valueKind != Kind.Char && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) {
+        if (valueKind != Kind.Char && valueKind != Kind.Long && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) {
             return value | (-1L << valueKind.getBitCount());
         } else {
             return value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Fri Oct 25 01:39:54 2013 +0200
@@ -123,13 +123,17 @@
     }
 
     public static void killWithUnusedFloatingInputs(Node node) {
-        List<Node> floatingInputs = node.inputs().filter(isFloatingNode()).snapshot();
-        node.safeDelete();
+        if (node.recordsUsages()) {
+            List<Node> floatingInputs = node.inputs().filter(isFloatingNode()).snapshot();
+            node.safeDelete();
 
-        for (Node in : floatingInputs) {
-            if (in.isAlive() && in.usages().isEmpty()) {
-                killWithUnusedFloatingInputs(in);
+            for (Node in : floatingInputs) {
+                if (in.isAlive() && (!in.recordsUsages() || in.usages().isEmpty())) {
+                    killWithUnusedFloatingInputs(in);
+                }
             }
+        } else {
+            assert node.inputs().isEmpty();
         }
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Oct 25 01:39:54 2013 +0200
@@ -206,7 +206,7 @@
         }
 
         private static boolean tryKillUnused(Node node) {
-            if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) {
+            if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) {
                 GraphUtil.killWithUnusedFloatingInputs(node);
                 return true;
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java	Fri Oct 25 01:39:54 2013 +0200
@@ -89,10 +89,9 @@
         int successorCount = controlSplit.successors().count();
         List<GuardNode> otherGuards = new ArrayList<>(successorCount - 1);
         for (GuardNode guard : successor.guards().snapshot()) {
-            if (guard.condition().usages().count() < successorCount) {
+            if (guard.isDeleted() || guard.condition().usages().count() < successorCount) {
                 continue;
             }
-
             for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) {
                 if (conditonGuard != guard) {
                     GuardingNode conditonGuardAnchor = conditonGuard.getGuard();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Fri Oct 25 01:39:54 2013 +0200
@@ -631,8 +631,10 @@
             cdbc.apply(cfg.getNodeToBlock().get(succ));
         }
         ensureScheduledUsages(node, strategy);
-        for (Node usage : node.usages()) {
-            blocksForUsage(node, usage, cdbc, strategy);
+        if (node.recordsUsages()) {
+            for (Node usage : node.usages()) {
+                blocksForUsage(node, usage, cdbc, strategy);
+            }
         }
         List<FixedNode> usages = phantomUsages.get(node);
         if (usages != null) {
@@ -808,8 +810,10 @@
     }
 
     private void ensureScheduledUsages(Node node, SchedulingStrategy strategy) {
-        for (Node usage : node.usages().filter(ScheduledNode.class)) {
-            assignBlockToNode((ScheduledNode) usage, strategy);
+        if (node.recordsUsages()) {
+            for (Node usage : node.usages().filter(ScheduledNode.class)) {
+                assignBlockToNode((ScheduledNode) usage, strategy);
+            }
         }
         // now true usages are ready
     }
@@ -1057,14 +1061,16 @@
             }
 
             visited.mark(instruction);
-            for (Node usage : instruction.usages()) {
-                if (usage instanceof VirtualState) {
-                    // only fixed nodes can have VirtualState -> no need to schedule them
-                } else {
-                    if (instruction instanceof LoopExitNode && usage instanceof ProxyNode) {
-                        // value proxies should be scheduled before the loopexit, not after
+            if (instruction.recordsUsages()) {
+                for (Node usage : instruction.usages()) {
+                    if (usage instanceof VirtualState) {
+                        // only fixed nodes can have VirtualState -> no need to schedule them
                     } else {
-                        addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited);
+                        if (instruction instanceof LoopExitNode && usage instanceof ProxyNode) {
+                            // value proxies should be scheduled before the loopexit, not after
+                        } else {
+                            addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited);
+                        }
                     }
                 }
             }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Fri Oct 25 01:39:54 2013 +0200
@@ -327,7 +327,7 @@
         out.println("=== Succesors ===");
         printNamedNodes(node, node.successors().iterator(), "", "\n", null);
         out.println("=== Usages ===");
-        if (!node.usages().isEmpty()) {
+        if (node.recordsUsages() && !node.usages().isEmpty()) {
             for (Node usage : node.usages()) {
                 out.print(nodeToString(usage)).print(" ");
             }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Fri Oct 25 01:39:54 2013 +0200
@@ -94,7 +94,7 @@
             return false;
         }
 
-        if (method != curMethod || !curDecorators.equals(decorators)) {
+        if (!method.equals(curMethod) || !curDecorators.equals(decorators)) {
             cfgPrinter.printCompilation(method);
             TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile);
             curMethod = method;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java	Fri Oct 25 01:39:54 2013 +0200
@@ -64,22 +64,22 @@
 
     @MethodSubstitution
     private static Node getNode(Node node, long offset) {
-        return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object), Node.class, false, false);
+        return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), Node.class, false, false);
     }
 
     @MethodSubstitution
     private static NodeList getNodeList(Node node, long offset) {
-        return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object), NodeList.class, false, false);
+        return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), NodeList.class, false, false);
     }
 
     @MethodSubstitution
     private static void putNode(Node node, long offset, Node value) {
-        UnsafeStoreNode.store(node, offset, value, Kind.Object);
+        UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution
     private static void putNodeList(Node node, long offset, NodeList value) {
-        UnsafeStoreNode.store(node, offset, value, Kind.Object);
+        UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION);
     }
 
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Fri Oct 25 01:39:54 2013 +0200
@@ -321,7 +321,8 @@
     }
 
     public void cleanUpReturnCheckCast(Node newInstance) {
-        if (newInstance instanceof ValueNode && (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) {
+        if (newInstance.recordsUsages() && newInstance instanceof ValueNode &&
+                        (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) {
             StructuredGraph graph = (StructuredGraph) newInstance.graph();
             for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) {
                 for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Oct 25 01:39:54 2013 +0200
@@ -273,6 +273,20 @@
         }
     }
 
+    static class VarargsPlaceholderNode extends FloatingNode implements ArrayLengthProvider {
+
+        final Varargs varargs;
+
+        public VarargsPlaceholderNode(Varargs varargs, MetaAccessProvider metaAccess) {
+            super(StampFactory.exactNonNull(metaAccess.lookupJavaType(varargs.componentType).getArrayClass()));
+            this.varargs = varargs;
+        }
+
+        public ValueNode length() {
+            return ConstantNode.forInt(varargs.length, graph());
+        }
+    }
+
     static class CacheKey {
 
         private final ResolvedJavaMethod method;
@@ -411,7 +425,7 @@
         assert checkTemplate(metaAccess, args, method, signature);
 
         int parameterCount = args.info.getParameterCount();
-        ConstantNode[] placeholders = new ConstantNode[parameterCount];
+        VarargsPlaceholderNode[] placeholders = new VarargsPlaceholderNode[parameterCount];
 
         for (int i = 0; i < parameterCount; i++) {
             if (args.info.isConstantParameter(i)) {
@@ -426,8 +440,7 @@
                 nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, metaAccess, snippetCopy));
             } else if (args.info.isVarargsParameter(i)) {
                 Varargs varargs = (Varargs) args.values[i];
-                Object array = Array.newInstance(varargs.componentType, varargs.length);
-                ConstantNode placeholder = ConstantNode.forObject(array, metaAccess, snippetCopy);
+                VarargsPlaceholderNode placeholder = snippetCopy.unique(new VarargsPlaceholderNode(varargs, providers.getMetaAccess()));
                 nodeReplacements.put(snippetGraph.getLocal(i), placeholder);
                 placeholders[i] = placeholder;
             }
@@ -461,7 +474,7 @@
                 }
                 parameters[i] = locals;
 
-                ConstantNode placeholder = placeholders[i];
+                VarargsPlaceholderNode placeholder = placeholders[i];
                 assert placeholder != null;
                 for (Node usage : placeholder.usages().snapshot()) {
                     if (usage instanceof LoadIndexedNode) {
@@ -584,7 +597,7 @@
         this.returnNode = retNode;
     }
 
-    private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, ConstantNode[] placeholders) {
+    private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, VarargsPlaceholderNode[] placeholders) {
         for (int i = 0; i < parameterCount; i++) {
             if (placeholders[i] != null) {
                 assert placeholders[i].isDeleted() : placeholders[i];
@@ -800,7 +813,7 @@
             // check if some node in snippet graph also kills the same location
             LocationIdentity locationIdentity = ((MemoryCheckpoint.Single) replacee).getLocationIdentity();
             if (locationIdentity == ANY_LOCATION) {
-                assert !(memoryMap.getLastLocationAccess(ANY_LOCATION) instanceof StartNode);
+                assert !(memoryMap.getLastLocationAccess(ANY_LOCATION) instanceof StartNode) : replacee + " kills ANY_LOCATION, but snippet does not";
             }
             assert kills.contains(locationIdentity) : replacee + " kills " + locationIdentity + ", but snippet doesn't contain a kill to this location";
             return true;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Fri Oct 25 01:39:54 2013 +0200
@@ -53,7 +53,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static Object getObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
-        return UnsafeLoadNode.load(o, offset, Kind.Object);
+        return UnsafeLoadNode.load(o, offset, Kind.Object, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -66,7 +66,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Object);
+        UnsafeStoreNode.store(o, offset, x, Kind.Object, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -85,7 +85,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static int getInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
-        Integer value = UnsafeLoadNode.load(o, offset, Kind.Int);
+        Integer value = UnsafeLoadNode.load(o, offset, Kind.Int, LocationIdentity.ANY_LOCATION);
         return value;
     }
 
@@ -99,7 +99,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Int);
+        UnsafeStoreNode.store(o, offset, x, Kind.Int, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -119,7 +119,7 @@
     @MethodSubstitution(isStatic = false)
     public static boolean getBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Boolean result = UnsafeLoadNode.load(o, offset, Kind.Boolean);
+        Boolean result = UnsafeLoadNode.load(o, offset, Kind.Boolean, LocationIdentity.ANY_LOCATION);
         return result;
     }
 
@@ -133,7 +133,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, boolean x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Boolean);
+        UnsafeStoreNode.store(o, offset, x, Kind.Boolean, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -146,7 +146,7 @@
     @MethodSubstitution(isStatic = false)
     public static byte getByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Byte result = UnsafeLoadNode.load(o, offset, Kind.Byte);
+        Byte result = UnsafeLoadNode.load(o, offset, Kind.Byte, LocationIdentity.ANY_LOCATION);
         return result;
     }
 
@@ -160,7 +160,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, byte x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Byte);
+        UnsafeStoreNode.store(o, offset, x, Kind.Byte, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -173,7 +173,7 @@
     @MethodSubstitution(isStatic = false)
     public static short getShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Short result = UnsafeLoadNode.load(o, offset, Kind.Short);
+        Short result = UnsafeLoadNode.load(o, offset, Kind.Short, LocationIdentity.ANY_LOCATION);
         return result;
     }
 
@@ -187,7 +187,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, short x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Short);
+        UnsafeStoreNode.store(o, offset, x, Kind.Short, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -200,7 +200,7 @@
     @MethodSubstitution(isStatic = false)
     public static char getChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Character result = UnsafeLoadNode.load(o, offset, Kind.Char);
+        Character result = UnsafeLoadNode.load(o, offset, Kind.Char, LocationIdentity.ANY_LOCATION);
         return result;
     }
 
@@ -214,7 +214,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, char x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Char);
+        UnsafeStoreNode.store(o, offset, x, Kind.Char, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -227,7 +227,7 @@
     @MethodSubstitution(isStatic = false)
     public static long getLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Long result = UnsafeLoadNode.load(o, offset, Kind.Long);
+        Long result = UnsafeLoadNode.load(o, offset, Kind.Long, LocationIdentity.ANY_LOCATION);
         return result;
     }
 
@@ -241,7 +241,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Long);
+        UnsafeStoreNode.store(o, offset, x, Kind.Long, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -261,7 +261,7 @@
     @MethodSubstitution(isStatic = false)
     public static float getFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Float result = UnsafeLoadNode.load(o, offset, Kind.Float);
+        Float result = UnsafeLoadNode.load(o, offset, Kind.Float, LocationIdentity.ANY_LOCATION);
         return result;
     }
 
@@ -275,7 +275,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, float x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Float);
+        UnsafeStoreNode.store(o, offset, x, Kind.Float, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
@@ -288,7 +288,7 @@
     @MethodSubstitution(isStatic = false)
     public static double getDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) {
         @JavacBug(id = 6995200)
-        Double result = UnsafeLoadNode.load(o, offset, Kind.Double);
+        Double result = UnsafeLoadNode.load(o, offset, Kind.Double, LocationIdentity.ANY_LOCATION);
         return result;
     }
 
@@ -302,7 +302,7 @@
 
     @MethodSubstitution(isStatic = false)
     public static void putDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, double x) {
-        UnsafeStoreNode.store(o, offset, x, Kind.Double);
+        UnsafeStoreNode.store(o, offset, x, Kind.Double, LocationIdentity.ANY_LOCATION);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java	Fri Oct 25 01:39:54 2013 +0200
@@ -22,36 +22,50 @@
  */
 package com.oracle.graal.truffle.hotspot.amd64;
 
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.amd64.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.hotspot.amd64.util.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 
 /**
- * Subclass of {@link AMD64HotSpotBackend} that injects special code into
+ * Backend that decorates an existing {@link AMD64HotSpotBackend}, injecting special code into
  * {@link OptimizedCallTarget#call(PackedFrame, Arguments)} for making a tail-call to the entry
  * point of the target callee.
  */
-class AMD64HotSpotTruffleBackend extends AMD64HotSpotBackend {
+class AMD64HotSpotTruffleBackend extends Backend {
+
+    private final AMD64HotSpotBackend original;
 
-    private ResolvedJavaMethod optimizedCallTargetCall;
+    private HotSpotResolvedJavaMethod optimizedCallTargetCall;
 
-    public AMD64HotSpotTruffleBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
-        super(runtime, providers);
+    public AMD64HotSpotTruffleBackend(AMD64HotSpotBackend original) {
+        super(original.getProviders());
+        this.original = original;
     }
 
     private ResolvedJavaMethod getInstrumentedMethod() throws GraalInternalError {
         if (optimizedCallTargetCall == null) {
             try {
-                optimizedCallTargetCall = getProviders().getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("call", PackedFrame.class, Arguments.class));
+                optimizedCallTargetCall = (HotSpotResolvedJavaMethod) getProviders().getMetaAccess().lookupJavaMethod(
+                                OptimizedCallTarget.class.getDeclaredMethod("call", PackedFrame.class, Arguments.class));
+                optimizedCallTargetCall.setDontInline();
             } catch (NoSuchMethodException | SecurityException e) {
                 throw new GraalInternalError(e);
             }
@@ -60,10 +74,88 @@
     }
 
     @Override
-    protected void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) {
-        super.emitCodePrefix(installedCodeOwner, tasm, asm, regConfig, config, verifiedStub);
+    public SuitesProvider getSuites() {
+        return original.getSuites();
+    }
+
+    @Override
+    public DisassemblerProvider getDisassembler() {
+        return original.getDisassembler();
+    }
+
+    @Override
+    public FrameMap newFrameMap() {
+        return original.newFrameMap();
+    }
+
+    @Override
+    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        return original.newLIRGenerator(graph, frameMap, cc, lir);
+    }
+
+    @Override
+    protected AbstractAssembler createAssembler(FrameMap frameMap) {
+        return null;
+    }
+
+    @Override
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
+        return original.newAssembler(lirGen, compilationResult);
+    }
+
+    @Override
+    public boolean shouldAllocateRegisters() {
+        return original.shouldAllocateRegisters();
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) {
+        AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
+        FrameMap frameMap = tasm.frameMap;
+        RegisterConfig regConfig = frameMap.registerConfig;
+        HotSpotVMConfig config = original.getRuntime().getConfig();
+        Label verifiedStub = new Label();
+
+        // Emit the prefix
+        original.emitCodePrefix(installedCodeOwner, tasm, asm, regConfig, config, verifiedStub);
+
         if (getInstrumentedMethod().equals(installedCodeOwner)) {
-            // TODO emit tailcall code
+            // Inject code for {@link OptimizedCallTarget#call(PackedFrame, Arguments)}
+            injectCode(asm, config);
         }
+
+        // Emit code for the LIR
+        original.emitCodeBody(installedCodeOwner, tasm, lirGen);
+
+        // Emit the suffix
+        original.emitCodeSuffix(installedCodeOwner, tasm, lirGen, asm, frameMap);
+    }
+
+    private void injectCode(AMD64MacroAssembler asm, HotSpotVMConfig config) {
+        HotSpotProviders providers = original.getRuntime().getHostProviders();
+        Register thisRegister = providers.getCodeCache().getRegisterConfig().getCallingConventionRegisters(Type.JavaCall, Kind.Object)[0];
+        Register spillRegister = AMD64.r10; // TODO(mg): fix me
+        AMD64Address nMethodAddress = new AMD64Address(thisRegister, OptimizedCallTargetFieldInfo.getCompiledMethodFieldOffset());
+        if (config.useCompressedOops) {
+            asm.movl(spillRegister, nMethodAddress);
+            AMD64HotSpotMove.decodePointer(asm, spillRegister, providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment());
+        } else {
+            asm.movq(spillRegister, nMethodAddress);
+        }
+        Label doProlog = new Label();
+
+        asm.cmpq(spillRegister, 0);
+        asm.jcc(ConditionFlag.Equal, doProlog);
+
+        AMD64Address codeBlobAddress = new AMD64Address(spillRegister, OptimizedCallTargetFieldInfo.getCodeBlobFieldOffset());
+        asm.movq(spillRegister, codeBlobAddress);
+        asm.cmpq(spillRegister, 0);
+        asm.jcc(ConditionFlag.Equal, doProlog);
+
+        AMD64Address verifiedEntryPointAddress = new AMD64Address(spillRegister, config.nmethodEntryOffset);
+        asm.movq(spillRegister, verifiedEntryPointAddress);
+        asm.jmp(spillRegister);
+
+        asm.bind(doProlog);
     }
 }
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackendFactory.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackendFactory.java	Fri Oct 25 01:39:54 2013 +0200
@@ -23,18 +23,22 @@
 package com.oracle.graal.truffle.hotspot.amd64;
 
 import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.hotspot.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.amd64.*;
-import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.truffle.*;
 
 /**
  * Factory to create a Truffle-specialized AMD64 HotSpot backend.
  */
-@ServiceProvider(HotSpotBackendFactory.class)
-public class AMD64HotSpotTruffleBackendFactory extends AMD64HotSpotBackendFactory {
+@ServiceProvider(TruffleBackendFactory.class)
+public class AMD64HotSpotTruffleBackendFactory implements TruffleBackendFactory {
 
     @Override
-    protected AMD64HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
-        return new AMD64HotSpotTruffleBackend(runtime, providers);
+    public Backend createBackend(Backend original) {
+        return new AMD64HotSpotTruffleBackend((AMD64HotSpotBackend) original);
+    }
+
+    public String getArchitecture() {
+        return "AMD64";
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/util/OptimizedCallTargetFieldInfo.java	Fri Oct 25 01:39:54 2013 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.hotspot.amd64.util;
+
+import java.lang.reflect.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.truffle.*;
+
+public class OptimizedCallTargetFieldInfo {
+
+    private static final Unsafe unsafe = UnsafeAccess.unsafe;
+    private static int compiledMethodFieldOffset = -1;
+    private static int codeBlobFieldOffset = -1;
+
+    public static int getCodeBlobFieldOffset() {
+        if (codeBlobFieldOffset == -1) {
+            codeBlobFieldOffset = getFieldOffset("codeBlob", HotSpotInstalledCode.class);
+        }
+        return codeBlobFieldOffset;
+    }
+
+    public static int getCompiledMethodFieldOffset() {
+        if (compiledMethodFieldOffset == -1) {
+            compiledMethodFieldOffset = getFieldOffset("compiledMethod", OptimizedCallTarget.class);
+        }
+        return compiledMethodFieldOffset;
+
+    }
+
+    private static int getFieldOffset(String name, Class container) {
+        try {
+            container.getDeclaredField(name).setAccessible(true);
+            Field field = container.getDeclaredField(name);
+            return (int) unsafe.objectFieldOffset(field);
+        } catch (NoSuchFieldException | SecurityException e) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Fri Oct 25 01:39:54 2013 +0200
@@ -102,7 +102,7 @@
             compilable.call(null, arguments);
         } while (compilable.inline());
 
-        StructuredGraph graph = Debug.scope("TruffleCompilation", new DebugDumpScope("TruffleCompilation: " + compilable), new Callable<StructuredGraph>() {
+        StructuredGraph graph = Debug.scope("TruffleCompilation", new TruffleDebugJavaMethod(compilable), new Callable<StructuredGraph>() {
 
             @Override
             public StructuredGraph call() {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Fri Oct 25 01:39:54 2013 +0200
@@ -22,11 +22,28 @@
  */
 package com.oracle.graal.truffle;
 
+import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
+import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
@@ -47,6 +64,7 @@
     private ArrayList<String> excludes;
 
     private GraalTruffleRuntime() {
+        installOptimizedCallTargetCallMethod();
     }
 
     public String getName() {
@@ -138,4 +156,55 @@
             }
         }
     }
+
+    public static void installOptimizedCallTargetCallMethod() {
+        Providers providers = getGraalProviders();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        ResolvedJavaMethod resolvedCallMethod = metaAccess.lookupJavaMethod(getCallMethod());
+        providers.getCodeCache().setDefaultMethod(resolvedCallMethod, compileMethod(resolvedCallMethod));
+    }
+
+    private static Method getCallMethod() {
+        Method method;
+        try {
+            method = OptimizedCallTarget.class.getDeclaredMethod("call", new Class[]{PackedFrame.class, Arguments.class});
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+        return method;
+    }
+
+    private static Backend instrumentBackend(Backend original) {
+        String arch = original.getTarget().arch.getName();
+
+        for (TruffleBackendFactory factory : ServiceLoader.loadInstalled(TruffleBackendFactory.class)) {
+            if (factory.getArchitecture().equals(arch)) {
+                return factory.createBackend(original);
+            }
+        }
+
+        return original;
+    }
+
+    private static CompilationResult compileMethod(ResolvedJavaMethod javaMethod) {
+        Providers providers = getGraalProviders();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        Suites suites = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites();
+        suites.getHighTier().findPhase(InliningPhase.class).remove();
+        StructuredGraph graph = new StructuredGraph(javaMethod);
+        ForeignCallsProvider foreignCalls = providers.getForeignCalls();
+        new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+        PhasePlan phasePlan = new PhasePlan();
+        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(RuntimeProvider.class).getHostBackend();
+        return GraalCompiler.compileGraph(graph, cc, javaMethod, providers, instrumentBackend(backend), providers.getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
+                        new SpeculationLog(), suites, new CompilationResult());
+    }
+
+    private static Providers getGraalProviders() {
+        RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
+        return runtimeProvider.getHostBackend().getProviders();
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Fri Oct 25 01:39:54 2013 +0200
@@ -77,6 +77,14 @@
     }
 
     private Object callHelper(PackedFrame caller, Arguments args) {
+        if (compiledMethod != null && compiledMethod.isValid()) {
+            TruffleRuntime runtime = Truffle.getRuntime();
+            if (runtime instanceof GraalTruffleRuntime) {
+                OUT.printf("[truffle] reinstall OptimizedCallTarget.call code with frame prolog shortcut.");
+                OUT.println();
+                GraalTruffleRuntime.installOptimizedCallTargetCallMethod();
+            }
+        }
         if (TruffleCallTargetProfiling.getValue()) {
             callCount++;
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Fri Oct 25 01:39:54 2013 +0200
@@ -104,7 +104,7 @@
 
         final StructuredGraph graph = new StructuredGraph(executeHelperMethod);
 
-        Debug.scope("createGraph", graph, new Runnable() {
+        Debug.scope("createGraph", new Runnable() {
 
             @Override
             public void run() {
@@ -245,13 +245,12 @@
                 ValueNode arg = arguments.get(local.index());
                 if (arg.isConstant()) {
                     Constant constant = arg.asConstant();
-                    ConstantNode constantNode = ConstantNode.forConstant(constant, phaseContext.getMetaAccess(), graphCopy);
-                    local.replaceAndDelete(constantNode);
-                    for (Node usage : constantNode.usages()) {
+                    for (Node usage : local.usages()) {
                         if (usage instanceof Canonicalizable) {
                             modifiedNodes.add(usage);
                         }
                     }
+                    local.replaceAndDelete(ConstantNode.forConstant(constant, phaseContext.getMetaAccess(), graphCopy));
                 }
             }
             Debug.scope("TruffleUnrollLoop", targetMethod, new Runnable() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleBackendFactory.java	Fri Oct 25 01:39:54 2013 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import com.oracle.graal.compiler.target.*;
+
+public interface TruffleBackendFactory {
+
+    Backend createBackend(Backend original);
+
+    /**
+     * Gets the CPU architecture of this backend.
+     */
+    String getArchitecture();
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Fri Oct 25 01:39:54 2013 +0200
@@ -156,7 +156,7 @@
                             int beforeInvokeMark = graph.getMark();
                             expandInvoke(methodCallTarget);
                             for (Node arg : argumentSnapshot) {
-                                if (arg != null) {
+                                if (arg != null && arg.recordsUsages()) {
                                     for (Node argUsage : arg.usages()) {
                                         if (graph.isNew(beforeInvokeMark, argUsage) && argUsage instanceof Canonicalizable) {
                                             canonicalizerUsages.add(argUsage);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Fri Oct 25 01:39:54 2013 +0200
@@ -198,7 +198,7 @@
     public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final Assumptions assumptions) {
         final PhasePlan plan = createPhasePlan(config);
 
-        Debug.scope("TruffleFinal", graph, new Runnable() {
+        Debug.scope("TruffleFinal", new Runnable() {
 
             @Override
             public void run() {
@@ -211,10 +211,15 @@
             @Override
             public CompilationResult call() {
                 try (TimerCloseable a = CompilationTime.start()) {
-                    CodeCacheProvider codeCache = providers.getCodeCache();
-                    CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false);
-                    return GraalCompiler.compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, plan, OptimisticOptimizations.ALL, new SpeculationLog(), suites,
-                                    new CompilationResult());
+                    return Debug.scope("GraalCompiler", new Object[]{providers.getCodeCache()}, new Callable<CompilationResult>() {
+                        public CompilationResult call() {
+                            CodeCacheProvider codeCache = providers.getCodeCache();
+                            CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false);
+                            CompilationResult compilationResult = new CompilationResult(compilable.toString());
+                            return GraalCompiler.compileGraphNoScope(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, plan, OptimisticOptimizations.ALL,
+                                            new SpeculationLog(), suites, compilationResult);
+                        }
+                    });
                 }
             }
         });
@@ -235,7 +240,7 @@
 
         result.setAssumptions(newAssumptions);
 
-        InstalledCode compiledMethod = Debug.scope("CodeInstall", new Object[]{graph.method()}, new Callable<InstalledCode>() {
+        InstalledCode compiledMethod = Debug.scope("CodeInstall", new Object[]{providers.getCodeCache()}, new Callable<InstalledCode>() {
 
             @Override
             public InstalledCode call() throws Exception {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java	Fri Oct 25 01:39:54 2013 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.truffle.api.impl.*;
+
+/**
+ * Enables a Truffle compilable to masquerade as a {@link JavaMethod} for use as a context value in
+ * {@linkplain Debug#scope(String, Object[], Runnable) debug scopes}.
+ */
+public class TruffleDebugJavaMethod implements JavaMethod {
+    private final DefaultCallTarget compilable;
+
+    private static final JavaType declaringClass = new JavaType() {
+
+        public String getName() {
+            return "LTruffle;";
+        }
+
+        public JavaType getComponentType() {
+            return null;
+        }
+
+        public JavaType getArrayClass() {
+            throw new UnsupportedOperationException();
+        }
+
+        public Kind getKind() {
+            return Kind.Object;
+        }
+
+        public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return obj.getClass() == getClass();
+        }
+
+        @Override
+        public int hashCode() {
+            return getName().hashCode();
+        }
+    };
+
+    private static final Signature signature = new Signature() {
+
+        public JavaType getReturnType(ResolvedJavaType accessingClass) {
+            return declaringClass;
+        }
+
+        public Kind getReturnKind() {
+            return declaringClass.getKind();
+        }
+
+        public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        public int getParameterSlots(boolean withReceiver) {
+            return 0;
+        }
+
+        public Kind getParameterKind(int index) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        public int getParameterCount(boolean receiver) {
+            return 0;
+        }
+    };
+
+    public TruffleDebugJavaMethod(DefaultCallTarget compilable) {
+        this.compilable = compilable;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof TruffleDebugJavaMethod) {
+            TruffleDebugJavaMethod other = (TruffleDebugJavaMethod) obj;
+            return other.compilable.equals(compilable);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return compilable.hashCode();
+    }
+
+    public Signature getSignature() {
+        return signature;
+    }
+
+    public String getName() {
+        return compilable.toString().replace('.', '_').replace(' ', '_');
+    }
+
+    public JavaType getDeclaringClass() {
+        return declaringClass;
+    }
+
+    @Override
+    public String toString() {
+        return format("Truffle<%n(%p)>", this);
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -163,7 +163,7 @@
             ConstantNode tagDefault = ConstantNode.forByte((byte) 0, graph());
             for (int i = 0; i < frameSize; i++) {
                 objectArrayEntryState[i] = objectDefault;
-                primitiveArrayEntryState[i] = initialValue(frameDescriptor.getSlots().get(i).getKind());
+                primitiveArrayEntryState[i] = initialPrimitiveValue(frameDescriptor.getSlots().get(i).getKind());
                 tagArrayEntryState[i] = tagDefault;
             }
             tool.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion()));
@@ -186,7 +186,7 @@
         tool.replaceWithVirtual(virtualFrame);
     }
 
-    private ValueNode initialValue(FrameSlotKind kind) {
+    private ValueNode initialPrimitiveValue(FrameSlotKind kind) {
         Kind graalKind = null;
         switch (kind) {
             case Boolean:
@@ -208,9 +208,8 @@
                 graalKind = Kind.Long;
                 break;
             case Object:
-                graalKind = Kind.Object;
-                break;
             case Illegal:
+                // won't be stored in the primitive array, so default to long
                 graalKind = Kind.Long;
                 break;
             default:
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Fri Oct 25 01:39:54 2013 +0200
@@ -34,6 +34,9 @@
 public class OptimizedCallTargetSubstitutions {
 
     @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
+    public static native Object call(OptimizedCallTarget target, PackedFrame caller, Arguments args);
+
+    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
     public static native Object callHelper(OptimizedCallTarget target, PackedFrame caller, Arguments args);
 
     @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Fri Oct 25 01:39:54 2013 +0200
@@ -531,8 +531,10 @@
     void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node) {
         if (node.isAlive()) {
             aliases.set(node, virtual);
-            for (Node usage : node.usages()) {
-                markVirtualUsages(usage);
+            if (node.recordsUsages()) {
+                for (Node usage : node.usages()) {
+                    markVirtualUsages(usage);
+                }
             }
         }
     }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Fri Oct 25 01:39:54 2013 +0200
@@ -61,6 +61,9 @@
         wordAccess.inferStamps(graph);
 
         for (ValueNode node : graph.getNodes().filter(ValueNode.class)) {
+            if (!node.recordsUsages()) {
+                continue;
+            }
             for (Node usage : node.usages()) {
                 if (usage instanceof AccessMonitorNode) {
                     verify(!isWord(node), node, usage, "word value has no monitor");
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Fri Oct 25 01:39:54 2013 +0200
@@ -306,7 +306,7 @@
             case LONG:
                 return "Long";
             case DECLARED:
-                return ((DeclaredType) mirror).asElement().getSimpleName().toString();
+                return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString());
             case ARRAY:
                 return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
             case VOID:
@@ -379,7 +379,7 @@
     }
 
     private static String getDeclaredName(DeclaredType element) {
-        String simpleName = element.asElement().getSimpleName().toString();
+        String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString());
 
         if (element.getTypeArguments().size() == 0) {
             return simpleName;
@@ -399,6 +399,14 @@
         return b.toString();
     }
 
+    public static String fixECJBinaryNameIssue(String name) {
+        if (name.contains("$")) {
+            int lastIndex = name.lastIndexOf('$');
+            return name.substring(lastIndex + 1, name.length());
+        }
+        return name;
+    }
+
     public static String getQualifiedName(TypeElement element) {
         String qualifiedName = element.getQualifiedName().toString();
         if (qualifiedName.contains("$")) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java	Fri Oct 25 01:39:54 2013 +0200
@@ -135,7 +135,7 @@
     }
 
     private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) {
-        String name = type.asElement().getSimpleName().toString();
+        String name = Utils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString());
 
         if (needsImport(enclosedElement, type)) {
             TypeMirror usedByType = simpleNamesUsed.get(name);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Fri Oct 25 01:39:54 2013 +0200
@@ -964,16 +964,78 @@
                 for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
                     clazz.add(method);
                 }
-
                 clazz.add(createGenericExecuteAndSpecialize(node, rootGroup));
                 clazz.add(createInfoMessage(node));
             }
 
+            if (needsInvokeCopyConstructorMethod()) {
+                clazz.add(createInvokeCopyConstructor(clazz.asType(), null));
+                clazz.add(createCopyPolymorphicConstructor(clazz.asType()));
+            }
+
             if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
                 clazz.add(createGenericExecute(node, rootGroup));
             }
         }
 
+        protected boolean needsInvokeCopyConstructorMethod() {
+            return getModel().getNode().isPolymorphic();
+        }
+
+        protected CodeExecutableElement createInvokeCopyConstructor(TypeMirror baseType, SpecializationData specialization) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), baseType, "invokeCopyConstructor");
+            if (specialization == null) {
+                method.getModifiers().add(ABSTRACT);
+            } else {
+                CodeTreeBuilder builder = method.createBuilder();
+                builder.startReturn();
+                builder.startNew(getElement().asType());
+                builder.string("this");
+                for (ActualParameter param : getImplicitTypeParamters(specialization)) {
+                    builder.string(implicitTypeName(param));
+                }
+                builder.end().end();
+            }
+            return method;
+        }
+
+        protected CodeExecutableElement createCopyPolymorphicConstructor(TypeMirror baseType) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), baseType, "copyPolymorphic");
+            CodeTreeBuilder builder = method.createBuilder();
+            CodeTreeBuilder nullBuilder = builder.create();
+            CodeTreeBuilder oldBuilder = builder.create();
+            CodeTreeBuilder resetBuilder = builder.create();
+
+            for (ActualParameter param : getModel().getParameters()) {
+                if (!param.getSpecification().isSignature()) {
+                    continue;
+                }
+                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+
+                CodeTreeBuilder access = builder.create();
+                access.string("this.").string(child.getName());
+                if (child.getCardinality().isMany()) {
+                    access.string("[").string(String.valueOf(param.getIndex())).string("]");
+                }
+
+                String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName());
+                oldBuilder.declaration(child.getNodeData().getNodeType(), oldName, access);
+                nullBuilder.startStatement().tree(access.getRoot()).string(" = null").end();
+                resetBuilder.startStatement().tree(access.getRoot()).string(" = ").string(oldName).end();
+            }
+
+            builder.tree(oldBuilder.getRoot());
+            builder.tree(nullBuilder.getRoot());
+
+            builder.startStatement().type(baseType).string(" copy = ");
+            builder.startCall("invokeCopyConstructor").end();
+            builder.end();
+
+            builder.tree(resetBuilder.getRoot());
+            builder.startReturn().string("copy").end();
+            return method;
+        }
+
         private List<CodeExecutableElement> createImplicitChildrenAccessors() {
             NodeData node = getModel().getNode();
             // Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>();
@@ -1795,27 +1857,14 @@
             String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
             CodeTreeBuilder builder = parent.create();
 
+            builder.declaration(getElement().asType(), "currentCopy", currentNode + ".copyPolymorphic()");
             builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end());
-
-            for (ActualParameter param : node.getGenericSpecialization().getParameters()) {
-                if (!param.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeChildData child = node.findChild(param.getSpecification().getName());
-                if (child != null) {
-                    builder.startStatement().string(currentNode).string(".").string(child.getName());
-                    if (child.getCardinality().isMany()) {
-                        builder.string("[").string(String.valueOf(param.getIndex())).string("]");
-                    }
-                    builder.string(" = null").end();
-                }
-            }
             builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end();
-            builder.startStatement().startCall("polymorphic", "setNext0").string(currentNode).end().end();
-            builder.startStatement().startCall(currentNode, "setNext0").startNew(uninitializedName).string(currentNode).end().end().end();
+            builder.startStatement().startCall("polymorphic", "setNext0").string("currentCopy").end().end();
+            builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end();
 
             builder.startReturn();
-            builder.startCall(currentNode + ".next0", executeCachedName(node.getGenericPolymorphicSpecialization()));
+            builder.startCall("currentCopy.next0", executeCachedName(node.getGenericPolymorphicSpecialization()));
             addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null);
             builder.end();
             builder.end();
@@ -1981,6 +2030,21 @@
             }
         }
 
+        protected final List<ActualParameter> getImplicitTypeParamters(SpecializationData model) {
+            List<ActualParameter> parameter = new ArrayList<>();
+            for (ActualParameter param : model.getParameters()) {
+                if (!param.getSpecification().isSignature()) {
+                    continue;
+                }
+                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+                List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                if (types.size() > 1) {
+                    parameter.add(param);
+                }
+            }
+            return parameter;
+        }
+
         protected final TreeSet<TypeData> lookupPolymorphicTargetTypes(ActualParameter param) {
             SpecializationData specialization = getModel();
             TreeSet<TypeData> possiblePolymorphicTypes = new TreeSet<>();
@@ -2529,6 +2593,10 @@
                 getElement().add(createUpdateType(parameter));
             }
 
+            if (needsInvokeCopyConstructorMethod()) {
+                clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization));
+            }
+
             createCachedExecuteMethods(specialization);
 
         }
@@ -2607,6 +2675,9 @@
             if (specialization.getNode().isPolymorphic()) {
                 getElement().add(createUpdateTypes(nodeGen.asType()));
             }
+            if (needsInvokeCopyConstructorMethod()) {
+                clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization));
+            }
         }
 
         protected void createConstructors(CodeTypeElement clazz) {
@@ -2636,20 +2707,13 @@
                         builder.statement("this.next0 = null");
                     }
 
-                    for (ActualParameter param : getModel().getParameters()) {
-                        if (!param.getSpecification().isSignature()) {
-                            continue;
-                        }
-                        NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
-                        List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-                        if (types.size() > 1) {
-                            clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
-                            superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
-
-                            builder.startStatement();
-                            builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param));
-                            builder.end();
-                        }
+                    for (ActualParameter param : getImplicitTypeParamters(getModel())) {
+                        clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
+                        superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
+
+                        builder.startStatement();
+                        builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param));
+                        builder.end();
                     }
 
                     clazz.add(superConstructor);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java	Fri Oct 25 01:39:54 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.truffle.sl.nodes;
 
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
 
 public class BlockNode extends StatementNode {
 
@@ -33,6 +34,7 @@
     }
 
     @Override
+    @ExplodeLoop
     public void executeVoid(VirtualFrame frame) {
         for (StatementNode statement : statements) {
             statement.executeVoid(frame);
--- a/make/solaris/makefiles/jsig.make	Tue Oct 22 15:06:02 2013 +0200
+++ b/make/solaris/makefiles/jsig.make	Fri Oct 25 01:39:54 2013 +0200
@@ -79,9 +79,9 @@
 
 install_jsig: $(LIBJSIG)
 	@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
-	$(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \
+	-$(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \
 	    cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO)
-	$(QUIETLY) test -f $(LIBJSIG_DIZ) && \
+	-$(QUIETLY) test -f $(LIBJSIG_DIZ) && \
 	    cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ)
 	$(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done"
 
--- a/make/solaris/makefiles/vm.make	Tue Oct 22 15:06:02 2013 +0200
+++ b/make/solaris/makefiles/vm.make	Fri Oct 25 01:39:54 2013 +0200
@@ -341,9 +341,9 @@
 
 install_jvm: $(LIBJVM)
 	@echo "Copying $(LIBJVM) to $(DEST_JVM)"
-	$(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \
+	-$(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \
 	    cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO)
-	$(QUIETLY) test -f $(LIBJVM_DIZ) && \
+	-$(QUIETLY) test -f $(LIBJVM_DIZ) && \
 	    cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ)
 	$(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done"
 
--- a/mx/commands.py	Tue Oct 22 15:06:02 2013 +0200
+++ b/mx/commands.py	Fri Oct 25 01:39:54 2013 +0200
@@ -244,7 +244,7 @@
     if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']:
         return 'amd64'
     if machine in ['sun4v', 'sun4u']:
-        return 'sparc'
+        return 'sparcv9'
     if machine == 'i386' and mx.get_os() == 'darwin':
         try:
             # Support for Snow Leopard and earlier version of MacOSX
@@ -320,11 +320,14 @@
                 for line in f:
                     if line.startswith('-') and defaultVM is None:
                         parts = line.split()
-                        assert len(parts) == 2, parts
-                        assert parts[1] == 'KNOWN', parts[1]
-                        defaultVM = parts[0][1:]
-                        jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n']
-                        jvmCfgLines += ['-original KNOWN\n']
+                        if len(parts) == 2:
+                            assert parts[1] == 'KNOWN', parts[1]
+                            defaultVM = parts[0][1:]
+                            jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n']
+                            jvmCfgLines += ['-original KNOWN\n']
+                        else:
+                            # skip lines which we cannot parse (e.g. '-hotspot ALIASED_TO -client')
+                            pass
                     else:
                         jvmCfgLines += [line]
 
--- a/mxtool/mx.py	Tue Oct 22 15:06:02 2013 +0200
+++ b/mxtool/mx.py	Fri Oct 25 01:39:54 2013 +0200
@@ -27,119 +27,9 @@
 #
 
 r"""
-mx is a command line tool inspired by mvn (http://maven.apache.org/)
-and hg (http://mercurial.selenic.com/). It includes a mechanism for
-managing the dependencies between a set of projects (like Maven)
-as well as making it simple to run commands
-(like hg is the interface to the Mercurial commands).
-
-The organizing principle of mx is a project suite. A suite is a directory
-containing one or more projects. It's not coincidental that this closely
-matches the layout of one or more projects in a Mercurial repository.
-The configuration information for a suite lives in an 'mx' sub-directory
-at the top level of the suite. A suite is given a name by a 'suite=name'
-property in the 'mx/projects' file (if omitted the name is suite directory).
-An 'mx' subdirectory can be named as plain 'mx' or 'mx.name', where
-'name' is typically the name as the suite name.
-The latter is useful to avoid clashes in IDE project names.
-
-When launched, mx treats the current working directory as a suite.
-This is the primary suite. All other suites are called included suites.
-
-The configuration files (i.e. in the 'mx' sub-directory) of a suite are:
-
-  projects
-      Defines the projects and libraries in the suite and the
-      dependencies between them.
-
-  commands.py
-      Suite specific extensions to the commands available to mx.
-
-  imports
-      Other suites to be loaded. This is recursive. Each
-      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 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
-in the file specifies an attribute of a project or library. The main
-difference between a project and a library is that the former contains
-source code built by the mx tool where as the latter is an external
-dependency. The format of the projects file is
-
-Library specification format:
-
-    library@<name>@<prop>=<value>
-
-Built-in library properties (* = required):
-
-   *path
-        The file system path for the library to appear on a class path.
-
-    urls
-        A comma separated list of URLs from which the library (jar) can
-        be downloaded and saved in the location specified by 'path'.
-
-    optional
-        If "true" then this library will be omitted from a class path
-        if it doesn't exist on the file system and no URLs are specified.
-
-    sourcePath
-        The file system path for a jar file containing the library sources.
-
-    sourceUrls
-        A comma separated list of URLs from which the library source jar can
-        be downloaded and saved in the location specified by 'sourcePath'.
-
-Project specification format:
-
-    project@<name>@<prop>=<value>
-
-The name of a project also denotes the directory it is in.
-
-Built-in project properties (* = required):
-
-    subDir
-        The sub-directory of the suite in which the project directory is
-        contained. If not specified, the project directory is directly
-        under the suite directory.
-
-   *sourceDirs
-        A comma separated list of source directory names (relative to
-        the project directory).
-
-    dependencies
-        A comma separated list of the libraries and project the project
-        depends upon (transitive dependencies should be omitted).
-
-    checkstyle
-        The project whose Checkstyle configuration
-        (i.e. <project>/.checkstyle_checks.xml) is used.
-
-    native
-        "true" if the project is native.
-
-    javaCompliance
-        The minimum JDK version (format: x.y) to which the project's
-        sources comply (required for non-native projects).
-
-    workingSets
-        A comma separated list of working set names. The project belongs
-        to the given working sets, for which the eclipseinit command
-        will generate Eclipse configurations.
-
-Other properties can be specified for projects and libraries for use
-by extension commands.
-
-Property values can use environment variables with Bash syntax (e.g. ${HOME}).
+mx is a command line tool for managing the development of Java code organized as suites of projects.
+
+Full documentation can be found at https://wiki.openjdk.java.net/display/Graal/The+mx+Tool
 """
 
 import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch
@@ -156,7 +46,8 @@
 _dists = dict()
 _suites = dict()
 _annotationProcessors = None
-_mainSuite = None
+_primary_suite_path = None
+_primary_suite = None
 _src_suitemodel = None
 _dst_suitemodel = None
 _opts = None
@@ -514,19 +405,16 @@
             except OSError:
                 self.has_hg = False
                 warn(self.missing)
-            
+
         if not self.has_hg:
             if abortOnFail:
                 abort(self.missing)
             else:
                 warn(self.missing)
 
-    def tip(self, s, abortOnError=True):
+    def tip(self, sDir, 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
+            return subprocess.check_output(['hg', 'tip', '-R', sDir, '--template', '{node}'])
         except OSError:
             warn(self.missing)
         except subprocess.CalledProcessError:
@@ -564,19 +452,19 @@
         self.primaryDir = None
         self.suitenamemap = {}
 
-    def _find_suite_dir(self, suitename):
+    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):
+        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):
+    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):
+        abort('importee_dir not implemented')
+
+    def nestedsuites_dirname(self):
         """Returns the dirname that contains any nested suites if the model supports that"""
         return None
 
@@ -613,7 +501,7 @@
             self.suitenamemap[mappair[0]] = mappair[1]
 
     @staticmethod
-    def _set_suitemodel(option, suitemap):
+    def set_suitemodel(option, suitemap):
         if option.startswith('sibling'):
             return SiblingSuiteModel(os.getcwd(), option, suitemap)
         elif option.startswith('nested'):
@@ -624,7 +512,7 @@
             abort('unknown suitemodel type: ' + option)
 
     @staticmethod
-    def _parse_options():
+    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):
@@ -650,13 +538,15 @@
                 # to get warnings on suite loading issues before command line is parsed
                 global _warn
                 _warn = True
-
+            elif arg == '-p' or arg == '--primary-suite-path':
+                global _primary_suite_path
+                _primary_suite_path = os.path.abspath(_get_argvalue(arg, args, i + 1))
             i = i + 1
 
         global _src_suitemodel
-        _src_suitemodel = SuiteModel._set_suitemodel(src_suitemodel_arg, suitemap_arg)
+        _src_suitemodel = SuiteModel.set_suitemodel(src_suitemodel_arg, suitemap_arg)
         global _dst_suitemodel
-        _dst_suitemodel = SuiteModel._set_suitemodel(dst_suitemodel_arg, suitemap_arg)
+        _dst_suitemodel = SuiteModel.set_suitemodel(dst_suitemodel_arg, suitemap_arg)
 
 
 class SiblingSuiteModel(SuiteModel):
@@ -666,14 +556,14 @@
         self._suiteRootDir = suiteRootDir
         self._create_suitenamemap(option[len('sibling:'):], suitemap)
 
-    def _find_suite_dir(self, name):
+    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)
+    def set_primary_dir(self, d):
+        SuiteModel.set_primary_dir(self, d)
         self._suiteRootDir = dirname(d)
 
-    def _importee_dir(self, importer_dir, suitename):
+    def importee_dir(self, importer_dir, suitename):
         if self.suitenamemap.has_key(suitename):
             suitename = self.suitenamemap[suitename]
         return join(dirname(importer_dir), suitename)
@@ -688,10 +578,10 @@
         self._primaryDir = primaryDir
         self._create_suitenamemap(option[len('nested:'):], suitemap)
 
-    def _find_suite_dir(self, name):
+    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):
+    def importee_dir(self, importer_dir, suitename):
         if self.suitenamemap.has_key(suitename):
             suitename = self.suitenamemap[suitename]
         if basename(importer_dir) == basename(self._primaryDir):
@@ -703,7 +593,7 @@
         else:
             return join(dirname(importer_dir), suitename)
 
-    def _nestedsuites_dirname(self):
+    def nestedsuites_dirname(self):
         return self._imported_suites_dirname()
 
 class PathSuiteModel(SuiteModel):
@@ -722,13 +612,13 @@
                 suiteurl = pair[0]
             self.suit_to_url[suitename] = suiteurl
 
-    def _find_suite_dir(self, suitename):
+    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):
+    def importee_dir(self, importer_dir, suitename):
         if suitename in self.suit_to_url:
             return self.suit_to_url[suitename]
         else:
@@ -740,7 +630,7 @@
         self.version = version
 
     @staticmethod
-    def _parse_specification(specification):
+    def parse_specification(specification):
         pair = specification.split(',')
         name = pair[0]
         if len(pair) > 1:
@@ -750,7 +640,7 @@
         return SuiteImport(name, version)
 
     @staticmethod
-    def _tostring(name, version):
+    def tostring(name, version):
         return name + ',' + version
 
     def __str__(self):
@@ -767,9 +657,6 @@
         self.commands = None
         self.primary = primary
         self.name = _suitename(mxDir)  # validated in _load_projects
-        self.version = None  # _hg.tip checks current version if not None
-        # TODO this forces hg to be run every time mx is run
-        #self.version = _hg.tip(self, False)
         if load:
             # load suites bottom up to make sure command overriding works properly
             self._load_imports()
@@ -780,6 +667,10 @@
     def __str__(self):
         return self.name
 
+    def version(self, abortOnError=True):
+        # we do not cache the version
+        return _hg.tip(self.dir, abortOnError)
+
     def _load_projects(self):
         libsMap = dict()
         projsMap = dict()
@@ -877,7 +768,7 @@
             abort('Missing "suite=<name>" in ' + projectsFile)
 
     def _commands_name(self):
-        return 'mx_' + self.name
+        return 'mx_' + self.name.replace('-', '_')
 
     def _find_commands(self, name):
         commandsPath = join(self.mxDir, name + '.py')
@@ -912,7 +803,7 @@
             mod.mx_init(self)
             self.commands = mod
 
-    def _visit_imports(self, visitor, **extra_args):
+    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
@@ -922,7 +813,7 @@
         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
+        as this function only visits the imports of a single 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')
@@ -937,25 +828,25 @@
                         if out is not None:
                             out.write(sline + '\n')
                         continue
-                    suite_import = SuiteImport._parse_specification(line.strip())
+                    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):
+    def _find_and_loadsuite(importing_suite, suite_import, **extra_args):
         """visitor for the initial suite load"""
-        importMxDir = _src_suitemodel._find_suite_dir(suite_import.name)
+        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)
+        importing_suite.imports.append(suite_import)
+        _loadSuite(importMxDir, False)
+        # we do not check at this stage whether the tip version of imported_suite
+        # matches that of the import, since during development, this can and will change
 
     def _load_imports(self):
-        self._visit_imports(self._find_and_loadsuite)
+        self.visit_imports(self._find_and_loadsuite)
 
     def _load_env(self):
         e = join(self.mxDir, 'env')
@@ -1320,7 +1211,7 @@
         else:
             break
 
-    envPath = join(_mainSuite.mxDir, 'env')
+    envPath = join(_primary_suite.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
@@ -1341,6 +1232,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('-p', '--primary-suite-path', help='set the primary suite directory', metavar='<path>')
         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>')
@@ -1909,7 +1801,7 @@
 
     javaCompliance = java().javaCompliance
 
-    defaultEcjPath = join(_mainSuite.mxDir, 'ecj.jar')
+    defaultEcjPath = join(_primary_suite.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)')
@@ -2228,7 +2120,7 @@
     if len(modified) != 0:
         if args.backup:
             backup = os.path.abspath('eclipseformat.backup.zip')
-            arcbase = _mainSuite.dir
+            arcbase = _primary_suite.dir
             zf = zipfile.ZipFile(backup, 'w', zipfile.ZIP_DEFLATED)
             for fi in modified:
                 arcname = os.path.relpath(fi.path, arcbase).replace(os.sep, '/')
@@ -2482,7 +2374,7 @@
         self.path = path
         self.timestamp = os.path.getmtime(path) if exists(path) else None
 
-    def outOfDate(self, arg):
+    def isOlderThan(self, arg):
         if not self.timestamp:
             return True
         if isinstance(arg, types.ListType):
@@ -2542,7 +2434,7 @@
             timestamp = TimeStampFile(join(p.suite.mxDir, 'checkstyle-timestamps', sourceDir[len(p.suite.dir) + 1:].replace(os.sep, '_') + '.timestamp'))
             mustCheck = False
             if not args.force and timestamp.exists():
-                mustCheck = timestamp.outOfDate(javafilelist)
+                mustCheck = timestamp.isOlderThan(javafilelist)
             else:
                 mustCheck = True
 
@@ -2853,7 +2745,7 @@
     if refreshOnly and not timestamp.exists():
         return
 
-    if not timestamp.outOfDate(projectsFile):
+    if not timestamp.isOlderThan(projectsFile) and not TimeStampFile(projectsFile).isOlderThan(__file__):
         logv('[Eclipse configurations are up to date - skipping]')
         return
 
@@ -3067,7 +2959,7 @@
     launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'})
     if logToFile:
         logFile = join(externalToolDir, name + '.log')
-        launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE', 'value': logFile})
+        launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE', 'value': logFile})
         launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_APPEND_TO_FILE', 'value': 'true' if appendToLogFile else 'false'})
 
     # expect to find the OS command to invoke mx in the same directory
@@ -3125,7 +3017,7 @@
     if os.environ.has_key('WORKSPACE'):
         expected_wsroot = os.environ['WORKSPACE']
     else:
-        expected_wsroot = _mainSuite.dir
+        expected_wsroot = _primary_suite.dir
 
     wsroot = _find_eclipse_wsroot(expected_wsroot)
     if wsroot is None:
@@ -3263,7 +3155,7 @@
     if refreshOnly and not timestamp.exists():
         return
 
-    if not timestamp.outOfDate(projectsFile):
+    if not timestamp.isOlderThan(projectsFile) and not TimeStampFile(projectsFile).isOlderThan(__file__):
         logv('[NetBeans configurations are up to date - skipping]')
         return
 
@@ -3529,8 +3421,8 @@
                 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())
+                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[:] = []
@@ -3682,7 +3574,7 @@
             names.append(p.name)
 
         links = ['-link', 'http://docs.oracle.com/javase/' + str(_java.javaCompliance.value) + '/docs/api/']
-        out = join(_mainSuite.dir, docDir)
+        out = join(_primary_suite.dir, docDir)
         if args.base is not None:
             out = join(args.base, docDir)
         cp = classpath()
@@ -3951,7 +3843,7 @@
 
 def sclone(args):
     """clone a suite repository, and its imported suites"""
-    _hg.check(True)
+    _hg.check()
     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>')
@@ -3968,11 +3860,11 @@
 
     if args.source is None:
         # must be primary suite and dest is required
-        if _mainSuite is None:
+        if _primary_suite 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
+        source = _primary_suite.dir
     else:
         source = args.source
 
@@ -3983,8 +3875,8 @@
 
     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)
+    _dst_suitemodel.set_primary_dir(dest)
+    _src_suitemodel.set_primary_dir(source)
 
     _sclone(source, dest, None, args.no_imports)
 
@@ -4006,12 +3898,12 @@
     # 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)
+        s.visit_imports(_scloneimports_visitor, source=source)
     return s
 
 def _scloneimports_visitor(s, suite_import, source, **extra_args):
     """
-    cloneimports visitor for Suite._visit_imports.
+    cloneimports visitor for Suite.visit_imports.
     The destination information is encapsulated by 's'
     """
     _scloneimports(s, suite_import, source)
@@ -4026,18 +3918,21 @@
 
 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)
+    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):
+        # already exists in the suite model, but may be wrong version
         importee_suite = _scloneimports_suitehelper(importee_dest)
-        importee_suite._visit_imports(_scloneimports_visitor, source=importee_source)
+        if suite_import.version is not None and importee_suite.version() != suite_import.version:
+            abort("imported version of " + suite_import.name + " in " + s.name + " does not match the version in already existing suite: " + importee_suite.dir)
+        importee_suite.visit_imports(_scloneimports_visitor, source=importee_source)
     else:
         _sclone(importee_source, importee_dest, suite_import.version, False)
         # _clone handles the recursive visit of the new imports
 
 def scloneimports(args):
     """clone the imports of an existing suite"""
-    _hg.check(True)
+    _hg.check()
     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]...')
@@ -4058,21 +3953,21 @@
 
     # 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)
+    _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"""
+    """push visitor for Suite.visit_imports"""
     if dest is not None:
-        dest = _dst_suitemodel._importee_dir(dest, suite_import.name)
+        dest = _dst_suitemodel.importee_dir(dest, suite_import.name)
     _spush(suite(suite_import.name), suite_import, dest, checks, clonemissing)
 
 def _spush_check_import_visitor(s, suite_import, **extra_args):
-    """push check visitor for Suite._visit_imports"""
-    currentTip = _hg.tip(suite(suite_import.name))
+    """push check visitor for Suite.visit_imports"""
+    currentTip = suite(suite_import.name).version()
     if currentTip != suite_import.version:
-        abort('import version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip')
+        abort('imported version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip')
 
 def _spush(s, suite_import, dest, checks, clonemissing):
     if checks:
@@ -4081,10 +3976,10 @@
 
     # check imports first
     if checks:
-        s._visit_imports(_spush_check_import_visitor)
+        s.visit_imports(_spush_check_import_visitor)
 
     # ok, push imports
-    s._visit_imports(_spush_import_visitor, dest=dest, checks=checks, clonemissing=clonemissing)
+    s.visit_imports(_spush_import_visitor, dest=dest, checks=checks, clonemissing=clonemissing)
 
     dest_exists = True
 
@@ -4116,7 +4011,7 @@
 
 def spush(args):
     """push primary suite and all its imports"""
-    _hg.check(True)
+    _hg.check()
     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')
@@ -4139,7 +4034,7 @@
         args.nochecks = True
 
     if args.dest is not None:
-        _dst_suitemodel._set_primary_dir(args.dest)
+        _dst_suitemodel.set_primary_dir(args.dest)
 
     _spush(s, None, args.dest, not args.no_checks, args.clonemissing)
 
@@ -4147,29 +4042,29 @@
     _supdate(suite(suite_import.name), suite_import)
 
 def _supdate(s, suite_import):
-    s._visit_imports(_supdate_import_visitor)
+    s.visit_imports(_supdate_import_visitor)
 
     run(['hg', '-R', s.dir, 'update'])
 
 def supdate(args):
     """update primary suite and all its imports"""
 
-    _hg.check(True)
+    _hg.check()
     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):
+    """scheckimports visitor for Suite.visit_imports"""
+    _scheck_imports(s, suite(suite_import.name), suite_import, update_versions, updated_imports)
+
+def _scheck_imports(importing_suite, imported_suite, suite_import, update_versions, updated_imports):
     # check imports recursively
-    s._visit_imports(_scheck_imports_visitor, update_versions=update_versions)
-
-    currentTip = _hg.tip(s)
+    imported_suite.visit_imports(_scheck_imports_visitor, update_versions=update_versions)
+
+    currentTip = imported_suite.version()
     if currentTip != suite_import.version:
-        print('import version of ' + s.name + ' does not match tip' + (': updating' if update_versions else ''))
+        print('imported version of ' + imported_suite.name + ' in ' + importing_suite.name + ' does not match tip' + (': updating' if update_versions else ''))
 
     if update_versions:
         suite_import.version = currentTip
@@ -4181,25 +4076,25 @@
     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)
+    _check_primary_suite().visit_imports(_scheck_imports_visitor, update_versions=args.update_versions)
 
 def _spull_import_visitor(s, suite_import, update_versions, updated_imports):
-    """pull visitor for Suite._visit_imports"""
+    """pull visitor for Suite.visit_imports"""
     _spull(suite(suite_import.name), update_versions, updated_imports)
 
 def _spull(s, update_versions, updated_imports):
-    _hg.check(True)
+    _hg.check()
     # pull imports first
-    s._visit_imports(_spull_import_visitor, update_versions=update_versions)
+    s.visit_imports(_spull_import_visitor, update_versions=update_versions)
 
     run(['hg', '-R', s.dir, 'pull', '-u'])
     if update_versions and updated_imports is not None:
-        tip = _hg.tip(s)
-        updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n')
+        tip = s.version()
+        updated_imports.write(SuiteImport.tostring(s.name, tip) + '\n')
 
 def spull(args):
     """pull primary suite and all its imports"""
-    _hg.check(True)
+    _hg.check()
     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)
@@ -4380,48 +4275,74 @@
                     return mxDir
 
 def _check_primary_suite():
-    if _mainSuite is None:
+    if _primary_suite is None:
         abort('no primary suite found')
     else:
-        return _mainSuite
+        return _primary_suite
 
 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)
+def _needs_primary_suite_cl():
+    return not any("sclone" in s for s in sys.argv[1:])
+
+def _findPrimarySuiteMxDirFrom(d):
+    """ search for a suite directory upwards from 'd' """
+    while d:
+        mxDir = _is_suite_dir(d)
         if mxDir is not None:
             return mxDir
-        parent = dirname(curdir)
-        if curdir == parent:
+        parent = dirname(d)
+        if d == parent:
             return None
-        curdir = parent
+        d = parent
 
     return None
 
+def _findPrimarySuiteMxDir():
+    # check for explicit setting
+    if _primary_suite_path is not None:
+        mxDir = _is_suite_dir(_primary_suite_path)
+        if mxDir is not None:
+            return mxDir
+        else:
+            abort(_primary_suite_path + ' does not contain an mx suite')
+
+    # try current working directory first
+    mxDir = _findPrimarySuiteMxDirFrom(os.getcwd())
+    if mxDir is not None:
+        return mxDir
+    # backwards compatibility: search from path of this file
+    return _findPrimarySuiteMxDirFrom(dirname(__file__))
+
 def main():
-    SuiteModel._parse_options()
+    SuiteModel.parse_options()
 
     global _hg
     _hg = HgConfig()
 
+    primary_suite_error = 'no primary suite found'
     primarySuiteMxDir = _findPrimarySuiteMxDir()
     if primarySuiteMxDir:
-        _src_suitemodel._set_primary_dir(dirname(primarySuiteMxDir))
-        global _mainSuite
-        _mainSuite = _loadSuite(primarySuiteMxDir, True)
+        _src_suitemodel.set_primary_dir(dirname(primarySuiteMxDir))
+        global _primary_suite
+        _primary_suite = _loadSuite(primarySuiteMxDir, True)
+    else:
+        # in general this is an error, except for the sclone/scloneimports commands,
+        # and an extensions command will likely not parse in this case, as any extra arguments
+        # will not have been added to _argParser.
+        # If the command line does not contain a string matching one of the exceptions, we can safely abort,
+        # but not otherwise, as we can't be sure the string isn't in a value for some other option.
+        if _needs_primary_suite_cl():
+            abort(primary_suite_error)
 
     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)
+            abort(primary_suite_error)
         else:
-            warn(msg)
+            warn(primary_suite_error)
 
     global _opts, _java
     _opts = opts
--- a/src/cpu/x86/vm/vmStructs_x86.hpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/cpu/x86/vm/vmStructs_x86.hpp	Fri Oct 25 01:39:54 2013 +0200
@@ -43,7 +43,8 @@
 
 #define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
 
-#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
+  declare_constant(frame::arg_reg_save_area_bytes)
 
 #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
 
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Fri Oct 25 01:39:54 2013 +0200
@@ -385,7 +385,7 @@
      case T_INT:
        {
          int return_val;
-         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_INT_BYTE_SIZE);
+         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_INT_BYTE_SIZE);
          if (status != GRAAL_CUDA_SUCCESS) {
            tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status);
            return false;
@@ -396,7 +396,7 @@
      case T_BOOLEAN:
        {
          int return_val;
-         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_INT_BYTE_SIZE);
+         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_INT_BYTE_SIZE);
          if (status != GRAAL_CUDA_SUCCESS) {
            tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status);
            return false;
@@ -407,7 +407,7 @@
      case T_FLOAT:
        {
          float return_val;
-         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_FLOAT_BYTE_SIZE);
+         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_FLOAT_BYTE_SIZE);
          if (status != GRAAL_CUDA_SUCCESS) {
            tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status);
            return false;
@@ -418,7 +418,7 @@
      case T_DOUBLE:
        {
          double return_val;
-         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_DOUBLE_BYTE_SIZE);
+         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_DOUBLE_BYTE_SIZE);
          if (status != GRAAL_CUDA_SUCCESS) {
            tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status);
            return false;
@@ -429,7 +429,7 @@
      case T_LONG:
        {
          long return_val;
-         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_LONG_BYTE_SIZE);
+         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._dev_return_value, T_LONG_BYTE_SIZE);
          if (status != GRAAL_CUDA_SUCCESS) {
            tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status);
            return false;
@@ -443,11 +443,11 @@
        tty->print_cr("[CUDA] TODO *** Unhandled return type: %d", return_type);
   }
 
-  // handle post-invocation object and array arguemtn
-  ptxka.reiterate();
+  // Copy all reference arguments from device to host memory.
+  ptxka.copyRefArgsFromDtoH();
 
   // Free device memory allocated for result
-  status = gpu::Ptx::_cuda_cu_memfree(ptxka._return_value_ptr);
+  status = gpu::Ptx::_cuda_cu_memfree(ptxka._dev_return_value);
   if (status != GRAAL_CUDA_SUCCESS) {
     tty->print_cr("[CUDA] *** Error (%d) Failed to free device memory of return value", status);
     return false;
--- a/src/gpu/ptx/vm/ptxKernelArguments.cpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/gpu/ptx/vm/ptxKernelArguments.cpp	Fri Oct 25 01:39:54 2013 +0200
@@ -32,127 +32,132 @@
 // Get next java argument
 oop PTXKernelArguments::next_arg(BasicType expectedType) {
   assert(_index < _args->length(), "out of bounds");
-
   oop arg = ((objArrayOop) (_args))->obj_at(_index++);
   assert(expectedType == T_OBJECT ||
          java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
-
   return arg;
 }
 
 void PTXKernelArguments::do_int() {
-    if (is_after_invocation()) {
+  // If the parameter is a return value,
+  if (is_return_type()) {
+    if (is_kernel_arg_setup()) {
+      // Allocate device memory for T_INT return value pointer on device. Size in bytes
+      int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_INT_BYTE_SIZE);
+      if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+        _success = false;
         return;
+      }
+      // Push _dev_return_value to _kernelBuffer
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value;
     }
-    // If the parameter is a return value,
-    if (is_return_type()) {
-        // Allocate device memory for T_INT return value pointer on device. Size in bytes
-        int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_INT_BYTE_SIZE);
-        if (status != GRAAL_CUDA_SUCCESS) {
-            tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
-            _success = false;
-            return;
-        }
-        // Push _return_value_ptr to _kernelBuffer
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
-        _bufferOffset += sizeof(_return_value_ptr);
-    } else {
-        // Get the next java argument and its value which should be a T_INT
-        oop arg = next_arg(T_INT);
-        // Copy the java argument value to kernelArgBuffer
-        jvalue intval;
-        if (java_lang_boxing_object::get_value(arg, &intval) != T_INT) {
-            tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT");
-            _success = false;
-            return;
-        }
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = intval.i;
-        _bufferOffset += sizeof(intval.i);
+    _bufferOffset += sizeof(_dev_return_value);
+  } else {
+    // Get the next java argument and its value which should be a T_INT
+    oop arg = next_arg(T_INT);
+    // Copy the java argument value to kernelArgBuffer
+    jvalue intval;
+    if (java_lang_boxing_object::get_value(arg, &intval) != T_INT) {
+      tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT");
+      _success = false;
+      return;
     }
-    return;
+    if (is_kernel_arg_setup()) {
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = intval.i;
+    }
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(intval.i);
+  }
+  return;
 }
 
 void PTXKernelArguments::do_float() {
-    if (is_after_invocation()) {
+  // If the parameter is a return value,
+  if (is_return_type()) {
+    if (is_kernel_arg_setup()) {
+      // Allocate device memory for T_INT return value pointer on device. Size in bytes
+      int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_FLOAT_BYTE_SIZE);
+      if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+        _success = false;
         return;
+      }
+      // Push _dev_return_value to _kernelBuffer
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value;
     }
-    // If the parameter is a return value,
-    if (is_return_type()) {
-        // Allocate device memory for T_INT return value pointer on device. Size in bytes
-        int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_FLOAT_BYTE_SIZE);
-        if (status != GRAAL_CUDA_SUCCESS) {
-            tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
-            _success = false;
-            return;
-        }
-        // Push _return_value_ptr to _kernelBuffer
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
-        _bufferOffset += sizeof(_return_value_ptr);
-    } else {
-        // Get the next java argument and its value which should be a T_INT
-        oop arg = next_arg(T_FLOAT);
-        // Copy the java argument value to kernelArgBuffer
-        jvalue floatval;
-        if (java_lang_boxing_object::get_value(arg, &floatval) != T_FLOAT) {
-            tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT");
-            _success = false;
-            return;
-        }
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = (gpu::Ptx::CUdeviceptr) floatval.f;
-        _bufferOffset += sizeof(floatval.f);
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(_dev_return_value);
+  } else {
+    // Get the next java argument and its value which should be a T_FLOAT
+    oop arg = next_arg(T_FLOAT);
+    // Copy the java argument value to kernelArgBuffer
+    jvalue floatval;
+    if (java_lang_boxing_object::get_value(arg, &floatval) != T_FLOAT) {
+      tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_FLOAT");
+      _success = false;
+      return;
     }
-    return;
+    if (is_kernel_arg_setup()) {
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = (gpu::Ptx::CUdeviceptr) floatval.f;
+    }
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(floatval.f);
+  }
+  return;
 }
 
 void PTXKernelArguments::do_double() {
-    if (is_after_invocation()) {
+  // If the parameter is a return value,
+  jvalue doubleval;
+  if (is_return_type()) {
+    if (is_kernel_arg_setup()) {
+      // Allocate device memory for T_INT return value pointer on device. Size in bytes
+      int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_DOUBLE_BYTE_SIZE);
+      if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+        _success = false;
         return;
+      }
+      // Push _dev_return_value to _kernelBuffer
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value;
     }
-    // If the parameter is a return value,
-    jvalue doubleval;
-    if (is_return_type()) {
-        // Allocate device memory for T_INT return value pointer on device. Size in bytes
-        int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_DOUBLE_BYTE_SIZE);
-        if (status != GRAAL_CUDA_SUCCESS) {
-            tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
-            _success = false;
-            return;
-        }
-        // Push _return_value_ptr to _kernelBuffer
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
-        // _bufferOffset += sizeof(_return_value_ptr);
-        _bufferOffset += sizeof(doubleval.d);
-    } else {
-        // Get the next java argument and its value which should be a T_INT
-        oop arg = next_arg(T_FLOAT);
-        // Copy the java argument value to kernelArgBuffer
-        if (java_lang_boxing_object::get_value(arg, &doubleval) != T_DOUBLE) {
-            tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT");
-            _success = false;
-            return;
-        }
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = (gpu::Ptx::CUdeviceptr) doubleval.d;
-        _bufferOffset += sizeof(doubleval.d);
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(doubleval.d);
+  } else {
+    // Get the next java argument and its value which should be a T_INT
+    oop arg = next_arg(T_FLOAT);
+    // Copy the java argument value to kernelArgBuffer
+    if (java_lang_boxing_object::get_value(arg, &doubleval) != T_DOUBLE) {
+      tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT");
+      _success = false;
+      return;
     }
-    return;
+    if (is_kernel_arg_setup()) {
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = (gpu::Ptx::CUdeviceptr) doubleval.d;
+    }
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(doubleval.d);
+  }
+  return;
 }
 
 void PTXKernelArguments::do_long() {
-  if (is_after_invocation()) {
-    return;
-  }
   // If the parameter is a return value,
   if (is_return_type()) {
-    // Allocate device memory for T_LONG return value pointer on device. Size in bytes
-    int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_LONG_BYTE_SIZE);
-    if (status != GRAAL_CUDA_SUCCESS) {
-      tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
-      _success = false;
-      return;
+    if (is_kernel_arg_setup()) {
+      // Allocate device memory for T_LONG return value pointer on device. Size in bytes
+      int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_LONG_BYTE_SIZE);
+      if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+        _success = false;
+        return;
+      }
+      // Push _dev_return_value to _kernelBuffer
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value;
     }
-    // Push _return_value_ptr to _kernelBuffer
-    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
-    _bufferOffset += sizeof(_return_value_ptr);
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(_dev_return_value);
   } else {
     // Get the next java argument and its value which should be a T_LONG
     oop arg = next_arg(T_LONG);
@@ -163,119 +168,132 @@
       _success = false;
       return;
     }
-    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.j;
+    if (is_kernel_arg_setup()) {
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.j;
+    }
+    // Advance _bufferOffset
     _bufferOffset += sizeof(val.j);
   }
   return;
 }
 
 void PTXKernelArguments::do_byte() {
-    if (is_after_invocation()) {
+  // If the parameter is a return value,
+  if (is_return_type()) {
+    if (is_kernel_arg_setup()) {
+      // Allocate device memory for T_BYTE return value pointer on device. Size in bytes
+      int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_BYTE_SIZE);
+      if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+        _success = false;
         return;
+      }
+      // Push _dev_return_value to _kernelBuffer
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value;
     }
-    // If the parameter is a return value,
-    if (is_return_type()) {
-        // Allocate device memory for T_BYTE return value pointer on device. Size in bytes
-        int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_BYTE_SIZE);
-        if (status != GRAAL_CUDA_SUCCESS) {
-            tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
-            _success = false;
-            return;
-        }
-        // Push _return_value_ptr to _kernelBuffer
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
-        _bufferOffset += sizeof(_return_value_ptr);
-    } else {
-        // Get the next java argument and its value which should be a T_BYTE
-        oop arg = next_arg(T_BYTE);
-        // Copy the java argument value to kernelArgBuffer
-        jvalue val;
-        if (java_lang_boxing_object::get_value(arg, &val) != T_BYTE) {
-            tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE");
-            _success = false;
-            return;
-        }
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.b;
-        _bufferOffset += sizeof(val.b);
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(_dev_return_value);
+  } else {
+    // Get the next java argument and its value which should be a T_BYTE
+    oop arg = next_arg(T_BYTE);
+    // Copy the java argument value to kernelArgBuffer
+    jvalue val;
+    if (java_lang_boxing_object::get_value(arg, &val) != T_BYTE) {
+      tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE");
+      _success = false;
+      return;
     }
-    return;
+    if (is_kernel_arg_setup()) {
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.b;
+    }
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(val.b);
+  }
+  return;
 }
 
 void PTXKernelArguments::do_bool() {
-    if (is_after_invocation()) {
+  // If the parameter is a return value,
+  if (is_return_type()) {
+    if (is_kernel_arg_setup()) {
+      // Allocate device memory for T_BYTE return value pointer on device. Size in bytes
+      int status = gpu::Ptx::_cuda_cu_memalloc(&_dev_return_value, T_BOOLEAN_SIZE);
+      if (status != GRAAL_CUDA_SUCCESS) {
+        tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+        _success = false;
         return;
+      }
+      // Push _dev_return_value to _kernelBuffer
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _dev_return_value;
     }
-    // If the parameter is a return value,
-    if (is_return_type()) {
-        // Allocate device memory for T_BYTE return value pointer on device. Size in bytes
-        int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_BOOLEAN_SIZE);
-        if (status != GRAAL_CUDA_SUCCESS) {
-            tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
-            _success = false;
-            return;
-        }
-        // Push _return_value_ptr to _kernelBuffer
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
-        _bufferOffset += sizeof(_return_value_ptr);
-    } else {
-        // Get the next java argument and its value which should be a T_BYTE
-        oop arg = next_arg(T_BYTE);
-        // Copy the java argument value to kernelArgBuffer
-        jvalue val;
-        if (java_lang_boxing_object::get_value(arg, &val) != T_BOOLEAN) {
-            tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE");
-            _success = false;
-            return;
-        }
-        *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.z;
-        _bufferOffset += sizeof(val.z);
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(_dev_return_value);
+  } else {
+    // Get the next java argument and its value which should be a T_BYTE
+    oop arg = next_arg(T_BYTE);
+    // Copy the java argument value to kernelArgBuffer
+    jvalue val;
+    if (java_lang_boxing_object::get_value(arg, &val) != T_BOOLEAN) {
+      tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE");
+      _success = false;
+      return;
     }
-    return;
+    if (is_kernel_arg_setup()) {
+      *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.z;
+    }
+    // Advance _bufferOffset
+    _bufferOffset += sizeof(val.z);
+  }
+  return;
 }
 
 void PTXKernelArguments::do_array(int begin, int end) {
-    gpu::Ptx::CUdeviceptr _array_ptr;
-    int status;
-
-    // Get the next java argument and its value which should be a T_ARRAY
-    oop arg = next_arg(T_OBJECT);
-    int array_size = arg->size() * HeapWordSize;
+  // Get the next java argument and its value which should be a T_ARRAY
+  oop arg = next_arg(T_OBJECT);
+  assert(arg->is_array(), "argument value not an array");
+  // Size of array argument
+  int argSize = arg->size() * HeapWordSize;
+  // Device pointer to array argument.
+  gpu::Ptx::CUdeviceptr arrayArgOnDev;
+  int status;
 
-    if (is_after_invocation()) {
-        _array_ptr = *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]);
-        status = gpu::Ptx::_cuda_cu_memcpy_dtoh(arg, _array_ptr, array_size);
-        if (status != GRAAL_CUDA_SUCCESS) {
-            tty->print_cr("[CUDA] *** Error (%d) Failed to copy array argument to host", status);
-            _success = false;
-            return;
-        } else {
-            // tty->print_cr("device: %x host: %x size: %d", _array_ptr, arg, array_size);
-        }
-        return;
+  if (is_kernel_arg_setup()) {
+    // Allocate device memory for array argument on device. Size in bytes
+    status = gpu::Ptx::_cuda_cu_memalloc(&arrayArgOnDev, argSize);
+    if (status != GRAAL_CUDA_SUCCESS) {
+      tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for array argument on device",
+                    status);
+      _success = false;
+      return;
     }
-    // Allocate device memory for T_ARRAY return value pointer on device. Size in bytes
-    status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, array_size);
-    if (status != GRAAL_CUDA_SUCCESS) {
-        tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
-        _success = false;
-        return;
-    }
-    status = gpu::Ptx::_cuda_cu_memcpy_htod(_return_value_ptr, arg, array_size);
+    // Copy array argument to device
+    status = gpu::Ptx::_cuda_cu_memcpy_htod(arrayArgOnDev, arg, argSize);
     if (status != GRAAL_CUDA_SUCCESS) {
-        tty->print_cr("[CUDA] *** Error (%d) Failed to copy array to device argument", status);
-        _success = false;
-        return;
-    } else {
-        // tty->print_cr("host: %x device: %x size: %d", arg, _return_value_ptr, array_size);
+      tty->print_cr("[CUDA] *** Error (%d) Failed to copy array argument content to device memory",
+                    status);
+      _success = false;
+      return;
     }
-    // Push _return_value_ptr to _kernelBuffer
-    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
-    _bufferOffset += sizeof(_return_value_ptr);
-    return;
+
+    // Push device array argument to _kernelBuffer
+    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = arrayArgOnDev;
+  } else {
+    arrayArgOnDev = *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]);
+    status = gpu::Ptx::_cuda_cu_memcpy_dtoh(arg, arrayArgOnDev, argSize);
+    if (status != GRAAL_CUDA_SUCCESS) {
+      tty->print_cr("[CUDA] *** Error (%d) Failed to copy array argument to host", status);
+      _success = false;
+      return;
+    }
+  }
+
+  // Advance _bufferOffset
+  _bufferOffset += sizeof(arrayArgOnDev);
+  return;
 }
 
 void PTXKernelArguments::do_void() {
-    return;
+  return;
 }
 
 // TODO implement other do_*
--- a/src/gpu/ptx/vm/ptxKernelArguments.hpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/gpu/ptx/vm/ptxKernelArguments.hpp	Fri Oct 25 01:39:54 2013 +0200
@@ -42,7 +42,13 @@
   char _kernelArgBuffer[1024];
   // Current offset into _kernelArgBuffer
   size_t _bufferOffset;
-  gpu::Ptx::CUdeviceptr _return_value_ptr;
+  // Device pointer holding return value
+  gpu::Ptx::CUdeviceptr _dev_return_value;
+
+  // Indicates if signature iteration is being done during kernel
+  // setup i.e., java arguments are being copied to device pointers.
+  bool _kernelArgSetup;
+
 private:
   // Array of java argument oops
   arrayOop _args;
@@ -51,7 +57,6 @@
   // Flag to indicate successful creation of kernel argument buffer
   bool _success;
 
-    bool _afterInvoocation;
   // Get next java argument
   oop next_arg(BasicType expectedType);
 
@@ -62,7 +67,9 @@
     _args = args;
     _success = true;
     _bufferOffset = 0;
-    _return_value_ptr = 0;
+    _dev_return_value = 0;
+    _kernelArgSetup = true;
+    //_dev_call_by_reference_args_index = 0;
     if (!is_static) {
       // TODO : Create a device argument for receiver object and add it to _kernelBuffer
       tty->print_cr("{CUDA] ****** TODO: Support for execution of non-static java methods not implemented yet.");
@@ -80,23 +87,23 @@
     return _bufferOffset;
   }
 
-    void reiterate() {
-        _afterInvoocation = true;
-        _bufferOffset = 0;
-        _index = 0;
-        iterate();
-    }
+  void copyRefArgsFromDtoH() {
+    _kernelArgSetup = false;
+    _bufferOffset = 0;
+    _index = 0;
+    iterate();
+  }
 
-    inline bool is_after_invocation() {
-        return _afterInvoocation;
-    }
+  inline bool is_kernel_arg_setup() {
+    return _kernelArgSetup;
+  }
 
   // Get the return oop value
   oop get_return_oop();
 
   // get device return value ptr
-  gpu::Ptx::CUdeviceptr get_return_value_ptr() {
-      return _return_value_ptr;
+  gpu::Ptx::CUdeviceptr get_dev_return_value() {
+      return _dev_return_value;
   }
 
 
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Fri Oct 25 01:39:54 2013 +0200
@@ -32,6 +32,7 @@
 import com.sun.hotspot.igv.graph.InputSlot;
 import java.awt.Color;
 import java.util.List;
+import java.util.regex.Pattern;
 
 /**
  * Filter that colors usage and successor edges differently.
@@ -55,6 +56,7 @@
     @Override
     public void apply(Diagram d) {
         List<Figure> figures = d.getFigures();
+        Pattern ndf = Pattern.compile(".*#NDF(\\[[0-9]*\\])?");
         for (Figure f : figures) {
             Properties p = f.getProperties();
             int predCount;
@@ -78,7 +80,7 @@
 
                 is.setColor(color);
                 for (Connection c : is.getConnections()) {
-                    if (c.getLabel() == null || !c.getLabel().endsWith("#NDF")) {
+                    if (c.getLabel() == null || !ndf.matcher(c.getLabel()).matches()) {
                         c.setColor(color);
                         if (c.getStyle() != ConnectionStyle.DASHED) {
                             c.setStyle(style);
--- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Fri Oct 25 01:39:54 2013 +0200
@@ -40,5 +40,5 @@
 
 # Disable assertions for RequestProcessor to prevent annoying messages in case
 # of multiple SceneAnimator update tasks in the default RequestProcessor.
-run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx4g
+run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g
 debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor
--- a/src/share/vm/gc_interface/collectedHeap.hpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/share/vm/gc_interface/collectedHeap.hpp	Fri Oct 25 01:39:54 2013 +0200
@@ -491,9 +491,7 @@
   // Total number of GC collections (started)
   unsigned int total_collections() const { return _total_collections; }
   unsigned int total_full_collections() const { return _total_full_collections;}
-#ifdef GRAAL
-  unsigned int* total_collections_address() { return &_total_collections;}
-#endif
+
   // Increment total number of GC collections (started)
   // Should be protected but used by PSMarkSweep - cleanup for 1.4.2
   void increment_total_collections(bool full = false) {
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Fri Oct 25 01:39:54 2013 +0200
@@ -38,6 +38,8 @@
 #include "graal/graalCodeInstaller.hpp"
 #include "graal/graalVMToCompiler.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/vmStructs.hpp"
 
 
 Method* getMethodFromHotSpotMethod(oop hotspot_method) {
@@ -307,11 +309,6 @@
   return code == NULL ? 0 : code->insts_size();
 C2V_END
 
-C2V_VMENTRY(jint, constantPoolLength, (JNIEnv *env, jobject, jobject type))
-  ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants();
-  return cp->length();
-C2V_END
-
 C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve))
   ResourceMark rm;
 
@@ -547,12 +544,14 @@
   return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD));
 C2V_END
 
+// TODO move to Java
 C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass))
   Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass));
   assert(klass != NULL, "method must not be called for primitive types");
   return InstanceKlass::cast(klass)->is_initialized();
 C2V_END
 
+// TODO move to Java
 C2V_VMENTRY(jboolean, isTypeLinked,(JNIEnv *, jobject, jobject hotspot_klass))
   Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass));
   assert(klass != NULL, "method must not be called for primitive types");
@@ -642,152 +641,120 @@
   return id;
 }
 
+C2V_VMENTRY(void, doNotInlineOrCompile,(JNIEnv *, jobject,  jlong metaspace_method))
+  methodHandle method = asMethod(metaspace_method);
+  method->set_not_c1_compilable();
+  method->set_not_c2_compilable();
+  method->set_dont_inline(true);
+C2V_END
+
+extern "C" {
+extern VMStructEntry* gHotSpotVMStructs;
+extern uint64_t gHotSpotVMStructEntryTypeNameOffset;
+extern uint64_t gHotSpotVMStructEntryFieldNameOffset;
+extern uint64_t gHotSpotVMStructEntryTypeStringOffset;
+extern uint64_t gHotSpotVMStructEntryIsStaticOffset;
+extern uint64_t gHotSpotVMStructEntryOffsetOffset;
+extern uint64_t gHotSpotVMStructEntryAddressOffset;
+extern uint64_t gHotSpotVMStructEntryArrayStride;
+
+extern VMTypeEntry* gHotSpotVMTypes;
+extern uint64_t gHotSpotVMTypeEntryTypeNameOffset;
+extern uint64_t gHotSpotVMTypeEntrySuperclassNameOffset;
+extern uint64_t gHotSpotVMTypeEntryIsOopTypeOffset;
+extern uint64_t gHotSpotVMTypeEntryIsIntegerTypeOffset;
+extern uint64_t gHotSpotVMTypeEntryIsUnsignedOffset;
+extern uint64_t gHotSpotVMTypeEntrySizeOffset;
+extern uint64_t gHotSpotVMTypeEntryArrayStride;
+
+extern VMIntConstantEntry* gHotSpotVMIntConstants;
+extern uint64_t gHotSpotVMIntConstantEntryNameOffset;
+extern uint64_t gHotSpotVMIntConstantEntryValueOffset;
+extern uint64_t gHotSpotVMIntConstantEntryArrayStride;
+
+extern VMLongConstantEntry* gHotSpotVMLongConstants;
+extern uint64_t gHotSpotVMLongConstantEntryNameOffset;
+extern uint64_t gHotSpotVMLongConstantEntryValueOffset;
+extern uint64_t gHotSpotVMLongConstantEntryArrayStride;
+}
+
 C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config))
 
 #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0)
 #define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0)
 #define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0)
 #define set_address(name, value) do { set_long(name, (jlong) value); } while (0)
-#define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0)
 
   guarantee(HeapWordSize == sizeof(char*), "Graal assumption that HeadWordSize == machine word size is wrong");
 
-  set_boolean("cAssertions", DEBUG_ONLY(true) NOT_DEBUG(false));
-  set_int("codeEntryAlignment", CodeEntryAlignment);
-  set_int("hubOffset", oopDesc::klass_offset_in_bytes());
-  set_int("markOffset", oopDesc::mark_offset_in_bytes());
-  set_int("prototypeMarkWordOffset", in_bytes(Klass::prototype_header_offset()));
-  set_int("superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset()));
-  set_int("secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset()));
-  set_int("secondarySupersOffset", in_bytes(Klass::secondary_supers_offset()));
-  set_int("subklassOffset", in_bytes(Klass::subklass_offset()));
-  set_int("nextSiblingOffset", in_bytes(Klass::next_sibling_offset()));
+  set_address("gHotSpotVMStructs", gHotSpotVMStructs);
+  set_long("gHotSpotVMStructEntryTypeNameOffset",   gHotSpotVMStructEntryTypeNameOffset);
+  set_long("gHotSpotVMStructEntryFieldNameOffset",  gHotSpotVMStructEntryFieldNameOffset);
+  set_long("gHotSpotVMStructEntryTypeStringOffset", gHotSpotVMStructEntryTypeStringOffset);
+  set_long("gHotSpotVMStructEntryIsStaticOffset",   gHotSpotVMStructEntryIsStaticOffset);
+  set_long("gHotSpotVMStructEntryOffsetOffset",     gHotSpotVMStructEntryOffsetOffset);
+  set_long("gHotSpotVMStructEntryAddressOffset",    gHotSpotVMStructEntryAddressOffset);
+  set_long("gHotSpotVMStructEntryArrayStride",      gHotSpotVMStructEntryArrayStride);
+
+  set_address("gHotSpotVMTypes", gHotSpotVMTypes);
+  set_long("gHotSpotVMTypeEntryTypeNameOffset",       gHotSpotVMTypeEntryTypeNameOffset);
+  set_long("gHotSpotVMTypeEntrySuperclassNameOffset", gHotSpotVMTypeEntrySuperclassNameOffset);
+  set_long("gHotSpotVMTypeEntryIsOopTypeOffset",      gHotSpotVMTypeEntryIsOopTypeOffset);
+  set_long("gHotSpotVMTypeEntryIsIntegerTypeOffset",  gHotSpotVMTypeEntryIsIntegerTypeOffset);
+  set_long("gHotSpotVMTypeEntryIsUnsignedOffset",     gHotSpotVMTypeEntryIsUnsignedOffset);
+  set_long("gHotSpotVMTypeEntrySizeOffset",           gHotSpotVMTypeEntrySizeOffset);
+  set_long("gHotSpotVMTypeEntryArrayStride",          gHotSpotVMTypeEntryArrayStride);
+
+  set_address("gHotSpotVMIntConstants", gHotSpotVMIntConstants);
+  set_long("gHotSpotVMIntConstantEntryNameOffset",  gHotSpotVMIntConstantEntryNameOffset);
+  set_long("gHotSpotVMIntConstantEntryValueOffset", gHotSpotVMIntConstantEntryValueOffset);
+  set_long("gHotSpotVMIntConstantEntryArrayStride", gHotSpotVMIntConstantEntryArrayStride);
+
+  set_address("gHotSpotVMLongConstants", gHotSpotVMLongConstants);
+  set_long("gHotSpotVMLongConstantEntryNameOffset",  gHotSpotVMLongConstantEntryNameOffset);
+  set_long("gHotSpotVMLongConstantEntryValueOffset", gHotSpotVMLongConstantEntryValueOffset);
+  set_long("gHotSpotVMLongConstantEntryArrayStride", gHotSpotVMLongConstantEntryArrayStride);
+
+  //------------------------------------------------------------------------------------------------
+
   set_int("arrayLengthOffset", arrayOopDesc::length_offset_in_bytes());
-  set_int("klassStateOffset", in_bytes(InstanceKlass::init_state_offset()));
-  set_int("klassStateFullyInitialized", (int)InstanceKlass::fully_initialized);
-  set_int("threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset()));
-  set_int("threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset()));
-  set_int("threadObjectOffset", in_bytes(JavaThread::threadObj_offset()));
-  set_int("threadIsMethodHandleReturnOffset", in_bytes(JavaThread::is_method_handle_return_offset()));
-  set_int("osThreadOffset", in_bytes(JavaThread::osthread_offset()));
-  set_int("osThreadInterruptedOffset", in_bytes(OSThread::interrupted_offset()));
-  set_int("unlockedMask", (int) markOopDesc::unlocked_value);
-  set_int("biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place);
-  set_int("ageMaskInPlace", (int) markOopDesc::age_mask_in_place);
-  set_int("epochMaskInPlace", (int) markOopDesc::epoch_mask_in_place);
-  set_int("biasedLockPattern", (int) markOopDesc::biased_lock_pattern);
-  set_int("methodMaxLocalsOffset", in_bytes(ConstMethod::size_of_locals_offset()));
-  set_int("methodConstMethodOffset", in_bytes(Method::const_offset()));
-  set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset()));
-  set_int("constMethodConstantsOffset", in_bytes(ConstMethod::constants_offset()));
-  set_int("constantPoolHolderOffset", ConstantPool::pool_holder_offset_in_bytes());
+
   set_int("extraStackEntries", Method::extra_stack_entries());
-  set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset()));
-  set_int("methodQueuedForCompilationBit", (int) JVM_ACC_QUEUED);
-  set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes());
-  set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER);
-  set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset()));
-  set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
-  set_long("safepointPollingAddress", (jlong)(os::get_polling_page()));
-#ifdef TARGET_ARCH_x86
-  set_boolean("isPollingPageFar", Assembler::is_polling_page_far());
-  set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes);
-#endif
-  set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset()));
-  set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset()));
-  set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset()));
-  set_int("klassOffset", java_lang_Class::klass_offset_in_bytes());
-  set_int("arrayKlassOffset", java_lang_Class::array_klass_offset_in_bytes());
-  set_int("graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes());
-  set_int("klassLayoutHelperOffset", in_bytes(Klass::layout_helper_offset()));
-  set_int("klassSuperKlassOffset", in_bytes(Klass::super_offset()));
-  set_int("methodDataOffset", in_bytes(Method::method_data_offset()));
-  set_int("nmethodEntryOffset", nmethod::verified_entry_point_offset());
-  set_int("methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset()));
-  set_int("basicLockSize", sizeof(BasicLock));
-  set_int("basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes());
-  set_int("uninitializedIdentityHashCodeValue", markOopDesc::no_hash);
-  set_int("identityHashCodeShift", markOopDesc::hash_shift);
-
-  set_int("arrayKlassLayoutHelperIdentifier", 0x80000000);
-  assert((Klass::_lh_array_tag_obj_value & Klass::_lh_array_tag_type_value & 0x80000000) != 0, "obj_array and type_array must have first bit set");
-  set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset()));
-
-
-  set_int("pendingExceptionOffset", in_bytes(ThreadShadow::pending_exception_offset()));
-  set_int("pendingDeoptimizationOffset", in_bytes(ThreadShadow::pending_deoptimization_offset()));
-
-  set_int("metaspaceArrayLengthOffset", Array<Klass*>::length_offset_in_bytes());
-  set_int("metaspaceArrayBaseOffset", Array<Klass*>::base_offset_in_bytes());
-  set_int("methodDataOopDataOffset", in_bytes(MethodData::data_offset()));
-  set_int("methodDataOopTrapHistoryOffset", in_bytes(MethodData::trap_history_offset()));
-  set_int("dataLayoutHeaderSize", DataLayout::header_size_in_bytes());
-  set_int("dataLayoutTagOffset", in_bytes(DataLayout::tag_offset()));
-  set_int("dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset()));
-  set_int("dataLayoutBCIOffset", in_bytes(DataLayout::bci_offset()));
-  set_int("dataLayoutCellsOffset", in_bytes(DataLayout::cell_offset(0)));
-  set_int("dataLayoutCellSize", DataLayout::cell_size);
 
   set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve());
-  set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2));
   set_long("heapTopAddress", (jlong)(address) Universe::heap()->top_addr());
   set_long("heapEndAddress", (jlong)(address) Universe::heap()->end_addr());
-  set_int("threadTlabStartOffset", in_bytes(JavaThread::tlab_start_offset()));
-  set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset()));
-  set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset()));
-  set_int("threadLastJavaSpOffset", in_bytes(JavaThread::last_Java_sp_offset()));
-  set_int("threadLastJavaPcOffset", in_bytes(JavaThread::last_Java_pc_offset()));
-#ifdef TARGET_ARCH_x86
-  set_int("threadLastJavaFpOffset", in_bytes(JavaThread::last_Java_fp_offset()));
-#endif
-#ifdef TARGET_ARCH_sparc
-  set_int("threadJavaFrameAnchorFlagsOffset", in_bytes(JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset()));
-#endif
-  set_int("threadObjectResultOffset", in_bytes(JavaThread::vm_result_offset()));
-  set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset()));
-  set_int("tlabFastRefillWasteOffset", in_bytes(JavaThread::tlab_fast_refill_waste_offset()));
-  set_int("tlabNumberOfRefillsOffset", in_bytes(JavaThread::tlab_number_of_refills_offset()));
-  set_int("tlabRefillWasteLimitOffset", in_bytes(JavaThread::tlab_refill_waste_limit_offset()));
-  set_int("tlabRefillWasteIncrement", (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment());
-  set_int("klassInstanceSizeOffset", in_bytes(Klass::layout_helper_offset()));
+
   set_boolean("inlineContiguousAllocationSupported", !CMSIncrementalMode && Universe::heap()->supports_inline_contig_alloc());
 
-  set_address("nonOopBits", Universe::non_oop_word());
-  set_long("verifyOopCounterAddress", (jlong)(address) StubRoutines::verify_oop_count_addr());
   set_long("verifyOopMask", Universe::verify_oop_mask());
   set_long("verifyOopBits", Universe::verify_oop_bits());
 
-  set_long("arrayPrototypeMarkWord", (intptr_t)markOopDesc::prototype());
-  set_int("layoutHelperLog2ElementSizeShift", Klass::_lh_log2_element_size_shift);
-  set_int("layoutHelperLog2ElementSizeMask", Klass::_lh_log2_element_size_mask);
-  set_int("layoutHelperElementTypeShift", Klass::_lh_element_type_shift);
-  set_int("layoutHelperElementTypeMask", Klass::_lh_element_type_mask);
-  // this filters out the bit that differentiates a type array from an object array
-  set_int("layoutHelperElementTypePrimitiveInPlace", (Klass::_lh_array_tag_type_value & ~Klass::_lh_array_tag_obj_value) << Klass::_lh_array_tag_shift);
-  set_int("layoutHelperHeaderSizeShift", Klass::_lh_header_size_shift);
-  set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask);
-  set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset()));
+  set_int("instanceKlassVtableStartOffset", InstanceKlass::vtable_start_offset() * HeapWordSize);
+
+  //------------------------------------------------------------------------------------------------
+
+  set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
+  set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap());
 
-  set_address("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub());
-  set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
-  set_address("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock());
-  set_address("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock());
-  set_address("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt());
-  set_address("cipherBlockChainingDecryptAESCryptStub", StubRoutines::cipherBlockChaining_decryptAESCrypt());
-  set_address("updateBytesCRC32Stub", StubRoutines::updateBytesCRC32());
+  set_address("registerFinalizerAddress", SharedRuntime::register_finalizer);
+  set_address("exceptionHandlerForReturnAddressAddress", SharedRuntime::exception_handler_for_return_address);
+  set_address("osrMigrationEndAddress", SharedRuntime::OSR_migration_end);
+
+  set_address("javaTimeMillisAddress", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
+  set_address("javaTimeNanosAddress", CAST_FROM_FN_PTR(address, os::javaTimeNanos));
+  set_address("arithmeticSinAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
+  set_address("arithmeticCosAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
+  set_address("arithmeticTanAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
 
   set_address("newInstanceAddress", GraalRuntime::new_instance);
   set_address("newArrayAddress", GraalRuntime::new_array);
   set_address("newMultiArrayAddress", GraalRuntime::new_multi_array);
   set_address("dynamicNewArrayAddress", GraalRuntime::dynamic_new_array);
-  set_address("registerFinalizerAddress", SharedRuntime::register_finalizer);
   set_address("threadIsInterruptedAddress", GraalRuntime::thread_is_interrupted);
-  set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap());
   set_address("vmMessageAddress", GraalRuntime::vm_message);
   set_address("identityHashCodeAddress", GraalRuntime::identity_hash_code);
   set_address("exceptionHandlerForPcAddress", GraalRuntime::exception_handler_for_pc);
-  set_address("exceptionHandlerForReturnAddressAddress", SharedRuntime::exception_handler_for_return_address);
-  set_address("osrMigrationEndAddress", SharedRuntime::OSR_migration_end);
   set_address("monitorenterAddress", GraalRuntime::monitorenter);
   set_address("monitorexitAddress", GraalRuntime::monitorexit);
   set_address("createNullPointerExceptionAddress", GraalRuntime::create_null_exception);
@@ -797,82 +764,11 @@
   set_address("logPrintfAddress", GraalRuntime::log_printf);
   set_address("vmErrorAddress", GraalRuntime::vm_error);
   set_address("loadAndClearExceptionAddress", GraalRuntime::load_and_clear_exception);
-  set_address("javaTimeMillisAddress", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
-  set_address("javaTimeNanosAddress", CAST_FROM_FN_PTR(address, os::javaTimeNanos));
-  set_address("arithmeticSinAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
-  set_address("arithmeticCosAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
-  set_address("arithmeticTanAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
-  set_address("crcTableAddress", StubRoutines::crc_table_addr());
-
-  set_int("deoptReasonNone", Deoptimization::Reason_none);
-  set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check);
-  set_int("deoptReasonRangeCheck", Deoptimization::Reason_range_check);
-  set_int("deoptReasonClassCheck", Deoptimization::Reason_class_check);
-  set_int("deoptReasonArrayCheck", Deoptimization::Reason_array_check);
-  set_int("deoptReasonUnreached0", Deoptimization::Reason_unreached0);
-  set_int("deoptReasonTypeCheckInlining", Deoptimization::Reason_type_checked_inlining);
-  set_int("deoptReasonOptimizedTypeCheck", Deoptimization::Reason_optimized_type_check);
-  set_int("deoptReasonNotCompiledExceptionHandler", Deoptimization::Reason_not_compiled_exception_handler);
-  set_int("deoptReasonUnresolved", Deoptimization::Reason_unresolved);
-  set_int("deoptReasonJsrMismatch", Deoptimization::Reason_jsr_mismatch);
-  set_int("deoptReasonDiv0Check", Deoptimization::Reason_div0_check);
-  set_int("deoptReasonConstraint", Deoptimization::Reason_constraint);
-  set_int("deoptReasonLoopLimitCheck", Deoptimization::Reason_loop_limit_check);
-
-  set_int("deoptActionNone", Deoptimization::Action_none);
-  set_int("deoptActionMaybeRecompile", Deoptimization::Action_maybe_recompile);
-  set_int("deoptActionReinterpret", Deoptimization::Action_reinterpret);
-  set_int("deoptActionMakeNotEntrant", Deoptimization::Action_make_not_entrant);
-  set_int("deoptActionMakeNotCompilable", Deoptimization::Action_make_not_compilable);
-
-  set_int("vmIntrinsicInvokeBasic", vmIntrinsics::_invokeBasic);
-  set_int("vmIntrinsicLinkToVirtual", vmIntrinsics::_linkToVirtual);
-  set_int("vmIntrinsicLinkToStatic", vmIntrinsics::_linkToStatic);
-  set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial);
-  set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface);
-
-  set_address("narrowOopBase", Universe::narrow_oop_base());
-  set_int("narrowOopShift", Universe::narrow_oop_shift());
-  set_address("narrowKlassBase", Universe::narrow_klass_base());
-  set_int("narrowKlassShift", Universe::narrow_klass_shift());
-  set_int("logKlassAlignment", LogKlassAlignmentInBytes);
-
-
-  set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()));
-  set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()));
-  set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes);
-  set_int("g1SATBQueueMarkingOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()));
-  set_int("g1SATBQueueIndexOffset", in_bytes(JavaThread::satb_mark_queue_offset() +  PtrQueue::byte_offset_of_index()));
-  set_int("g1SATBQueueBufferOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()));
   set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre);
   set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post);
-  set_address("gcTotalCollectionsAddress", (jlong)(address)(Universe::heap()->total_collections_address()));
   set_address("validateObject", GraalRuntime::validate_object);
 
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  switch (bs->kind()) {
-    case BarrierSet::CardTableModRef:
-    case BarrierSet::CardTableExtension:
-    case BarrierSet::G1SATBCT:
-    case BarrierSet::G1SATBCTLogging:{
-      jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base;
-      assert(base != 0, "unexpected byte_map_base");
-      set_long("cardtableStartAddress", base);
-      set_int("cardtableShift", CardTableModRefBS::card_shift);
-      break;
-    }
-    case BarrierSet::ModRef:
-    case BarrierSet::Other:
-      set_long("cardtableStartAddress", 0);
-      set_int("cardtableShift", 0);
-      // No post barriers
-      break;
-    default:
-      ShouldNotReachHere();
-      break;
-    }
-
-  set_int("arrayClassElementOffset", in_bytes(ObjArrayKlass::element_klass_offset()));
+  //------------------------------------------------------------------------------------------------
 
   set_int("graalCountersThreadOffset", in_bytes(JavaThread::graal_counters_offset()));
   set_int("graalCountersSize", (jint) GRAAL_COUNTERS_SIZE);
@@ -880,7 +776,6 @@
 #undef set_boolean
 #undef set_int
 #undef set_long
-#undef set_object
 
 C2V_END
 
@@ -996,26 +891,6 @@
   }
 C2V_END
 
-C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method))
-
-  Method* method = asMethod(metaspace_method);
-  assert(!InstanceKlass::cast(method->method_holder())->is_interface(), "vtableEntryOffset cannot be called for interface methods");
-  assert(InstanceKlass::cast(method->method_holder())->is_linked(), "vtableEntryOffset cannot be called is holder is not linked");
-  assert(method->vtable_index() >= 0, "vtable entry offset should not be used");
-
-  // get entry offset in words
-  int vtable_entry_offset = InstanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size();
-  // convert to bytes
-  vtable_entry_offset = vtable_entry_offset * wordSize + vtableEntry::method_offset_in_bytes();
-
-  return vtable_entry_offset;
-C2V_END
-
-C2V_VMENTRY(jboolean, hasVtableEntry, (JNIEnv *, jobject, jlong metaspace_method))
-  Method* method = asMethod(metaspace_method);
-  return method->vtable_index() >= 0;
-C2V_END
-
 C2V_VMENTRY(jobject, getDeoptedLeafGraphIds, (JNIEnv *, jobject))
 
   // the contract for this method is as follows:
@@ -1138,7 +1013,7 @@
 
 C2V_VMENTRY(jobject, readUnsafeUncompressedPointer, (JNIEnv *env, jobject, jobject o, jlong offset))
   oop resolved_o = JNIHandles::resolve(o);
-  address addr = offset + (address)resolved_o;
+  address addr = ((address)resolved_o) + offset;
   return JNIHandles::make_local(*((oop*)addr));
 C2V_END
 
@@ -1196,12 +1071,10 @@
   {CC"getUniqueImplementor",          CC"("HS_RESOLVED_TYPE")"RESOLVED_TYPE,                            FN_PTR(getUniqueImplementor)},
   {CC"getStackTraceElement",          CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT,                     FN_PTR(getStackTraceElement)},
   {CC"initializeMethod",              CC"("METASPACE_METHOD HS_RESOLVED_METHOD")V",                     FN_PTR(initializeMethod)},
+  {CC"doNotInlineOrCompile",          CC"("METASPACE_METHOD")V",                                        FN_PTR(doNotInlineOrCompile)},
   {CC"initializeMethodData",          CC"("METASPACE_METHOD_DATA METHOD_DATA")V",                       FN_PTR(initializeMethodData)},
   {CC"isMethodCompilable",            CC"("METASPACE_METHOD")Z",                                        FN_PTR(isMethodCompilable)},
   {CC"getCompiledCodeSize",           CC"("METASPACE_METHOD")I",                                        FN_PTR(getCompiledCodeSize)},
-  {CC"getVtableEntryOffset",          CC"("METASPACE_METHOD")I",                                        FN_PTR(getVtableEntryOffset)},
-  {CC"hasVtableEntry",                CC"("METASPACE_METHOD")Z",                                        FN_PTR(hasVtableEntry)},
-  {CC"constantPoolLength",            CC"("HS_RESOLVED_TYPE")I",                                        FN_PTR(constantPoolLength)},
   {CC"lookupType",                    CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE,                             FN_PTR(lookupType)},
   {CC"lookupConstantInPool",          CC"("HS_RESOLVED_TYPE"I)"OBJECT,                                  FN_PTR(lookupConstantInPool)},
   {CC"lookupAppendixInPool",          CC"("HS_RESOLVED_TYPE"IB)"OBJECT,                                 FN_PTR(lookupAppendixInPool)},
--- a/src/share/vm/graal/graalJavaAccess.hpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Fri Oct 25 01:39:54 2013 +0200
@@ -85,6 +85,7 @@
   start_class(HotSpotNmethod)                                                                                                                                  \
     boolean_field(HotSpotNmethod, isDefault)                                                                                                                   \
     boolean_field(HotSpotNmethod, isExternal)                                                                                                                  \
+    oop_field(HotSpotNmethod, name, "Ljava/lang/String;")                                                                                                      \
   end_class                                                                                                                                                    \
   start_class(HotSpotCompiledCode)                                                                                                                             \
     oop_field(HotSpotCompiledCode, comp, "Lcom/oracle/graal/api/code/CompilationResult;")                                                                      \
--- a/src/share/vm/runtime/deoptimization.cpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Fri Oct 25 01:39:54 2013 +0200
@@ -89,6 +89,7 @@
 
 #ifdef GRAAL
 #include "graal/graalCompiler.hpp"
+#include "graal/graalJavaAccess.hpp"
 #endif
 
 
@@ -1420,6 +1421,19 @@
       if (TraceDeoptimization) {  // make noise on the tty
         tty->print("Uncommon trap occurred in");
         nm->method()->print_short_name(tty);
+#ifdef GRAAL
+        oop installedCode = nm->graal_installed_code();
+        if (installedCode != NULL) {
+          oop installedCodeName = HotSpotNmethod::name(installedCode);
+          if (installedCodeName != NULL) {
+            tty->print(" (Graal: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName));
+          } else {
+            tty->print(" (Graal: installed code has no name) ");
+          }
+        } else if (nm->is_compiled_by_graal()) {
+          tty->print(" (Graal: no installed code) ");
+        }
+#endif //GRAAL
         tty->print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d",
                    fr.pc(),
                    os::current_thread_id(),
--- a/src/share/vm/runtime/vmStructs.cpp	Tue Oct 22 15:06:02 2013 +0200
+++ b/src/share/vm/runtime/vmStructs.cpp	Fri Oct 25 01:39:54 2013 +0200
@@ -563,6 +563,8 @@
   nonstatic_field(Space,                       _bottom,                                       HeapWord*)                             \
   nonstatic_field(Space,                       _end,                                          HeapWord*)                             \
                                                                                                                                      \
+     static_field(HeapRegion,                  LogOfHRGrainBytes,                             int)                                   \
+                                                                                                                                     \
   nonstatic_field(ThreadLocalAllocBuffer,      _start,                                        HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _top,                                          HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _end,                                          HeapWord*)                             \
@@ -890,6 +892,7 @@
      static_field(Threads,                     _return_code,                                  int)                                   \
                                                                                                                                      \
   nonstatic_field(ThreadShadow,                _pending_exception,                            oop)                                   \
+  nonstatic_field(ThreadShadow,                _pending_deoptimization,                       int)                                   \
   nonstatic_field(ThreadShadow,                _exception_file,                               const char*)                           \
   nonstatic_field(ThreadShadow,                _exception_line,                               int)                                   \
    volatile_nonstatic_field(Thread,            _suspend_flags,                                uint32_t)                              \
@@ -1243,6 +1246,7 @@
   static_field(java_lang_Class,                _array_klass_offset,                           int)                                   \
   static_field(java_lang_Class,                _oop_size_offset,                              int)                                   \
   static_field(java_lang_Class,                _static_oop_field_count_offset,                int)                                   \
+  GRAAL_ONLY(static_field(java_lang_Class,     _graal_mirror_offset,                          int))                                  \
                                                                                                                                      \
   /************************/                                                                                                         \
   /* Miscellaneous fields */                                                                                                         \
@@ -1482,6 +1486,8 @@
            declare_type(EdenSpace,                    ContiguousSpace)    \
            declare_type(OffsetTableContigSpace,       ContiguousSpace)    \
            declare_type(TenuredSpace,                 OffsetTableContigSpace) \
+           declare_type(G1OffsetTableContigSpace,     ContiguousSpace)    \
+           declare_type(HeapRegion,                   G1OffsetTableContigSpace) \
   declare_toplevel_type(BarrierSet)                                       \
            declare_type(ModRefBarrierSet,             BarrierSet)         \
            declare_type(CardTableModRefBS,            ModRefBarrierSet)   \