changeset 18669:7cc21427d54b

Merge
author Stefan Anzinger <stefan.a.anzinger@oracle.com>
date Fri, 12 Dec 2014 20:29:35 +0100
parents 6ace9e5bc384 (current diff) b026b6d86ab6 (diff)
children 8aeee4179e22
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/Context.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/Handler.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/Invocation.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/LinkedIdentityHashMap.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/ProxyUtil.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java
diffstat 93 files changed, 1383 insertions(+), 1613 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Fri Dec 12 20:29:35 2014 +0100
@@ -1273,18 +1273,6 @@
         }
     }
 
-// public static class Fmt4a {
-//
-// public Fmt4a(SPARCAssembler masm, int op, int op3, int cc, int rs1, int regOrImmediate, int rd) {
-// assert op == 2;
-// assert rs1 >= 0 && rs1 < 0x20;
-// assert rd >= 0 && rd < 0x10;
-//
-// masm.emitInt(op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | ((cc << 11) & 0x000001800) |
-// regOrImmediate);
-// }
-// }
-
     // @formatter:off
     /**
      * Instruction format for Movcc.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/CollectionsFactory.java	Fri Dec 12 20:29:35 2014 +0100
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.common;
+
+import static com.oracle.graal.compiler.common.CollectionsFactory.Mode.*;
+
+import java.util.*;
+
+/**
+ * Factory for creating collection objects used during compilation.
+ */
+public class CollectionsFactory {
+
+    private static final ThreadLocal<Mode> tl = new ThreadLocal<>();
+
+    public static class ModeScope implements AutoCloseable {
+        private final Mode previousMode;
+
+        public ModeScope(Mode previousMode) {
+            this.previousMode = previousMode;
+        }
+
+        public void close() {
+            tl.set(previousMode);
+        }
+    }
+
+    /**
+     * Constants denoting what type of collections are {@link CollectionsFactory#getMode()
+     * currently} returned by the factory.
+     */
+    public enum Mode {
+        /**
+         * Denotes standard collections such as {@link HashSet} and {@link HashMap}.
+         */
+        STANDARD,
+
+        /**
+         * Denotes collections that have a deterministic iteration order over their keys/entries.
+         */
+        DETERMINISTIC_ITERATION_ORDER;
+    }
+
+    /**
+     * Gets the current mode determining the type of collection objects created by this factory.
+     */
+    public static Mode getMode() {
+        Mode mode = tl.get();
+        return mode == null ? Mode.STANDARD : mode;
+    }
+
+    /**
+     * Updates the mode for the current thread.
+     *
+     * @return an object which when {@linkplain ModeScope#close() closed} will revert the mode of
+     *         the current thread to the stae before calling this method
+     */
+    public static ModeScope changeMode(Mode mode) {
+        Mode previousMode = tl.get();
+        tl.set(mode);
+        return new ModeScope(previousMode);
+    }
+
+    public static <K, V> HashMap<K, V> newMap() {
+        return getMode() == STANDARD ? new HashMap<>() : new LinkedHashMap<>();
+    }
+
+    public static <K, V> HashMap<K, V> newMap(Map<K, V> m) {
+        return getMode() == STANDARD ? new HashMap<>(m) : new LinkedHashMap<>(m);
+    }
+
+    public static <K, V> HashMap<K, V> newMap(int initialCapacity) {
+        return getMode() == STANDARD ? new HashMap<>(initialCapacity) : new LinkedHashMap<>(initialCapacity);
+    }
+
+    public static <K, V> Map<K, V> newIdentityMap() {
+        return getMode() == STANDARD ? new IdentityHashMap<>() : new LinkedIdentityHashMap<>();
+    }
+
+    public static <K, V> Map<K, V> newIdentityMap(int expectedMaxSize) {
+        return getMode() == STANDARD ? new IdentityHashMap<>(expectedMaxSize) : new LinkedIdentityHashMap<>();
+    }
+
+    public static <K, V> Map<K, V> newIdentityMap(Map<K, V> m) {
+        return getMode() == STANDARD ? new IdentityHashMap<>(m) : new LinkedIdentityHashMap<>(m);
+    }
+}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Fri Dec 12 20:29:35 2014 +0100
@@ -30,58 +30,67 @@
 // @formatter:off
 public final class GraalOptions {
 
-    @Option(help = "Use baseline compiler configuration")
+    @Option(help = "Use experimental baseline compiler configuration.")
     public static final OptionValue<Boolean> UseBaselineCompiler = new OptionValue<>(false);
-    @Option(help = "Enable use of compiler intrinsics")
+
+    @Option(help = "Use compiler intrinsifications.")
     public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true);
-    @Option(help = "Enable inlining of monomorphic calls")
+
+    @Option(help = "Inline calls with monomorphic type profile.")
     public static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true);
-    @Option(help = "Enable inlining of polymorphic calls")
+
+    @Option(help = "Inline calls with polymorphic type profile.")
     public static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true);
-    @Option(help = "Enable inlining of megamorphic calls")
+
+    @Option(help = "Inline calls with megamorphic type profile (i.e., not all types could be recorded).")
     public static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true);
-    @Option(help = "")
+
+    @Option(help = "Maximum desired size of the compiler graph in nodes.")
+    public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(20000);
+
+    @Option(help = "Minimum probability for methods to be inlined for megamorphic type profiles.")
     public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D);
-    @Option(help = "")
-    public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(20000);
-    @Option(help = "")
+
+    @Option(help = "Maximum level of recursive inlining.")
     public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(5);
 
-    // inlining settings
-    @Option(help = "")
-    public static final OptionValue<Float> BoostInliningForEscapeAnalysis = new OptionValue<>(2f);
-    @Option(help = "")
-    public static final OptionValue<Float> RelevanceCapForInlining = new OptionValue<>(1f);
-    @Option(help = "")
-    public static final OptionValue<Float> CapInheritedRelevance = new OptionValue<>(1f);
     @Option(help = "")
     public static final OptionValue<Boolean> IterativeInlining = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "Graphs with less than this number of nodes are trivial and therefore always inlined.")
     public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10);
-    @Option(help = "")
+
+    @Option(help = "Inlining is explored up to this number of nodes in the graph for each call site.")
     public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300);
-    @Option(help = "")
+
+    @Option(help = "If the previous low-level graph size of the method exceeds the threshold, it is not inlined.")
     public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300);
+
     @Option(help = "")
     public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0);
+
     @Option(help = "")
     public static final OptionValue<Boolean> InlineEverything = new OptionValue<>(false);
 
     // escape analysis settings
     @Option(help = "")
     public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2);
+
     @Option(help = "")
     public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null);
+
     @Option(help = "")
     public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32);
+
     @Option(help = "")
     public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false);
 
     @Option(help = "")
     public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5);
+
     @Option(help = "")
     public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1);
 
@@ -96,32 +105,44 @@
     //loop transform settings TODO (gd) tune
     @Option(help = "")
     public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Integer> FullUnrollMaxNodes = new OptionValue<>(300);
+
     @Option(help = "")
     public static final OptionValue<Integer> ExactFullUnrollMaxNodes = new OptionValue<>(1200);
+
     @Option(help = "")
     public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f);
+
     @Option(help = "")
     public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3);
+
     @Option(help = "")
     public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(50);
+
     @Option(help = "")
     public static final OptionValue<Integer> LoopUnswitchUncertaintyBoost = new OptionValue<>(5);
+
     @Option(help = "")
     public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true);
 
     // debugging settings
     @Option(help = "")
     public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false);
 
@@ -131,47 +152,66 @@
     // Debug settings:
     @Option(help = "")
     public static final OptionValue<Boolean> BootstrapReplacements = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Integer> GCDebugStartCycle = new OptionValue<>(-1);
+
     // Ideal graph visualizer output settings
     @Option(help = "Dump IdealGraphVisualizer output in binary format")
     public static final OptionValue<Boolean> PrintBinaryGraphs = new OptionValue<>(true);
+
     @Option(help = "Output probabilities for fixed nodes during binary graph dumping")
     public static final OptionValue<Boolean> PrintGraphProbabilities = new OptionValue<>(false);
+
     @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.")
     public static final OptionValue<Boolean> PrintCFG = new OptionValue<>(false);
+
     @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.")
     public static final OptionValue<Boolean> PrintBackendCFG = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> PrintIdealGraphFile = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<String> PrintIdealGraphAddress = new OptionValue<>("127.0.0.1");
+
     @Option(help = "")
     public static final OptionValue<Integer> PrintIdealGraphPort = new OptionValue<>(4444);
+
     @Option(help = "")
     public static final OptionValue<Integer> PrintBinaryGraphPort = new OptionValue<>(4445);
+
     @Option(help = "")
     public static final OptionValue<Boolean> PrintIdealGraphSchedule = new OptionValue<>(false);
 
     // Other printing settings
     @Option(help = "")
     public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false);
+
     @Option(help = "Print profiling information when parsing a method's bytecode")
     public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> PrintCodeBytes = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> TraceEscapeAnalysis = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
+
     @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required")
     public static final OptionValue<String> DecompileAfterPhase = new OptionValue<>(null);
 
@@ -180,55 +220,59 @@
     public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false);
 
     // Register allocator debugging
-    @Option(help = "")
+    @Option(help = "Comma separated list of register that the allocation is limited to.")
     public static final OptionValue<String> RegisterPressure = new OptionValue<>(null);
 
     // Code generator settings
     @Option(help = "")
     public static final OptionValue<Boolean> FlowSensitiveReduction = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> GenAssertionCode = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> AlignCallsForPatching = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true);
 
-    // Translating tableswitch instructions
-    @Option(help = "")
-    public static final OptionValue<Integer> MinimumJumpTableSize = new OptionValue<>(5);
-    @Option(help = "")
-    public static final OptionValue<Integer> RangeTestsSwitchDensity = new OptionValue<>(5);
-    @Option(help = "")
-    public static final OptionValue<Double> MinTableSwitchDensity = new OptionValue<>(0.5);
-
     // Ahead of time compilation
     @Option(help = "Try to avoid emitting code where patching is required")
     public static final OptionValue<Boolean> ImmutableCode = new OptionValue<>(false);
 
+    @Option(help = "Generate position independent code")
+    public static final OptionValue<Boolean> GeneratePIC = new OptionValue<>(false);
+
     @Option(help = "")
     public static final OptionValue<Boolean> CallArrayCopy = new OptionValue<>(true);
 
@@ -238,42 +282,58 @@
 
     @Option(help = "")
     public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptDeoptimizationGrouping = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true);
+
     @Option(help = "")
     public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
-    @Option(help = "Allow backend to emit arithmetic and compares directly against memory.")
-    public static final OptionValue<Boolean> OptFoldMemory = new OptionValue<>(false);
+
     @Option(help = "Allow backend to match complex expressions.")
     public static final OptionValue<Boolean> MatchExpressions = new OptionValue<>(true);
+
     @Option(help = "Constant fold final fields with default values.")
     public static final OptionValue<Boolean> TrustFinalDefaultFields = new OptionValue<>(true);
+
     @Option(help = "Mark well-known stable fields as such.")
     public static final OptionValue<Boolean> ImplicitStableValues = new OptionValue<>(true);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/LinkedIdentityHashMap.java	Fri Dec 12 20:29:35 2014 +0100
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.common;
+
+import java.util.*;
+import java.util.function.*;
+
+/**
+ * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of
+ * ensuring a deterministic execution order during a capturing compilation.
+ */
+final class LinkedIdentityHashMap<K, V> implements Map<K, V> {
+
+    private final LinkedHashMap<Id<K>, V> map;
+
+    public LinkedIdentityHashMap() {
+        map = new LinkedHashMap<>();
+    }
+
+    public LinkedIdentityHashMap(Map<K, V> m) {
+        map = new LinkedHashMap<>(m.size());
+        putAll(m);
+    }
+
+    public LinkedIdentityHashMap(int expectedMaxSize) {
+        map = new LinkedHashMap<>(expectedMaxSize);
+    }
+
+    /**
+     * Wrapper for an object that gives uses the object's identity for the purpose of equality
+     * comparisons and computing a hash code.
+     */
+    static final class Id<T> {
+        final T object;
+
+        public Id(T object) {
+            assert object != null;
+            this.object = object;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean equals(Object obj) {
+            return obj instanceof Id && ((Id<T>) obj).object == object;
+        }
+
+        @Override
+        public int hashCode() {
+            return System.identityHashCode(object);
+        }
+    }
+
+    public int size() {
+        return map.size();
+    }
+
+    public boolean isEmpty() {
+        return map.isEmpty();
+    }
+
+    public boolean containsKey(Object key) {
+        return map.containsKey(id(key));
+    }
+
+    @SuppressWarnings("unchecked")
+    private Id<K> id(Object key) {
+        if (key == null) {
+            return null;
+        }
+        return new Id<>((K) key);
+    }
+
+    public boolean containsValue(Object value) {
+        return map.containsValue(value);
+    }
+
+    public V get(Object key) {
+        return map.get(id(key));
+    }
+
+    public V put(K key, V value) {
+        return map.put(id(key), value);
+    }
+
+    public V remove(Object key) {
+        return map.remove(id(key));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void putAll(Map<? extends K, ? extends V> m) {
+        if (m == null) {
+            throw new NullPointerException();
+        }
+        if (m.getClass() == getClass()) {
+            LinkedIdentityHashMap<K, V> that = (LinkedIdentityHashMap<K, V>) m;
+            map.putAll(that.map);
+
+        } else {
+            for (K key : m.keySet()) {
+                map.put(id(key), m.get(key));
+            }
+        }
+    }
+
+    public void clear() {
+        map.clear();
+    }
+
+    final class KeySet extends AbstractSet<K> {
+        @Override
+        public int size() {
+            return map.size();
+        }
+
+        @Override
+        public void clear() {
+            map.clear();
+        }
+
+        @Override
+        public Iterator<K> iterator() {
+            return new Iterator<K>() {
+                final Iterator<Id<K>> i = map.keySet().iterator();
+
+                public boolean hasNext() {
+                    return i.hasNext();
+                }
+
+                public K next() {
+                    return i.next().object;
+                }
+
+                public void remove() {
+                    i.remove();
+                }
+            };
+        }
+
+        @Override
+        public boolean contains(Object o) {
+            return containsKey(o);
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            return LinkedIdentityHashMap.this.remove(o) != null;
+        }
+
+        public Spliterator<K> spliterator() {
+            return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT);
+        }
+
+        public void forEach(Consumer<? super K> action) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    public Set<K> keySet() {
+        return new KeySet();
+    }
+
+    public Collection<V> values() {
+        return map.values();
+    }
+
+    final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
+        @Override
+        public int size() {
+            return map.size();
+        }
+
+        @Override
+        public void clear() {
+            map.clear();
+        }
+
+        @Override
+        public Iterator<Map.Entry<K, V>> iterator() {
+            return new Iterator<Map.Entry<K, V>>() {
+                final Iterator<Map.Entry<Id<K>, V>> i = map.entrySet().iterator();
+
+                public boolean hasNext() {
+                    return i.hasNext();
+                }
+
+                public Map.Entry<K, V> next() {
+                    Map.Entry<Id<K>, V> e = i.next();
+                    return new Map.Entry<K, V>() {
+
+                        public K getKey() {
+                            return e.getKey().object;
+                        }
+
+                        public V getValue() {
+                            return e.getValue();
+                        }
+
+                        public V setValue(V value) {
+                            return e.setValue(value);
+                        }
+                    };
+                }
+
+                public void remove() {
+                    i.remove();
+                }
+            };
+        }
+
+        @Override
+        public boolean contains(Object o) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            throw new UnsupportedOperationException();
+        }
+
+        public Spliterator<Map.Entry<K, V>> spliterator() {
+            throw new UnsupportedOperationException();
+        }
+
+        public void forEach(Consumer<? super Map.Entry<K, V>> action) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    public Set<Map.Entry<K, V>> entrySet() {
+        return new EntrySet();
+    }
+}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/Context.java	Fri Dec 12 20:02:09 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,533 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.common.remote;
-
-import static java.lang.reflect.Modifier.*;
-
-import java.lang.reflect.*;
-import java.nio.*;
-import java.util.*;
-
-import sun.awt.util.*;
-
-import com.oracle.graal.api.code.Register.RegisterCategory;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.type.*;
-
-/**
- * Manages a context for replay or remote compilation.
- *
- * With respect to replay or remote compilation, certain objects only exist on the VM side of the
- * VM-compiler boundary. These are objects that encapsulate compiler references to user heap objects
- * or other VM data such as native VM objects representing Java classes and methods.
- */
-public class Context implements AutoCloseable {
-
-    private static final ThreadLocal<Context> currentContext = new ThreadLocal<>();
-
-    private final Map<Class<?>, Fields> fieldsMap = new HashMap<>();
-
-    public enum Mode {
-        Capturing,
-        Replaying
-    }
-
-    private Mode mode = Mode.Capturing;
-
-    public Mode getMode() {
-        return mode;
-    }
-
-    public void setMode(Mode mode) {
-        this.mode = mode;
-    }
-
-    public static <K, V> HashMap<K, V> newMap() {
-        return Context.getCurrent() == null ? new HashMap<>() : new LinkedHashMap<>();
-    }
-
-    public static <K, V> HashMap<K, V> newMap(Map<K, V> m) {
-        return Context.getCurrent() == null ? new HashMap<>(m) : new LinkedHashMap<>(m);
-    }
-
-    public static <K, V> HashMap<K, V> newMap(int initialCapacity) {
-        return Context.getCurrent() == null ? new HashMap<>(initialCapacity) : new LinkedHashMap<>(initialCapacity);
-    }
-
-    public static <K, V> Map<K, V> newIdentityMap() {
-        return Context.getCurrent() == null ? new IdentityHashMap<>() : new LinkedIdentityHashMap<>();
-    }
-
-    public static <K, V> Map<K, V> newIdentityMap(int expectedMaxSize) {
-        return Context.getCurrent() == null ? new IdentityHashMap<>(expectedMaxSize) : new LinkedIdentityHashMap<>();
-    }
-
-    public static <K, V> Map<K, V> newIdentityMap(Map<K, V> m) {
-        return Context.getCurrent() == null ? new IdentityHashMap<>(m) : new LinkedIdentityHashMap<>(m);
-    }
-
-    /**
-     * Gets a descriptor for the fields in a class that can be used for serialization.
-     */
-    private Fields fieldsFor(Class<?> c) {
-        Fields fields = fieldsMap.get(c);
-        if (fields == null) {
-            fields = Fields.forClass(c, Object.class, true, null);
-            fieldsMap.put(c, fields);
-        }
-        return fields;
-    }
-
-    /**
-     * Classes whose values are subject to special serialization handling.
-     */
-    // @formatter:off
-    private static final Set<Class<?>> DontCopyClasses = new HashSet<>(Arrays.asList(
-        Enum.class,
-        Integer.class,
-        Boolean.class,
-        Short.class,
-        Byte.class,
-        Character.class,
-        Float.class,
-        Long.class,
-        Double.class,
-        String.class,
-        Method.class,
-        Class.class,
-        Field.class,
-        Constructor.class,
-        RegisterCategory.class,
-        NamedLocationIdentity.class
-    ));
-    // @formatter:on
-
-    private static void registerSharedGlobal(Class<?> declaringClass, String staticFieldName) {
-        try {
-            SharedGlobal global = new SharedGlobal(declaringClass.getDeclaredField(staticFieldName));
-            SharedGlobals.put(global.get(), global);
-        } catch (NoSuchFieldException e) {
-            // ignore non-existing fields
-        } catch (Exception e) {
-            throw new GraalInternalError(e);
-        }
-    }
-
-    private static void registerSharedGlobals(Class<?> declaringClass, Class<?> staticFieldType) {
-        assert !staticFieldType.isPrimitive();
-        try {
-            for (Field f : declaringClass.getDeclaredFields()) {
-                if (isStatic(f.getModifiers()) && isFinal(f.getModifiers()) && !f.getType().isPrimitive()) {
-                    SharedGlobal global = new SharedGlobal(f);
-                    if (staticFieldType.isAssignableFrom(f.getType())) {
-                        SharedGlobals.put(global.get(), global);
-                    } else {
-                        Class<?> componentType = f.getType().getComponentType();
-                        if (componentType != null && staticFieldType.isAssignableFrom(componentType)) {
-                            Object[] vals = global.get();
-                            for (int i = 0; i < vals.length; i++) {
-                                SharedGlobal g = new SharedGlobal(f, i);
-                                Object obj = g.get();
-                                SharedGlobals.put(obj, g);
-                            }
-                        }
-                    }
-                }
-            }
-        } catch (Exception e) {
-            throw new GraalInternalError(e);
-        }
-    }
-
-    /**
-     * A shared global is a non-primitive value in a static final variable whose identity is
-     * important to the compiler. That is, equality tests against these values are performed with
-     * {@code ==} or these values are keys in identity hash maps.
-     */
-    static class SharedGlobal {
-        final Field staticField;
-        final Integer index;
-
-        public SharedGlobal(Field staticField) {
-            this(staticField, null);
-        }
-
-        public SharedGlobal(Field staticField, Integer index) {
-            int mods = staticField.getModifiers();
-            assert isStatic(mods) && isFinal(mods) && !staticField.getType().isPrimitive() : staticField;
-            staticField.setAccessible(true);
-            this.staticField = staticField;
-            this.index = index;
-        }
-
-        @SuppressWarnings("unchecked")
-        public <T> T get() {
-            try {
-                Object value = staticField.get(null);
-                if (index != null) {
-                    value = ((Object[]) value)[index.intValue()];
-                }
-                return (T) value;
-            } catch (Exception e) {
-                throw new GraalInternalError(e);
-            }
-        }
-
-        @Override
-        public String toString() {
-            String res = staticField.getDeclaringClass().getName() + "." + staticField.getName();
-            if (index != null) {
-                res += "[" + index + "]";
-            }
-            return res;
-        }
-    }
-
-    /**
-     * Objects that should not be copied but retrieved from final static fields.
-     */
-    private static final Map<Object, SharedGlobal> SharedGlobals = new IdentityHashMap<>();
-    static {
-        registerSharedGlobal(ByteOrder.class, "BIG_ENDIAN");
-        registerSharedGlobal(ByteOrder.class, "LITTLE_ENDIAN");
-        registerSharedGlobal(ArrayList.class, "EMPTY_ELEMENTDATA");
-        registerSharedGlobal(ArrayList.class, "DEFAULTCAPACITY_EMPTY_ELEMENTDATA");
-        registerSharedGlobals(StampFactory.class, Stamp.class);
-    }
-
-    /**
-     * Determines if a given class is a subclass of any class in a given collection of classes.
-     */
-    private static boolean isAssignableTo(Class<?> from, Collection<Class<?>> to) {
-        return to.stream().anyMatch(c -> c.isAssignableFrom(from));
-    }
-
-    /**
-     * Gets a string representing the identity of an object.
-     */
-    private static String id(Object o) {
-        if (o == null) {
-            return "null";
-        }
-        return String.format("%s@%x", MetaUtil.getSimpleName(o.getClass(), true), System.identityHashCode(o));
-    }
-
-    /**
-     * Process an object graph copy operation iteratively using a worklist.
-     */
-    private void copy0(Deque<Object> worklist, Map<Object, Object> copies) {
-        // 1. Traverse object graph, making uninitialized copies of
-        // objects that need to be copied (other object values are transferred 'as is')
-        while (!worklist.isEmpty()) {
-            Object obj = worklist.pollFirst();
-            // System.out.printf("worklist-: %s%n", s(obj));
-            assert copies.get(obj) == copies : id(obj) + " -> " + id(copies.get(obj));
-            assert pool.get(obj) == null;
-            Class<? extends Object> clazz = obj.getClass();
-            Class<?> componentType = clazz.getComponentType();
-            if (componentType != null) {
-                if (componentType.isPrimitive()) {
-                    if (obj instanceof int[]) {
-                        copies.put(obj, ((int[]) obj).clone());
-                    } else if (obj instanceof byte[]) {
-                        copies.put(obj, ((byte[]) obj).clone());
-                    } else if (obj instanceof char[]) {
-                        copies.put(obj, ((char[]) obj).clone());
-                    } else if (obj instanceof short[]) {
-                        copies.put(obj, ((short[]) obj).clone());
-                    } else if (obj instanceof float[]) {
-                        copies.put(obj, ((float[]) obj).clone());
-                    } else if (obj instanceof long[]) {
-                        copies.put(obj, ((long[]) obj).clone());
-                    } else if (obj instanceof double[]) {
-                        copies.put(obj, ((double[]) obj).clone());
-                    } else {
-                        copies.put(obj, ((boolean[]) obj).clone());
-                    }
-                } else {
-                    Object[] o = (Object[]) obj;
-                    Object[] c = o.clone();
-                    copies.put(obj, c);
-                    // System.out.printf("m+: %s%n", s(obj));
-                    for (int i = 0; i < c.length; i++) {
-                        c[i] = copyFieldOrElement(worklist, copies, o[i]);
-                    }
-                }
-            } else {
-                assert !isAssignableTo(clazz, DontCopyClasses);
-                Object c;
-                try {
-                    c = UnsafeAccess.unsafe.allocateInstance(clazz);
-                    copies.put(obj, c);
-                    // System.out.printf("m+: %s%n", s(obj));
-
-                    Fields fields = fieldsFor(clazz);
-                    fields.copy(obj, c, (i, o) -> copyFieldOrElement(worklist, copies, o));
-                } catch (InstantiationException e) {
-                    throw new GraalInternalError(e);
-                }
-            }
-        }
-
-        // 2. Initialize fields of copied objects
-        for (Map.Entry<Object, Object> e : copies.entrySet()) {
-            Object src = e.getKey();
-            Object dst = e.getValue();
-            assert dst != copies : id(src);
-            pool.put(src, dst);
-            if (src instanceof Object[]) {
-                Object[] srcArr = (Object[]) src;
-                Object[] dstArr = (Object[]) dst;
-                for (int i = 0; i < srcArr.length; i++) {
-                    Object dstElement = copies.get(srcArr[i]);
-                    if (dstElement != null) {
-                        dstArr[i] = dstElement;
-                    }
-                }
-            } else {
-                Fields fields = fieldsFor(src.getClass());
-                assert !Proxy.isProxyClass(dst.getClass());
-                for (int index = 0; index < fields.getCount(); index++) {
-                    if (!fields.getType(index).isPrimitive()) {
-                        Object value = copies.get(fields.getObject(src, index));
-                        if (value != null) {
-                            fields.set(dst, index, value);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Given the value of an object field or object array element, returns the value that should be
-     * written into the copy of the object or array.
-     */
-    private Object copyFieldOrElement(Deque<Object> worklist, Map<Object, Object> copies, Object srcValue) {
-        Object dstValue = srcValue;
-        if (srcValue != null && !Proxy.isProxyClass(srcValue.getClass())) {
-            if (isAssignableTo(srcValue.getClass(), DontCopyClasses) || SharedGlobals.containsKey(srcValue)) {
-                pool.put(srcValue, srcValue);
-                return srcValue;
-            }
-            dstValue = pool.get(srcValue);
-            if (dstValue == null) {
-                if (srcValue instanceof Remote) {
-                    dstValue = get(srcValue);
-                } else {
-                    dstValue = copies.get(srcValue);
-                    if (dstValue == null) {
-                        // System.out.printf("worklist+: %s%n", s(srcValue));
-                        worklist.add(srcValue);
-                        copies.put(srcValue, copies);
-                    } else if (dstValue == copies) {
-                        dstValue = null;
-                    }
-                }
-            }
-        }
-        return dstValue;
-    }
-
-    /**
-     * Copies an object graph. This operation does not copy:
-     * <ul>
-     * <li>objects whose type is assignable to one of {@link #DontCopyClasses}</li>
-     * <li>proxy objects</li>
-     * </ul>
-     * In addition, copies in {@link #pool} are re-used.
-     */
-    private Object copy(Object root) {
-        long start = System.currentTimeMillis();
-        assert !(isAssignableTo(root.getClass(), DontCopyClasses) || SharedGlobals.containsKey(root));
-        // System.out.printf("----- %s ------%n", s(obj));
-        assert pool.get(root) == null;
-        Deque<Object> worklist = new IdentityLinkedList<>();
-        worklist.add(root);
-        IdentityHashMap<Object, Object> copies = new IdentityHashMap<>();
-        copies.put(root, copies);
-        copy0(worklist, copies);
-        if (DEBUG) {
-            long duration = System.currentTimeMillis() - start;
-            if (duration > 10) {
-                System.out.printf("After copying %s (proxies: %d, pool: %d) %d ms%n", root.getClass().getSimpleName(), proxies.size(), pool.size(), duration);
-            }
-        }
-        return pool.get(root);
-    }
-
-    /**
-     * Creates an opens a context for a remote compilation request or a replay compilation
-     * capturing. This should be used in conjunction with the try-finally statement:
-     *
-     * <pre>
-     * try (Context c = new Context()) {
-     *     ...
-     * }
-     * </pre>
-     *
-     * Open one context can be active at any time for a thread.
-     */
-    public Context() {
-        assert currentContext.get() == null : currentContext.get();
-        currentContext.set(this);
-        pool = new IdentityHashMap<>();
-    }
-
-    private final Map<Object, Object> proxies = new IdentityHashMap<>();
-    private final Map<Object, Object> pool;
-
-    int invocationCacheHits;
-    int invocationCacheMisses;
-
-    /**
-     * Gets the value of a given object within this context.
-     */
-    @SuppressWarnings("unchecked")
-    public <T> T get(Object obj) {
-        if (obj == null || Proxy.isProxyClass(obj.getClass())) {
-            return (T) obj;
-        }
-        if (obj instanceof Remote) {
-            Object proxy = proxies.get(obj);
-            if (proxy == null) {
-                Class<?>[] interfaces = ProxyUtil.getAllInterfaces(obj.getClass());
-                proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(), interfaces, new Handler<>(obj));
-                proxies.put(obj, proxy);
-            }
-            return (T) proxy;
-        } else {
-            Object value;
-            if (isAssignableTo(obj.getClass(), DontCopyClasses) || SharedGlobals.containsKey(obj)) {
-                value = obj;
-            } else {
-                value = pool.get(obj);
-                if (value == null) {
-                    if (mode == Mode.Capturing) {
-                        value = copy(obj);
-                    } else {
-                        throw new GraalInternalError("No captured state for %s [class=%s]", obj, obj.getClass());
-                    }
-                }
-            }
-            return (T) value;
-        }
-    }
-
-    private static final boolean DEBUG = Boolean.getBoolean("graal.replayContext.debug");
-
-    public void close() {
-        assert currentContext.get() == this : currentContext.get();
-        if (DEBUG) {
-            System.out.printf("proxies: %d, pool: %d, invocation cache hits: %d, invocation cache misses: %d%n", proxies.size(), pool.size(), invocationCacheHits, invocationCacheMisses);
-        }
-        currentContext.set(null);
-    }
-
-    /**
-     * Checks that a given value is valid within the {@linkplain #getCurrent() current context} (if
-     * any).
-     */
-    public static boolean check(Object o) {
-        if (o != null) {
-            Context c = currentContext.get();
-            if (c != null) {
-                if (o instanceof Remote) {
-                    if (!Proxy.isProxyClass(o.getClass())) {
-                        throw new GraalInternalError("Expecting proxy, found instance of %s", o.getClass());
-                    }
-                } else {
-                    if (Proxy.isProxyClass(o.getClass())) {
-                        throw new GraalInternalError("Expecting instance of %s, found proxy", o.getClass());
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Asserts that the current caller is in code that is on the VM side.
-     *
-     * @param errorMessage the error message used for the {@link GraalInternalError} thrown if the
-     *            check fails
-     * @return true if the check succeeds
-     * @throw AssertionError if the check fails
-     */
-    public static boolean assertInLocal(String errorMessage) {
-        Context c = Context.getCurrent();
-        if (c != null) {
-            if (!c.inProxyInvocation()) {
-                throw new AssertionError(errorMessage);
-            }
-        }
-        return true;
-    }
-
-    private NoContext leave;
-    int activeInvocations;
-
-    /**
-     * Enters a scope that disables the {@linkplain Context#getCurrent() current} context. The
-     * disabled scope is exited when {@link NoContext#close()} is called on the returned object.
-     */
-    public NoContext leave() {
-        return new NoContext();
-    }
-
-    public class NoContext implements AutoCloseable {
-        NoContext() {
-            assert currentContext.get() == Context.this;
-            assert Context.this.leave == null;
-            Context.this.leave = this;
-            currentContext.set(null);
-        }
-
-        public void close() {
-            assert leave == this;
-            assert currentContext.get() == null;
-            currentContext.set(Context.this);
-            leave = null;
-        }
-    }
-
-    /**
-     * Gets the currently active context for the calling thread.
-     *
-     * @return {@code null} if there is no context active on the calling thread
-     */
-    public static Context getCurrent() {
-        return currentContext.get();
-    }
-
-    public boolean inProxyInvocation() {
-        return activeInvocations != 0;
-    }
-
-    public static void breakpoint() {
-        if (getCurrent() != null) {
-            System.console();
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/Handler.java	Fri Dec 12 20:02:09 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.common.remote;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-public class Handler<T> implements InvocationHandler {
-
-    private final T delegate;
-
-    /**
-     * Proxies objects may be visible to multiple threads.
-     */
-    Map<Invocation, Object> cachedInvocations = new ConcurrentHashMap<>();
-
-    public Handler(T delegate) {
-        this.delegate = delegate;
-    }
-
-    static Object[] unproxify(Object[] args) {
-        if (args == null) {
-            return args;
-        }
-        Object[] res = args;
-        for (int i = 0; i < args.length; i++) {
-            Object arg = args[i];
-            if (arg != null) {
-                if (Proxy.isProxyClass(arg.getClass())) {
-                    Handler<?> h = (Handler<?>) Proxy.getInvocationHandler(arg);
-                    if (res == args) {
-                        res = args.clone();
-                    }
-                    res[i] = h.delegate;
-                } else if (arg instanceof Object[]) {
-                    Object[] arrayArg = (Object[]) arg;
-                    arrayArg = unproxify(arrayArg);
-                    if (arrayArg != arg) {
-                        if (res == args) {
-                            res = args.clone();
-                        }
-                        res[i] = arrayArg;
-                    }
-                }
-            }
-        }
-        return res;
-    }
-
-    private static boolean isCacheable(Method method) {
-        // TODO: use annotations for finer control of what should be cached
-        return method.getReturnType() != Void.TYPE;
-    }
-
-    private static final Object NULL_RESULT = new Object();
-
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] a) throws Throwable {
-        Object[] args = unproxify(a);
-        boolean isCacheable = isCacheable(method);
-        Invocation invocation = new Invocation(method, delegate, args);
-        if (isCacheable) {
-            Object result = cachedInvocations.get(invocation);
-            if (result != null) {
-                if (result == NULL_RESULT) {
-                    result = null;
-                }
-                // System.out.println(invocation + ": " + result);
-                return result;
-            }
-        } else {
-            // System.out.println("not cacheable: " + method);
-        }
-
-        Context context = Context.getCurrent();
-        assert context != null;
-        try {
-            assert context.activeInvocations >= 0;
-            context.activeInvocations++;
-            Object result = invocation.invoke();
-            result = context.get(result);
-            if (isCacheable) {
-                context.invocationCacheHits++;
-                cachedInvocations.put(invocation, result == null ? NULL_RESULT : result);
-            }
-            return result;
-        } finally {
-            assert context.activeInvocations > 0;
-            context.activeInvocations--;
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/Invocation.java	Fri Dec 12 20:02:09 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.common.remote;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.stream.*;
-
-class Invocation {
-    final Method method;
-    final Object receiver;
-    final Object[] args;
-
-    public Invocation(Method method, Object receiver, Object[] args) {
-        this.method = method;
-        this.receiver = receiver;
-        this.args = args;
-    }
-
-    @Override
-    public String toString() {
-        String res = receiver.getClass().getSimpleName() + "@" + System.identityHashCode(receiver) + "." + method.getName();
-        if (args == null) {
-            return res + "()";
-        }
-        return res + "(" + Arrays.asList(args).stream().map(o -> String.valueOf(o)).collect(Collectors.joining(", ")) + ")";
-    }
-
-    public Object invoke() {
-        try {
-            if (args == null) {
-                return method.invoke(receiver);
-            } else {
-                return method.invoke(receiver, args);
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof Invocation) {
-            Invocation that = (Invocation) obj;
-            assert that.receiver == receiver;
-            return that.method.equals(this.method) && Arrays.equals(that.args, this.args);
-
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        if (args == null) {
-            return method.hashCode();
-        }
-        return method.hashCode() ^ args.length;
-    }
-}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/LinkedIdentityHashMap.java	Fri Dec 12 20:02:09 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,254 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.common.remote;
-
-import java.util.*;
-import java.util.function.*;
-
-import com.oracle.graal.compiler.common.remote.Context.Mode;
-
-/**
- * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of
- * ensuring a deterministic execution order during {@link Mode#Capturing}.
- */
-final class LinkedIdentityHashMap<K, V> implements Map<K, V> {
-
-    private final LinkedHashMap<Id<K>, V> map;
-
-    public LinkedIdentityHashMap() {
-        map = new LinkedHashMap<>();
-    }
-
-    public LinkedIdentityHashMap(Map<K, V> m) {
-        map = new LinkedHashMap<>(m.size());
-        putAll(m);
-    }
-
-    public LinkedIdentityHashMap(int expectedMaxSize) {
-        map = new LinkedHashMap<>(expectedMaxSize);
-    }
-
-    /**
-     * Wrapper for an object that gives uses the object's identity for the purpose of equality
-     * comparisons and computing a hash code.
-     */
-    static final class Id<T> {
-        final T object;
-
-        public Id(T object) {
-            assert object != null;
-            this.object = object;
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public boolean equals(Object obj) {
-            return obj instanceof Id && ((Id<T>) obj).object == object;
-        }
-
-        @Override
-        public int hashCode() {
-            return System.identityHashCode(object);
-        }
-    }
-
-    public int size() {
-        return map.size();
-    }
-
-    public boolean isEmpty() {
-        return map.isEmpty();
-    }
-
-    public boolean containsKey(Object key) {
-        return map.containsKey(id(key));
-    }
-
-    @SuppressWarnings("unchecked")
-    private Id<K> id(Object key) {
-        if (key == null) {
-            return null;
-        }
-        return new Id<>((K) key);
-    }
-
-    public boolean containsValue(Object value) {
-        return map.containsValue(value);
-    }
-
-    public V get(Object key) {
-        return map.get(id(key));
-    }
-
-    public V put(K key, V value) {
-        return map.put(id(key), value);
-    }
-
-    public V remove(Object key) {
-        return map.remove(id(key));
-    }
-
-    @SuppressWarnings("unchecked")
-    public void putAll(Map<? extends K, ? extends V> m) {
-        if (m == null) {
-            throw new NullPointerException();
-        }
-        if (m.getClass() == getClass()) {
-            LinkedIdentityHashMap<K, V> that = (LinkedIdentityHashMap<K, V>) m;
-            map.putAll(that.map);
-
-        } else {
-            for (K key : m.keySet()) {
-                map.put(id(key), m.get(key));
-            }
-        }
-    }
-
-    public void clear() {
-        map.clear();
-    }
-
-    final class KeySet extends AbstractSet<K> {
-        @Override
-        public int size() {
-            return map.size();
-        }
-
-        @Override
-        public void clear() {
-            map.clear();
-        }
-
-        @Override
-        public Iterator<K> iterator() {
-            return new Iterator<K>() {
-                final Iterator<Id<K>> i = map.keySet().iterator();
-
-                public boolean hasNext() {
-                    return i.hasNext();
-                }
-
-                public K next() {
-                    return i.next().object;
-                }
-
-                public void remove() {
-                    i.remove();
-                }
-            };
-        }
-
-        @Override
-        public boolean contains(Object o) {
-            return containsKey(o);
-        }
-
-        @Override
-        public boolean remove(Object o) {
-            return LinkedIdentityHashMap.this.remove(o) != null;
-        }
-
-        public Spliterator<K> spliterator() {
-            return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT);
-        }
-
-        public void forEach(Consumer<? super K> action) {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    public Set<K> keySet() {
-        return new KeySet();
-    }
-
-    public Collection<V> values() {
-        return map.values();
-    }
-
-    final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
-        @Override
-        public int size() {
-            return map.size();
-        }
-
-        @Override
-        public void clear() {
-            map.clear();
-        }
-
-        @Override
-        public Iterator<Map.Entry<K, V>> iterator() {
-            return new Iterator<Map.Entry<K, V>>() {
-                final Iterator<Map.Entry<Id<K>, V>> i = map.entrySet().iterator();
-
-                public boolean hasNext() {
-                    return i.hasNext();
-                }
-
-                public Map.Entry<K, V> next() {
-                    Map.Entry<Id<K>, V> e = i.next();
-                    return new Map.Entry<K, V>() {
-
-                        public K getKey() {
-                            return e.getKey().object;
-                        }
-
-                        public V getValue() {
-                            return e.getValue();
-                        }
-
-                        public V setValue(V value) {
-                            return e.setValue(value);
-                        }
-                    };
-                }
-
-                public void remove() {
-                    i.remove();
-                }
-            };
-        }
-
-        @Override
-        public boolean contains(Object o) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public boolean remove(Object o) {
-            throw new UnsupportedOperationException();
-        }
-
-        public Spliterator<Map.Entry<K, V>> spliterator() {
-            throw new UnsupportedOperationException();
-        }
-
-        public void forEach(Consumer<? super Map.Entry<K, V>> action) {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    public Set<Map.Entry<K, V>> entrySet() {
-        return new EntrySet();
-    }
-}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/remote/ProxyUtil.java	Fri Dec 12 20:02:09 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.common.remote;
-
-import java.util.*;
-
-public final class ProxyUtil {
-
-    public static Class<?>[] getAllInterfaces(Class<?> clazz) {
-        HashSet<Class<?>> interfaces = new HashSet<>();
-        getAllInterfaces(clazz, interfaces);
-        return interfaces.toArray(new Class<?>[interfaces.size()]);
-    }
-
-    private static void getAllInterfaces(Class<?> clazz, HashSet<Class<?>> interfaces) {
-        for (Class<?> iface : clazz.getInterfaces()) {
-            if (!interfaces.contains(iface)) {
-                interfaces.add(iface);
-                getAllInterfaces(iface, interfaces);
-            }
-        }
-        if (clazz.getSuperclass() != null) {
-            getAllInterfaces(clazz.getSuperclass(), interfaces);
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Dec 12 20:29:35 2014 +0100
@@ -27,7 +27,6 @@
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
 
-import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.atomic.*;
@@ -44,8 +43,6 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.GraalCompiler.Request;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.remote.*;
-import com.oracle.graal.compiler.common.remote.Context.Mode;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -676,96 +673,6 @@
     }
 
     /**
-     * Determines if {@linkplain #compile(ResolvedJavaMethod, StructuredGraph) compilation} should
-     * also be attempted in a replay {@link Context} where possible.
-     */
-    private static final boolean TEST_REPLAY = Boolean.getBoolean("graal.testReplay");
-
-    /**
-     * Determines if a {@link #checkCompilationResultsEqual mismatching} replay compilation result
-     * results in a diagnostic message or a test error.
-     */
-    private static final boolean TEST_REPLAY_MISMATCH_IS_FAILURE = Boolean.parseBoolean(System.getProperty("graal.testReplay.strict", "true"));
-
-    /**
-     * Directory into which tests can dump content useful in debugging test failures.
-     */
-    private static final File OUTPUT_DIR = new File(System.getProperty("graal.test.output"), "testOutput");
-
-    protected static File getOutputDir() {
-        if (!OUTPUT_DIR.exists()) {
-            OUTPUT_DIR.mkdirs();
-        }
-        if (!OUTPUT_DIR.exists()) {
-            throw new GraalInternalError("Could not create test output directory: %s", OUTPUT_DIR.getAbsolutePath());
-        }
-        return OUTPUT_DIR;
-    }
-
-    protected String dissasembleToFile(CompilationResult result, ResolvedJavaMethod installedCodeOwner, String fileSuffix) {
-        String dis = getCodeCache().disassemble(result, null);
-        File disFile = new File(getOutputDir(), installedCodeOwner.format("%H.%n_%p").replace(", ", "__") + "." + fileSuffix);
-        try (PrintStream ps = new PrintStream(new FileOutputStream(disFile))) {
-            ps.println(dis);
-            return disFile.getAbsolutePath();
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    protected void checkCompilationResultsEqual(CompilationResult expected, CompilationResult actual, ResolvedJavaMethod installedCodeOwner) {
-        if (!actual.equals(expected)) {
-            // Reset to capturing mode as dumping/printing/disassembling
-            // may need to execute proxy methods that have not yet been executed
-            String expectedDisFile = dissasembleToFile(expected, installedCodeOwner, "expected");
-            String actualDisFile = dissasembleToFile(actual, installedCodeOwner, "actual");
-            String message = "Reply compilation result differs from capturing compilation result";
-            if (expectedDisFile != null && actualDisFile != null) {
-                message += String.format(" [diff %s %s]", expectedDisFile, actualDisFile);
-            }
-            if (TEST_REPLAY_MISMATCH_IS_FAILURE) {
-                Assert.fail(message);
-            } else {
-                System.out.println(message);
-            }
-        }
-    }
-
-    protected CompilationResult recompile(Context c, Mode mode, ResolvedJavaMethod installedCodeOwner) {
-        try (Debug.Scope s = Debug.scope(mode.name(), new DebugDumpScope(mode.name(), true))) {
-
-            StructuredGraph graphToCompile;
-            CallingConvention cc;
-
-            try (Context.NoContext l = c.leave()) {
-                graphToCompile = parseForCompile(installedCodeOwner);
-                lastCompiledGraph = graphToCompile;
-                cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graphToCompile.method(), false);
-            }
-            graphToCompile = c.get(graphToCompile);
-            Request<CompilationResult> request = c.get(new GraalCompiler.Request<>(graphToCompile, null, cc, installedCodeOwner, getProviders(), getBackend(), getCodeCache().getTarget(), null,
-                            getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graphToCompile), getSpeculationLog(), getSuites(), new CompilationResult(),
-                            CompilationResultBuilderFactory.Default));
-            return GraalCompiler.compile(request);
-        } catch (Throwable e) {
-            throw Debug.handle(e);
-        }
-    }
-
-    protected void testReplayCompile(ResolvedJavaMethod installedCodeOwner) {
-        try (Context c = new Context()) {
-
-            // Capturing compilation
-            CompilationResult expected = recompile(c, Mode.Capturing, installedCodeOwner);
-
-            // Replay compilation
-            CompilationResult actual = recompile(c, Mode.Replaying, installedCodeOwner);
-
-            checkCompilationResultsEqual(expected, actual, installedCodeOwner);
-        }
-    }
-
-    /**
      * Compiles a given method.
      *
      * @param installedCodeOwner the method the compiled code will be associated with when installed
@@ -777,13 +684,9 @@
         StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner) : graph;
         lastCompiledGraph = graphToCompile;
         CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graphToCompile.method(), false);
-        CompilationResult res = GraalCompiler.compileGraph(graphToCompile, null, cc, installedCodeOwner, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(),
+        Request<CompilationResult> request = new Request<>(graphToCompile, null, cc, installedCodeOwner, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(),
                         OptimisticOptimizations.ALL, getProfilingInfo(graphToCompile), getSpeculationLog(), getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default);
-
-        if (TEST_REPLAY && graph == null) {
-            testReplayCompile(installedCodeOwner);
-        }
-        return res;
+        return GraalCompiler.compile(request);
     }
 
     protected StructuredGraph lastCompiledGraph;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LocationMarker.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LocationMarker.java	Fri Dec 12 20:29:35 2014 +0100
@@ -41,7 +41,7 @@
     public static class Options {
         // @formatter:off
         @Option(help = "Use decoupled pass for location marking (instead of using LSRA marking)")
-        public static final OptionValue<Boolean> UseLocationMarker = new OptionValue<>(true);
+        public static final OptionValue<Boolean> UseLocationMarker = new OptionValue<>(false);
         // @formatter:on
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Fri Dec 12 20:29:35 2014 +0100
@@ -29,6 +29,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 
@@ -119,7 +120,7 @@
     /**
      * Maps operands to nodes.
      */
-    private final HashMap<Value, PhiResolverNode> operandToNodeMap = new HashMap<>();
+    private final HashMap<Value, PhiResolverNode> operandToNodeMap = CollectionsFactory.newMap();
 
     public PhiResolver(LIRGeneratorTool gen) {
         this.gen = gen;
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugDumpHandler.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugDumpHandler.java	Fri Dec 12 20:29:35 2014 +0100
@@ -28,6 +28,11 @@
 
     void dump(Object object, String message);
 
+    /**
+     * Flushes and releases resources managed by this dump handler. A subsequent call to
+     * {@link #dump(Object, String)} will create and open new resources. That is, this method can be
+     * used to reset the handler.
+     */
     @Override
     void close();
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Fri Dec 12 20:29:35 2014 +0100
@@ -68,8 +68,9 @@
 
     // these two arrays contain one entry for each NodeClass, indexed by NodeClass.iterableId.
     // they contain the first and last pointer to a linked list of all nodes with this type.
-    private final ArrayList<Node> nodeCacheFirst;
-    private final ArrayList<Node> nodeCacheLast;
+    private final ArrayList<Node> iterableNodesFirst;
+    private final ArrayList<Node> iterableNodesLast;
+
     private int nodesDeletedSinceLastCompression;
     private int nodesDeletedBeforeLastCompression;
 
@@ -153,8 +154,8 @@
      */
     public Graph(String name) {
         nodes = new Node[INITIAL_NODES_SIZE];
-        nodeCacheFirst = new ArrayList<>(NodeClass.cacheSize());
-        nodeCacheLast = new ArrayList<>(NodeClass.cacheSize());
+        iterableNodesFirst = new ArrayList<>(NodeClass.allocatedNodeIterabledIds());
+        iterableNodesLast = new ArrayList<>(NodeClass.allocatedNodeIterabledIds());
         this.name = name;
         if (MODIFICATION_COUNTS_ENABLED) {
             nodeModCounts = new int[INITIAL_NODES_SIZE];
@@ -708,7 +709,7 @@
     }
 
     Node getStartNode(int iterableId) {
-        Node start = nodeCacheFirst.size() <= iterableId ? null : nodeCacheFirst.get(iterableId);
+        Node start = iterableNodesFirst.size() <= iterableId ? null : iterableNodesFirst.get(iterableId);
         return start;
     }
 
@@ -742,20 +743,7 @@
         nodes[id] = node;
         nodesSize++;
 
-        int nodeClassId = node.getNodeClass().iterableId();
-        if (nodeClassId != Node.NOT_ITERABLE) {
-            while (nodeCacheFirst.size() <= nodeClassId) {
-                nodeCacheFirst.add(null);
-                nodeCacheLast.add(null);
-            }
-            Node prev = nodeCacheLast.get(nodeClassId);
-            if (prev != null) {
-                prev.typeCacheNext = node;
-            } else {
-                nodeCacheFirst.set(nodeClassId, node);
-            }
-            nodeCacheLast.set(nodeClassId, node);
-        }
+        updateNodeCaches(node);
 
         node.id = id;
         if (nodeEventListener != null) {
@@ -763,6 +751,42 @@
         }
     }
 
+    @SuppressWarnings("unused")
+    private void postDeserialization() {
+        recomputeIterableNodeLists();
+    }
+
+    /**
+     * Rebuilds the lists used to support {@link #getNodes(Class)}. This is useful for serialization
+     * where the underlying {@linkplain NodeClass#iterableId() iterable ids} may have changed.
+     */
+    private void recomputeIterableNodeLists() {
+        iterableNodesFirst.clear();
+        iterableNodesLast.clear();
+        for (Node node : nodes) {
+            if (node != null && node.isAlive()) {
+                updateNodeCaches(node);
+            }
+        }
+    }
+
+    private void updateNodeCaches(Node node) {
+        int nodeClassId = node.getNodeClass().iterableId();
+        if (nodeClassId != Node.NOT_ITERABLE) {
+            while (iterableNodesFirst.size() <= nodeClassId) {
+                iterableNodesFirst.add(null);
+                iterableNodesLast.add(null);
+            }
+            Node prev = iterableNodesLast.get(nodeClassId);
+            if (prev != null) {
+                prev.typeCacheNext = node;
+            } else {
+                iterableNodesFirst.set(nodeClassId, node);
+            }
+            iterableNodesLast.set(nodeClassId, node);
+        }
+    }
+
     void unregister(Node node) {
         assert !isFrozen();
         assert !node.isDeleted() : "cannot delete a node twice! node=" + node;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Fri Dec 12 20:29:35 2014 +0100
@@ -31,7 +31,7 @@
 import sun.misc.*;
 
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.remote.*;
+import com.oracle.graal.compiler.common.CollectionsFactory.Mode;
 import com.oracle.graal.graph.Graph.NodeEventListener;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
@@ -209,20 +209,20 @@
     }
 
     /**
-     * Creates a {@link Node} set. If the current thread has a non-null
-     * {@linkplain Context#getCurrent() compilation replay scope}, the returned set will have a
-     * deterministic iteration order determined by the order in which elements are inserted in the
-     * map.
+     * Creates a {@link Node} set. If the current thread is
+     * {@linkplain CollectionsFactory#getMode() using} {@link Mode#DETERMINISTIC_ITERATION_ORDER}
+     * collections, the returned set will have an iteration order determined by the order in which
+     * elements are inserted in the set.
      */
     public static <E extends Node> Set<E> newSet() {
-        return Context.getCurrent() == null ? new HashSet<>() : new LinkedHashSet<>();
+        return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>() : new LinkedHashSet<>();
     }
 
     /**
      * @see #newSet()
      */
     public static <E extends Node> Set<E> newSet(Collection<? extends E> c) {
-        return Context.getCurrent() == null ? new HashSet<>(c) : new LinkedHashSet<>(c);
+        return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>(c) : new LinkedHashSet<>(c);
     }
 
     public static <K extends Node, V> Map<K, V> newMap() {
@@ -250,15 +250,15 @@
     }
 
     public static <K extends Node, V> Map<K, V> newIdentityMap() {
-        return Context.newIdentityMap();
+        return CollectionsFactory.newIdentityMap();
     }
 
     public static <K extends Node, V> Map<K, V> newIdentityMap(Map<K, V> m) {
-        return Context.newIdentityMap(m);
+        return CollectionsFactory.newIdentityMap(m);
     }
 
     public static <K extends Node, V> Map<K, V> newIdentityMap(int expectedMaxSize) {
-        return Context.newIdentityMap(expectedMaxSize);
+        return CollectionsFactory.newIdentityMap(expectedMaxSize);
     }
 
     /**
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Dec 12 20:29:35 2014 +0100
@@ -255,7 +255,7 @@
         return isSimplifiable;
     }
 
-    public static int cacheSize() {
+    static int allocatedNodeIterabledIds() {
         return nextIterableId;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableAddressOp.java	Fri Dec 12 20:29:35 2014 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.hotspot.HotSpotGraalRuntime;
+
+public class AMD64HotSpotCardTableAddressOp extends AMD64LIRInstruction {
+
+    @Def({OperandFlag.REG}) private AllocatableValue result;
+
+    public AMD64HotSpotCardTableAddressOp(AllocatableValue result) {
+        this.result = result;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
+        Kind hostWordKind = HotSpotGraalRuntime.getHostWordKind();
+        int alignment = hostWordKind.getBitCount() / Byte.SIZE;
+        JavaConstant address = JavaConstant.forIntegerKind(hostWordKind, 0);
+        // recordDataReferenceInCode forces the mov to be rip-relative
+        asm.movq(ValueUtil.asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(address, alignment));
+        MarkId.recordMark(crb, MarkId.CARD_TABLE_ADDRESS);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableShiftOp.java	Fri Dec 12 20:29:35 2014 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.hotspot.HotSpotGraalRuntime;
+
+public class AMD64HotSpotCardTableShiftOp extends AMD64LIRInstruction {
+
+    @Def({OperandFlag.REG, OperandFlag.ILLEGAL}) private AllocatableValue result;
+
+    public AMD64HotSpotCardTableShiftOp(AllocatableValue result) {
+        this.result = result;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
+        Kind hostWordKind = HotSpotGraalRuntime.getHostWordKind();
+        int alignment = Kind.Int.getBitCount() / Byte.SIZE;
+        JavaConstant shift = JavaConstant.forIntegerKind(hostWordKind, 0);
+        // recordDataReferenceInCode forces the mov to be rip-relative
+        asm.movq(ValueUtil.asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(shift, alignment));
+        MarkId.recordMark(crb, MarkId.CARD_TABLE_SHIFT);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java	Fri Dec 12 20:29:35 2014 +0100
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import com.oracle.graal.hotspot.HotSpotGraalRuntime;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
@@ -66,14 +67,31 @@
                     masm.cmpq(asRegister(x), patch);
                 }
             } else if (y instanceof HotSpotMetaspaceConstant) {
+                boolean isImmutable = GraalOptions.ImmutableCode.getValue();
+                boolean generatePIC = GraalOptions.GeneratePIC.getValue();
                 if (y.getKind() == Kind.Int) {
                     // compressed metaspace pointer
                     crb.recordInlineDataInCode(y);
-                    masm.cmpl(asRegister(x), y.asInt());
+                    if (isImmutable && generatePIC) {
+                        Kind hostWordKind = HotSpotGraalRuntime.getHostWordKind();
+                        int alignment = hostWordKind.getBitCount() / Byte.SIZE;
+                        // recordDataReferenceInCode forces the mov to be rip-relative
+                        masm.cmpl(asRegister(x), (AMD64Address) crb.recordDataReferenceInCode(JavaConstant.INT_0, alignment));
+                    } else {
+                        masm.cmpl(asRegister(x), y.asInt());
+                    }
                 } else {
                     // uncompressed metaspace pointer
-                    AMD64Address patch = (AMD64Address) crb.recordDataReferenceInCode(y, 8);
-                    masm.cmpq(asRegister(x), patch);
+                    if (isImmutable && generatePIC) {
+                        crb.recordInlineDataInCode(y);
+                        Kind hostWordKind = HotSpotGraalRuntime.getHostWordKind();
+                        int alignment = hostWordKind.getBitCount() / Byte.SIZE;
+                        // recordDataReferenceInCode forces the mov to be rip-relative
+                        masm.cmpq(asRegister(x), (AMD64Address) crb.recordDataReferenceInCode(JavaConstant.INT_0, alignment));
+                    } else {
+                        AMD64Address patch = (AMD64Address) crb.recordDataReferenceInCode(y, 8);
+                        masm.cmpq(asRegister(x), patch);
+                    }
                 }
             } else {
                 throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Fri Dec 12 20:29:35 2014 +0100
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
@@ -45,7 +46,7 @@
      * Map from debug infos that need to be updated with callee save information to the operations
      * that provide the information.
      */
-    private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>();
+    private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = CollectionsFactory.newMap();
 
     public AMD64HotSpotLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, Object stub) {
         super(lir, frameMapBuilder);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Dec 12 20:29:35 2014 +0100
@@ -211,6 +211,20 @@
         append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), saveRegisterOp));
     }
 
+    @Override
+    public Value emitCardTableShift() {
+        Variable result = newVariable(LIRKind.value(Kind.Long));
+        append(new AMD64HotSpotCardTableShiftOp(result));
+        return result;
+    }
+
+    @Override
+    public Value emitCardTableAddress() {
+        Variable result = newVariable(LIRKind.value(Kind.Long));
+        append(new AMD64HotSpotCardTableAddressOp(result));
+        return result;
+    }
+
     /**
      * @param savedRegisters the registers saved by this operation which may be subject to pruning
      * @param savedRegisterLocations the slots to which the registers are saved
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Fri Dec 12 20:29:35 2014 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
@@ -94,17 +95,37 @@
             } else if (input instanceof HotSpotMetaspaceConstant) {
                 assert input.getKind() == Kind.Int || input.getKind() == Kind.Long;
                 boolean compressed = input.getKind() == Kind.Int;
+                boolean isImmutable = GraalOptions.ImmutableCode.getValue();
+                boolean generatePIC = GraalOptions.GeneratePIC.getValue();
                 crb.recordInlineDataInCode(input);
                 if (isRegister(result)) {
                     if (compressed) {
-                        masm.movl(asRegister(result), input.asInt());
+                        if (isImmutable && generatePIC) {
+                            Kind hostWordKind = HotSpotGraalRuntime.getHostWordKind();
+                            int alignment = hostWordKind.getBitCount() / Byte.SIZE;
+                            // recordDataReferenceInCode forces the mov to be rip-relative
+                            masm.movl(asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(JavaConstant.INT_0, alignment));
+                        } else {
+                            masm.movl(asRegister(result), input.asInt());
+                        }
                     } else {
-                        masm.movq(asRegister(result), input.asLong());
+                        if (isImmutable && generatePIC) {
+                            Kind hostWordKind = HotSpotGraalRuntime.getHostWordKind();
+                            int alignment = hostWordKind.getBitCount() / Byte.SIZE;
+                            // recordDataReferenceInCode forces the mov to be rip-relative
+                            masm.movq(asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(JavaConstant.INT_0, alignment));
+                        } else {
+                            masm.movq(asRegister(result), input.asLong());
+                        }
                     }
                 } else {
                     assert isStackSlot(result);
                     if (compressed) {
-                        masm.movl((AMD64Address) crb.asAddress(result), input.asInt());
+                        if (isImmutable && generatePIC) {
+                            throw GraalInternalError.shouldNotReachHere("Unsupported operation offset(%rip) -> mem (mem -> mem)");
+                        } else {
+                            masm.movl((AMD64Address) crb.asAddress(result), input.asInt());
+                        }
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                     }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Fri Dec 12 20:29:35 2014 +0100
@@ -1228,10 +1228,10 @@
         int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int);
         if (regNumber >= HSAIL.s0.number && regNumber <= HSAIL.s31.number) {
             long offset = config.hsailFrameHeaderSize + intSize * (regNumber - HSAIL.s0.number);
-            location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
+            location = ConstantLocationNode.create(FINAL_LOCATION, offset, hostGraph);
         } else if (regNumber >= HSAIL.d0.number && regNumber <= HSAIL.d15.number) {
             long offset = config.hsailFrameHeaderSize + intSize * numSRegs + longSize * (regNumber - HSAIL.d0.number);
-            location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
+            location = ConstantLocationNode.create(FINAL_LOCATION, offset, hostGraph);
         } else {
             throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber);
         }
@@ -1246,7 +1246,7 @@
             int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long);
             int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int);
             long offset = config.hsailFrameHeaderSize + (intSize * numSRegs) + (longSize * numDRegs) + HSAIL.getStackOffsetStart(slot, slotSizeInBits);
-            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
+            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, offset, hostGraph);
             ValueNode valueNode = hostGraph.unique(FloatingReadNode.create(hsailFrame, location, null, StampFactory.forKind(valueKind)));
             return valueNode;
         } else {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java	Fri Dec 12 20:29:35 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.ptx;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -51,7 +52,7 @@
         }
     }
 
-    public ValueNode reconstructArrayIndex(LocationNode location) {
+    public ValueNode reconstructArrayIndex(Kind elementKind, LocationNode location) {
         throw GraalInternalError.unimplemented();
     }
 }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Fri Dec 12 20:29:35 2014 +0100
@@ -210,7 +210,7 @@
             int index = 0;
             for (int slot : objectSlots) {
                 int offset = slot * wordSize;
-                LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, index * intSize, getGraph());
+                LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, index * intSize, getGraph());
                 append(WriteNode.create(objectParametersOffsets, ConstantNode.forInt(offset, getGraph()), location, BarrierType.NONE, false));
                 index++;
             }
@@ -233,12 +233,12 @@
         for (javaParametersIndex = 0; javaParametersIndex < javaParameters.length; javaParametersIndex++) {
             ParameterNode javaParameter = javaParameters[javaParametersIndex];
             int javaParameterOffset = javaParameterOffsetsInKernelParametersBuffer[javaParametersIndex];
-            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, javaParameter.getKind(), javaParameterOffset, getGraph());
+            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, javaParameterOffset, getGraph());
             append(WriteNode.create(buf, javaParameter, location, BarrierType.NONE, false));
             updateDimArg(method, sig, sigIndex++, args, javaParameter);
         }
         if (returnKind != Kind.Void) {
-            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, bufSize - wordSize, getGraph());
+            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, bufSize - wordSize, getGraph());
             append(WriteNode.create(buf, nullWord, location, BarrierType.NONE, false));
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Fri Dec 12 20:29:35 2014 +0100
@@ -31,6 +31,7 @@
 
 import java.lang.reflect.*;
 import java.util.*;
+import java.util.function.*;
 
 import sun.misc.*;
 
@@ -41,7 +42,6 @@
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.remote.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -80,13 +80,17 @@
         }
     }
 
+    private static Predicate<Void> runtimeAccessCheck;
+
     /**
-     * Checks that all accesses to a {@link HotSpotGraalRuntimeProvider} within a replay context are
-     * through references to a captured {@link HotSpotGraalRuntimeProvider}, not through the static
-     * {@link HotSpotGraalRuntimeProvider} instance of the runtime hosting the replay.
+     * Sets a predicate which will be used to assert a valid calling context for a call to
+     * {@link #runtime()}. This is useful for verifying execution scopes that should not make a
+     * static access to {@link HotSpotGraalRuntime}. Such scopes are responsible for resetting the
+     * predicate to null.
      */
-    public static boolean checkRuntimeAccess() {
-        return Context.assertInLocal("Cannot access HotSpotGraalRuntime statically in replay/remote context");
+    public static void setRuntimeAccessCheck(Predicate<Void> predicate) {
+        assert runtimeAccessCheck == null || predicate == null : "at most once runtime access check can be active";
+        runtimeAccessCheck = predicate;
     }
 
     /**
@@ -94,7 +98,7 @@
      */
     public static HotSpotGraalRuntime runtime() {
         assert instance != null;
-        assert checkRuntimeAccess();
+        assert runtimeAccessCheck == null || runtimeAccessCheck.test(null);
         return instance;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Fri Dec 12 20:29:35 2014 +0100
@@ -127,6 +127,14 @@
         throw GraalInternalError.unimplemented();
     }
 
+    default Value emitCardTableShift() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    default Value emitCardTableAddress() {
+        throw GraalInternalError.unimplemented();
+    }
+
     /**
      * Gets a stack slot for a lock at a given lock nesting depth.
      */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java	Fri Dec 12 20:29:35 2014 +0100
@@ -34,7 +34,7 @@
 
     private static final long serialVersionUID = -1052183095979496819L;
 
-    private static final int BITS_PER_WORD = 3;
+    public static final int BITS_PER_WORD = 3;
 
     /**
      * Contains 3 bits per scalar register, and n*3 bits per n-word vector register (e.g., on a
@@ -167,6 +167,14 @@
         }
     }
 
+    public BitSet getFrameMap() {
+        return (BitSet) frameRefMap.clone();
+    }
+
+    public BitSet getRegisterMap() {
+        return (BitSet) registerRefMap.clone();
+    }
+
     // clear
 
     private static void clearOop(BitSet map, int startIdx, LIRKind kind) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Dec 12 20:29:35 2014 +0100
@@ -74,7 +74,29 @@
         oopEncoding = new CompressEncoding(narrowOopBase, narrowOopShift, logMinObjAlignment());
         klassEncoding = new CompressEncoding(narrowKlassBase, narrowKlassShift, logKlassAlignment);
 
+        codeCacheLowBoundary = unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceLowBoundaryOffset);
+        codeCacheHighBoundary = unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceHighBoundaryOffset);
+
+        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;
+            cardtableStartAddress = base;
+            cardtableShift = cardTableModRefBSCardShift;
+        } else if ((kind == barrierSetModRef) || (kind == barrierSetOther)) {
+            // No post barriers
+            cardtableStartAddress = 0;
+            cardtableShift = 0;
+        } else {
+            cardtableStartAddress = -1;
+            cardtableShift = -1;
+        }
+
+        inlineCacheMissStub = inlineCacheMissBlob + unsafe.getInt(inlineCacheMissBlob + codeBlobCodeOffsetOffset);
+
         assert check();
+        assert HotSpotVMConfigVerifier.check();
     }
 
     /**
@@ -1205,32 +1227,21 @@
     @HotSpotVMValue(expression = "(jbyte)CardTableModRefBS::dirty_card_val()") @Stable public byte dirtyCardValue;
     @HotSpotVMValue(expression = "(jbyte)G1SATBCardTableModRefBS::g1_young_card_val()") @Stable public byte g1YoungCardValue;
 
+    private final long cardtableStartAddress;
+    private final int cardtableShift;
+
     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 (cardtableStartAddress == -1) {
+            throw GraalInternalError.shouldNotReachHere();
         }
-        if ((kind == barrierSetModRef) || (kind == barrierSetOther)) {
-            // No post barriers
-            return 0;
-        }
-        throw GraalInternalError.shouldNotReachHere("kind: " + kind);
+        return cardtableStartAddress;
     }
 
     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 (cardtableShift == -1) {
+            throw GraalInternalError.shouldNotReachHere();
         }
-        if ((kind == barrierSetModRef) || (kind == barrierSetOther)) {
-            // No post barriers
-            return 0;
-        }
-        throw GraalInternalError.shouldNotReachHere("kind: " + kind);
+        return cardtableShift;
     }
 
     @HotSpotVMField(name = "os::_polling_page", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long safepointPollingAddress;
@@ -1367,8 +1378,10 @@
     @HotSpotVMField(name = "CodeBlob::_code_offset", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable private int codeBlobCodeOffsetOffset;
     @HotSpotVMField(name = "SharedRuntime::_ic_miss_blob", type = "RuntimeStub*", get = HotSpotVMField.Type.VALUE) @Stable private long inlineCacheMissBlob;
 
+    private final long inlineCacheMissStub;
+
     public long inlineCacheMissStub() {
-        return inlineCacheMissBlob + unsafe.getInt(inlineCacheMissBlob + codeBlobCodeOffsetOffset);
+        return inlineCacheMissStub;
     }
 
     @HotSpotVMField(name = "CodeCache::_heap", type = "CodeHeap*", get = HotSpotVMField.Type.VALUE) @Stable private long codeCacheHeap;
@@ -1376,18 +1389,21 @@
     @HotSpotVMField(name = "VirtualSpace::_low_boundary", type = "char*", get = HotSpotVMField.Type.OFFSET) @Stable private int virtualSpaceLowBoundaryOffset;
     @HotSpotVMField(name = "VirtualSpace::_high_boundary", type = "char*", get = HotSpotVMField.Type.OFFSET) @Stable private int virtualSpaceHighBoundaryOffset;
 
+    private final long codeCacheLowBoundary;
+    private final long codeCacheHighBoundary;
+
     /**
      * @return CodeCache::_heap-&gt;_memory._low_boundary
      */
     public long codeCacheLowBoundary() {
-        return unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceLowBoundaryOffset);
+        return codeCacheLowBoundary;
     }
 
     /**
      * @return CodeCache::_heap-&gt;_memory._high_boundary
      */
     public long codeCacheHighBoundary() {
-        return unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceHighBoundaryOffset);
+        return codeCacheHighBoundary;
     }
 
     @HotSpotVMField(name = "StubRoutines::_aescrypt_encryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptEncryptBlockStub;
@@ -1538,6 +1554,8 @@
     @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_NEAR") @Stable public int codeInstallerMarkIdPollReturnNear;
     @HotSpotVMConstant(name = "CodeInstaller::POLL_FAR") @Stable public int codeInstallerMarkIdPollFar;
     @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_FAR") @Stable public int codeInstallerMarkIdPollReturnFar;
+    @HotSpotVMConstant(name = "CodeInstaller::CARD_TABLE_SHIFT") @Stable public int codeInstallerMarkIdCardTableShift;
+    @HotSpotVMConstant(name = "CodeInstaller::CARD_TABLE_ADDRESS") @Stable public int codeInstallerMarkIdCardTableAddress;
     @HotSpotVMConstant(name = "CodeInstaller::INVOKE_INVALID") @Stable public int codeInstallerMarkIdInvokeInvalid;
 
     public boolean check() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfigVerifier.java	Fri Dec 12 20:29:35 2014 +0100
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2014, 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 static java.lang.String.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.compiler.common.*;
+
+import jdk.internal.org.objectweb.asm.*;
+import jdk.internal.org.objectweb.asm.Type;
+import sun.misc.*;
+
+/**
+ * A {@link ClassVisitor} that verifies {@link HotSpotVMConfig} does not access {@link Unsafe} from
+ * any of its non-static, non-constructor methods. This ensures that a deserialized
+ * {@link HotSpotVMConfig} object does not perform any unsafe reads on addresses that are only valid
+ * in the context in which the object was serialized. Note that this does not catch cases where a
+ * client uses an address stored in a {@link HotSpotVMConfig} field.
+ */
+final class HotSpotVMConfigVerifier extends ClassVisitor {
+
+    public static boolean check() {
+        Class<?> cls = HotSpotVMConfig.class;
+        String classFilePath = "/" + cls.getName().replace('.', '/') + ".class";
+        try {
+            InputStream classfile = cls.getResourceAsStream(classFilePath);
+            ClassReader cr = new ClassReader(Objects.requireNonNull(classfile, "Could not find class file for " + cls.getName()));
+            ClassVisitor cv = new HotSpotVMConfigVerifier();
+            cr.accept(cv, 0);
+            return true;
+        } catch (IOException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    /**
+     * Source file context for error reporting.
+     */
+    String sourceFile = null;
+
+    /**
+     * Line number for error reporting.
+     */
+    int lineNo = -1;
+
+    private static Class<?> resolve(String name) {
+        try {
+            return Class.forName(name.replace('/', '.'));
+        } catch (ClassNotFoundException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    HotSpotVMConfigVerifier() {
+        super(Opcodes.ASM5);
+    }
+
+    @Override
+    public void visitSource(String source, String debug) {
+        this.sourceFile = source;
+    }
+
+    void verify(boolean condition, String message) {
+        if (!condition) {
+            error(message);
+        }
+    }
+
+    void error(String message) {
+        String errorMessage = format("%s:%d: %s is not allowed in the context of compilation replay. The unsafe access should be moved into the %s constructor and the result cached in a field",
+                        sourceFile, lineNo, message, HotSpotVMConfig.class.getSimpleName());
+        throw new InternalError(errorMessage);
+
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) {
+        if (!Modifier.isStatic(access) && Modifier.isPublic(access) && !name.equals("<init>")) {
+            return new MethodVisitor(Opcodes.ASM5) {
+
+                @Override
+                public void visitLineNumber(int line, Label start) {
+                    lineNo = line;
+                }
+
+                private Executable resolveMethod(String owner, String methodName, String methodDesc) {
+                    Class<?> declaringClass = resolve(owner);
+                    while (declaringClass != null) {
+                        if (methodName.equals("<init>")) {
+                            for (Constructor<?> c : declaringClass.getDeclaredConstructors()) {
+                                if (methodDesc.equals(Type.getConstructorDescriptor(c))) {
+                                    return c;
+                                }
+                            }
+                        } else {
+                            Type[] argumentTypes = Type.getArgumentTypes(methodDesc);
+                            for (Method m : declaringClass.getDeclaredMethods()) {
+                                if (m.getName().equals(methodName)) {
+                                    if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) {
+                                        if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) {
+                                            return m;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        declaringClass = declaringClass.getSuperclass();
+                    }
+                    throw new NoSuchMethodError(owner + "." + methodName + methodDesc);
+                }
+
+                /**
+                 * Checks whether a given method is allowed to be called.
+                 */
+                private boolean checkInvokeTarget(Executable method) {
+                    if (method.getDeclaringClass().equals(Unsafe.class)) {
+                        return false;
+                    }
+                    return true;
+                }
+
+                @Override
+                public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) {
+                    Executable callee = resolveMethod(owner, methodName, methodDesc);
+                    verify(checkInvokeTarget(callee), "invocation of " + callee);
+                }
+            };
+        } else {
+            return null;
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Fri Dec 12 20:29:35 2014 +0100
@@ -383,9 +383,9 @@
         if (index >= config.graalCountersSize) {
             throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")");
         }
-        ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, wordKind, config.graalCountersThreadOffset, graph);
+        ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, config.graalCountersThreadOffset, graph);
         ReadNode readArray = graph.add(ReadNode.create(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE));
-        ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
+        ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
         ReadNode read = graph.add(ReadNode.create(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE));
         AddNode add = graph.unique(AddNode.create(read, counter.getIncrement()));
         WriteNode write = graph.add(WriteNode.create(readArray, add, location, BarrierType.NONE));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri Dec 12 20:29:35 2014 +0100
@@ -198,11 +198,11 @@
                     Kind wordKind = runtime.getTarget().wordKind;
                     ValueNode hub = createReadHub(graph, receiver, receiverNullCheck);
 
-                    ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod, receiverType);
+                    ReadNode metaspaceMethod = createReadVirtualMethod(graph, hub, hsMethod, receiverType);
                     // We use LocationNode.ANY_LOCATION for the reads that access the
                     // compiled code entry as HotSpot does not guarantee they are final
                     // values.
-                    ReadNode compiledEntry = graph.add(ReadNode.create(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, runtime.getConfig().methodCompiledEntryOffset, graph),
+                    ReadNode compiledEntry = graph.add(ReadNode.create(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, runtime.getConfig().methodCompiledEntryOffset, graph),
                                     StampFactory.forKind(wordKind), BarrierType.NONE));
 
                     loweredCallTarget = graph.add(HotSpotIndirectCallTargetNode.create(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
@@ -254,8 +254,7 @@
 
     @Override
     protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor) {
-        Kind wordKind = runtime.getTarget().wordKind;
-        LocationNode location = ConstantLocationNode.create(OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph);
+        LocationNode location = ConstantLocationNode.create(OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION, runtime.getConfig().arrayClassElementOffset, graph);
         /*
          * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass
          * is an object class, which might not be the case in other parts of the compiled method.
@@ -273,15 +272,15 @@
         }
     }
 
-    private void lowerLoadMethodNode(LoadMethodNode loadMethodNode) {
+    private static void lowerLoadMethodNode(LoadMethodNode loadMethodNode) {
         StructuredGraph graph = loadMethodNode.graph();
         HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) loadMethodNode.getMethod();
-        ReadNode metaspaceMethod = createReadVirtualMethod(graph, runtime.getTarget().wordKind, loadMethodNode.getHub(), method, loadMethodNode.getReceiverType());
+        ReadNode metaspaceMethod = createReadVirtualMethod(graph, loadMethodNode.getHub(), method, loadMethodNode.getReceiverType());
         graph.replaceFixed(loadMethodNode, metaspaceMethod);
     }
 
     private void lowerStoreHubNode(StoreHubNode storeHub, StructuredGraph graph) {
-        WriteNode hub = createWriteHub(graph, runtime.getTarget().wordKind, storeHub.getObject(), storeHub.getValue());
+        WriteNode hub = createWriteHub(graph, storeHub.getObject(), storeHub.getValue());
         graph.replaceFixed(storeHub, hub);
     }
 
@@ -314,7 +313,7 @@
             for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
                 int size = HIRFrameStateBuilder.stackSlots(osrLocal.getKind());
                 int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
-                IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.getKind(), offset, ConstantNode.forLong(0, graph), graph, 1);
+                IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, offset, ConstantNode.forLong(0, graph), graph, 1);
                 ReadNode load = graph.add(ReadNode.create(buffer, location, osrLocal.stamp(), BarrierType.NONE));
                 osrLocal.replaceAndDelete(load);
                 graph.addBeforeFixed(migrationEnd, load);
@@ -390,24 +389,23 @@
         return false;
     }
 
-    private static ReadNode createReadVirtualMethod(StructuredGraph graph, Kind wordKind, ValueNode hub, HotSpotResolvedJavaMethod method, ResolvedJavaType receiverType) {
-        return createReadVirtualMethod(graph, wordKind, hub, method.vtableEntryOffset(receiverType));
+    private static ReadNode createReadVirtualMethod(StructuredGraph graph, ValueNode hub, HotSpotResolvedJavaMethod method, ResolvedJavaType receiverType) {
+        return createReadVirtualMethod(graph, hub, method.vtableEntryOffset(receiverType));
     }
 
-    private static ReadNode createReadVirtualMethod(StructuredGraph graph, Kind wordKind, ValueNode hub, int vtableEntryOffset) {
+    private static ReadNode createReadVirtualMethod(StructuredGraph graph, ValueNode hub, int vtableEntryOffset) {
         assert vtableEntryOffset > 0;
         // We use LocationNode.ANY_LOCATION for the reads that access the vtable
         // entry as HotSpot does not guarantee that this is a final value.
         Stamp methodStamp = MethodPointerStamp.method();
-        ReadNode metaspaceMethod = graph.add(ReadNode.create(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), methodStamp, BarrierType.NONE));
+        ReadNode metaspaceMethod = graph.add(ReadNode.create(hub, ConstantLocationNode.create(ANY_LOCATION, vtableEntryOffset, graph), methodStamp, BarrierType.NONE));
         return metaspaceMethod;
     }
 
     @Override
     protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard) {
-        Kind wordKind = target.wordKind;
         HotSpotVMConfig config = runtime.getConfig();
-        LocationNode location = ConstantLocationNode.create(HUB_LOCATION, wordKind, config.hubOffset, graph);
+        LocationNode location = ConstantLocationNode.create(HUB_LOCATION, config.hubOffset, graph);
         assert !object.isConstant() || object.isNullConstant();
 
         KlassPointerStamp hubStamp = KlassPointerStamp.klassNonNull();
@@ -423,9 +421,9 @@
         }
     }
 
-    private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) {
+    private WriteNode createWriteHub(StructuredGraph graph, ValueNode object, ValueNode value) {
         HotSpotVMConfig config = runtime.getConfig();
-        LocationNode location = ConstantLocationNode.create(HUB_WRITE_LOCATION, wordKind, config.hubOffset, graph);
+        LocationNode location = ConstantLocationNode.create(HUB_WRITE_LOCATION, config.hubOffset, graph);
         assert !object.isConstant() || object.isNullConstant();
 
         ValueNode writeValue = value;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Fri Dec 12 20:29:35 2014 +0100
@@ -80,7 +80,9 @@
         POLL_NEAR(config().codeInstallerMarkIdPollNear),
         POLL_RETURN_NEAR(config().codeInstallerMarkIdPollReturnNear),
         POLL_FAR(config().codeInstallerMarkIdPollFar),
-        POLL_RETURN_FAR(config().codeInstallerMarkIdPollReturnFar);
+        POLL_RETURN_FAR(config().codeInstallerMarkIdPollReturnFar),
+        CARD_TABLE_SHIFT(config().codeInstallerMarkIdCardTableShift),
+        CARD_TABLE_ADDRESS(config().codeInstallerMarkIdCardTableAddress);
 
         private final int value;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstantImpl.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstantImpl.java	Fri Dec 12 20:29:35 2014 +0100
@@ -25,7 +25,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.remote.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 
 public final class HotSpotMetaspaceConstantImpl extends PrimitiveConstant implements HotSpotMetaspaceConstant, VMConstant, Remote {
@@ -47,7 +46,6 @@
         super(kind, primitive);
         this.metaspaceObject = metaspaceObject;
         this.compressed = compressed;
-        assert Context.assertInLocal("Should not create metaspace constants here");
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java	Fri Dec 12 20:29:35 2014 +0100
@@ -28,7 +28,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.remote.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 
@@ -96,7 +95,6 @@
         assert stableDimension == 0 || (object != null && object.getClass().isArray());
         assert stableDimension >= 0 && stableDimension <= 255;
         assert !isDefaultStable || stableDimension > 0;
-        assert Context.assertInLocal("Should not create object constants here");
     }
 
     private HotSpotObjectConstantImpl(Object object, boolean compressed) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Fri Dec 12 20:29:35 2014 +0100
@@ -120,7 +120,7 @@
                 int displacement = runtime().getArrayBaseOffset(arrayElementKind);
                 ConstantNode index = ConstantNode.forInt(0, g);
                 int indexScaling = runtime().getArrayIndexScale(arrayElementKind);
-                IndexedLocationNode locationNode = IndexedLocationNode.create(locationIdentity, arrayElementKind, displacement, index, g, indexScaling);
+                IndexedLocationNode locationNode = IndexedLocationNode.create(locationIdentity, displacement, index, g, indexScaling);
                 Stamp wordStamp = StampFactory.forKind(providers.getCodeCache().getTarget().wordKind);
                 ComputeAddressNode arrayAddress = g.unique(ComputeAddressNode.create(boxedElement, locationNode, wordStamp));
                 args.add(arrayAddress);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Fri Dec 12 20:29:35 2014 +0100
@@ -70,7 +70,7 @@
                 Constant klass;
                 LocationNode location;
                 if (type instanceof HotSpotResolvedObjectType) {
-                    location = ConstantLocationNode.create(CLASS_MIRROR_LOCATION, Kind.Object, classMirrorOffset, graph);
+                    location = ConstantLocationNode.create(CLASS_MIRROR_LOCATION, classMirrorOffset, graph);
                     klass = ((HotSpotResolvedObjectType) type).klass();
                 } else {
                     /*
@@ -91,7 +91,7 @@
                     if (typeField == null) {
                         throw new GraalInternalError("Can't find TYPE field in class");
                     }
-                    location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Object, typeField.offset(), graph);
+                    location = ConstantLocationNode.create(FINAL_LOCATION, typeField.offset(), graph);
                 }
                 ConstantNode klassNode = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), klass, metaAccess, graph);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableAddressNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 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.replacements;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo
+public class CardTableAddressNode extends FloatingNode implements LIRLowerable {
+
+    public static CardTableAddressNode create() {
+        return new CardTableAddressNode();
+    }
+
+    protected CardTableAddressNode() {
+        super(StampFactory.forKind(Kind.Long));
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool generator) {
+        Value res = ((HotSpotLIRGenerator) generator.getLIRGeneratorTool()).emitCardTableAddress();
+        generator.setResult(this, res);
+    }
+
+    @NodeIntrinsic
+    public static native long cardTableAddress();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableShiftNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 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.replacements;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo
+public class CardTableShiftNode extends FloatingNode implements LIRLowerable {
+
+    public static CardTableShiftNode create() {
+        return new CardTableShiftNode();
+    }
+
+    protected CardTableShiftNode() {
+        super(StampFactory.intValue());
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool generator) {
+        Value res = ((HotSpotLIRGenerator) generator.getLIRGeneratorTool()).emitCardTableShift();
+        generator.setResult(this, res);
+    }
+
+    @NodeIntrinsic
+    public static native int cardTableShift();
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -98,7 +98,7 @@
             return;
         }
 
-        LocationNode location = ConstantLocationNode.create(CLASS_KLASS_LOCATION, runtime.getTarget().wordKind, runtime.getConfig().klassOffset, graph());
+        LocationNode location = ConstantLocationNode.create(CLASS_KLASS_LOCATION, runtime.getConfig().klassOffset, graph());
         assert !clazz.isConstant();
         FloatingReadNode read = graph().unique(FloatingReadNode.create(clazz, location, null, stamp(), getGuard(), BarrierType.NONE));
         graph().replaceFloating(this, read);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri Dec 12 20:29:35 2014 +0100
@@ -810,6 +810,16 @@
     public static native int identityHashCode(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
 
     @Fold
+    public static boolean isImmutableCode() {
+        return GraalOptions.ImmutableCode.getValue();
+    }
+
+    @Fold
+    public static boolean generatePIC() {
+        return GraalOptions.GeneratePIC.getValue();
+    }
+
+    @Fold
     public static int verifiedEntryPointOffset() {
         return config().nmethodEntryOffset;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -81,7 +81,7 @@
             return;
         }
 
-        LocationNode location = ConstantLocationNode.create(CLASS_MIRROR_LOCATION, Kind.Object, config.classMirrorOffset, graph());
+        LocationNode location = ConstantLocationNode.create(CLASS_MIRROR_LOCATION, config.classMirrorOffset, graph());
         assert !hub.isConstant();
         FloatingReadNode read = graph().unique(FloatingReadNode.create(hub, location, null, stamp(), getGuard(), BarrierType.NONE));
         graph().replaceFloating(this, read);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -117,7 +117,7 @@
         if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) {
             return;
         }
-        LocationNode location = ConstantLocationNode.create(KLASS_LAYOUT_HELPER_LOCATION, Kind.Int, config.klassLayoutHelperOffset, graph());
+        LocationNode location = ConstantLocationNode.create(KLASS_LAYOUT_HELPER_LOCATION, config.klassLayoutHelperOffset, graph());
         assert !klass.isConstant();
         graph().replaceFloating(this, graph().unique(FloatingReadNode.create(klass, location, null, stamp(), getGuard(), BarrierType.NONE)));
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Fri Dec 12 20:29:35 2014 +0100
@@ -77,13 +77,15 @@
             oop = Word.fromObject(fixedObject);
         }
         serialWriteBarrierCounter.inc();
-        Word base = (Word) oop.unsignedShiftRight(cardTableShift());
-        long startAddress = cardTableStart();
+        int cardTableShift = (isImmutableCode() && generatePIC()) ? CardTableShiftNode.cardTableShift() : cardTableShift();
+        long cardTableAddress = (isImmutableCode() && generatePIC()) ? CardTableAddressNode.cardTableAddress() : cardTableStart();
+        Word base = (Word) oop.unsignedShiftRight(cardTableShift);
+        long startAddress = cardTableAddress;
         int displacement = 0;
         if (((int) startAddress) == startAddress) {
             displacement = (int) startAddress;
         } else {
-            base = base.add(Word.unsigned(cardTableStart()));
+            base = base.add(Word.unsigned(cardTableAddress));
         }
         base.writeByte(displacement, (byte) 0, GC_CARD_LOCATION);
     }
@@ -481,7 +483,7 @@
     public static void validateObject(Object parent, Object child) {
         if (verifyOops() && child != null && !validateOop(VALIDATE_OBJECT, parent, child)) {
             log(true, "Verification ERROR, Parent: %p Child: %p\n", Word.fromObject(parent).rawValue(), Word.fromObject(child).rawValue());
-            DirectObjectStoreNode.storeObject(null, 0, 0, null, LocationIdentity.ANY_LOCATION);
+            DirectObjectStoreNode.storeObject(null, 0, 0, null, LocationIdentity.ANY_LOCATION, Kind.Object);
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -111,7 +111,7 @@
     private ValueNode computeBase(ValueNode base, ValueNode pos) {
         FixedWithNextNode basePtr = graph().add(GetObjectAddressNode.create(base));
         graph().addBeforeFixed(this, basePtr);
-        ValueNode loc = IndexedLocationNode.create(getLocationIdentity(), elementKind, runtime.getArrayBaseOffset(elementKind), pos, graph(), runtime.getArrayIndexScale(elementKind));
+        ValueNode loc = IndexedLocationNode.create(getLocationIdentity(), runtime.getArrayBaseOffset(elementKind), pos, graph(), runtime.getArrayIndexScale(elementKind));
         return graph().unique(ComputeAddressNode.create(basePtr, loc, StampFactory.forKind(Kind.Long)));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -98,7 +98,7 @@
     private ValueNode computeBase(ValueNode base, ValueNode pos) {
         FixedWithNextNode basePtr = graph().add(GetObjectAddressNode.create(base));
         graph().addBeforeFixed(this, basePtr);
-        ValueNode loc = IndexedLocationNode.create(getLocationIdentity(), Kind.Object, runtime.getArrayBaseOffset(Kind.Object), pos, graph(), runtime.getArrayIndexScale(Kind.Object));
+        ValueNode loc = IndexedLocationNode.create(getLocationIdentity(), runtime.getArrayBaseOffset(Kind.Object), pos, graph(), runtime.getArrayIndexScale(Kind.Object));
         return graph().unique(ComputeAddressNode.create(basePtr, loc, StampFactory.forKind(Kind.Long)));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java	Fri Dec 12 20:29:35 2014 +0100
@@ -207,13 +207,13 @@
             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, arrayLocation);
-                DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind));
+                DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind), kind);
             }
         } 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, arrayLocation);
-                DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind));
+                DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind), kind);
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Fri Dec 12 20:29:35 2014 +0100
@@ -135,7 +135,7 @@
          * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for
          * total size of the interpreter frames plus shadow page size. Bang one page at a time
          * because large sizes can bang beyond yellow and red zones.
-         *
+         * 
          * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository.
          */
         final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java	Fri Dec 12 20:29:35 2014 +0100
@@ -147,7 +147,7 @@
          * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for
          * total size of the interpreter frames plus shadow page size. Bang one page at a time
          * because large sizes can bang beyond yellow and red zones.
-         *
+         * 
          * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository.
          */
         final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java	Fri Dec 12 20:29:35 2014 +0100
@@ -130,13 +130,12 @@
 
                 case READ_KLASS_POINTER:
                     assert arguments.size() == 2 || arguments.size() == 3;
-                    Kind readKind = asKind(callTargetNode.returnType());
                     Stamp readStamp = KlassPointerStamp.klass();
                     LocationNode location;
                     if (arguments.size() == 2) {
-                        location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
+                        location = makeLocation(graph, arguments.get(1), ANY_LOCATION);
                     } else {
-                        location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
+                        location = makeLocation(graph, arguments.get(1), arguments.get(2));
                     }
                     replace(invoke, readKlassOp(graph, arguments.get(0), invoke, location, readStamp, operation.opcode()));
                     break;
@@ -150,9 +149,8 @@
     protected ValueNode readKlassOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, Stamp readStamp, HotspotOpcode op) {
         assert op == READ_KLASS_POINTER;
         final BarrierType barrier = BarrierType.NONE;
-        final boolean compressible = false;
 
-        JavaReadNode read = graph.add(JavaReadNode.create(base, location, readStamp, barrier, compressible));
+        ReadNode read = graph.add(ReadNode.create(base, location, readStamp, barrier));
         graph.addBeforeFixed(invoke.asNode(), read);
         /*
          * The read must not float outside its block otherwise it may float above an explicit zero
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java	Fri Dec 12 20:29:35 2014 +0100
@@ -102,8 +102,20 @@
     @Test
     public void run0() throws Throwable {
         runTest("testShortened", "7", 10);
+    }
+
+    @Test
+    public void run1() throws Throwable {
         runTest("testShortened", "-100", 10);
+    }
+
+    @Test
+    public void run2() throws Throwable {
         runTest("test", "7", 10);
+    }
+
+    @Test
+    public void run3() throws Throwable {
         runTest("test", "-100", 10);
     }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Fri Dec 12 20:29:35 2014 +0100
@@ -25,8 +25,8 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ta;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Trap;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -51,8 +51,7 @@
     }
 
     @Override
-    @SuppressWarnings("unused")
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-        new Trap(masm, ST_RESERVED_FOR_USER_0);
+        new Ta(ST_RESERVED_FOR_USER_0).emit(masm);
     }
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Fri Dec 12 20:29:35 2014 +0100
@@ -332,7 +332,7 @@
                  * VirtualState nodes contained in the old exit's state may be shared by other
                  * dominated VirtualStates. Those dominated virtual states need to see the
                  * proxy->phi update that are applied below.
-                 *
+                 * 
                  * We now update the original fragment's nodes accordingly:
                  */
                 originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node));
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Fri Dec 12 20:29:35 2014 +0100
@@ -24,8 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.cfg.*;
-import com.oracle.graal.compiler.common.remote.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
@@ -34,7 +34,7 @@
 
 public class LoopsData {
 
-    private Map<Loop<Block>, LoopEx> loopToEx = Context.newIdentityMap();
+    private Map<Loop<Block>, LoopEx> loopToEx = CollectionsFactory.newIdentityMap();
     private Map<LoopBeginNode, LoopEx> loopBeginToEx = Node.newIdentityMap();
     private ControlFlowGraph cfg;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import java.io.*;
 import java.util.function.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
@@ -38,9 +39,12 @@
 @NodeInfo
 public abstract class BinaryArithmeticNode<OP> extends BinaryNode implements ArithmeticLIRLowerable {
 
-    protected final Function<ArithmeticOpTable, BinaryOp<OP>> getOp;
+    protected interface SerializableBinaryFunction<T> extends Function<ArithmeticOpTable, BinaryOp<T>>, Serializable {
+    }
 
-    public BinaryArithmeticNode(Function<ArithmeticOpTable, BinaryOp<OP>> getOp, ValueNode x, ValueNode y) {
+    protected final SerializableBinaryFunction<OP> getOp;
+
+    public BinaryArithmeticNode(SerializableBinaryFunction<OP> getOp, ValueNode x, ValueNode y) {
         super(getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), y.stamp()), x, y);
         this.getOp = getOp;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import java.io.*;
 import java.util.function.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
@@ -38,14 +39,16 @@
 @NodeInfo
 public abstract class IntegerConvertNode<OP, REV> extends UnaryNode implements ConvertNode, ArithmeticLIRLowerable {
 
-    protected final Function<ArithmeticOpTable, IntegerConvertOp<OP>> getOp;
-    protected final Function<ArithmeticOpTable, IntegerConvertOp<REV>> getReverseOp;
+    protected final SerializableIntegerConvertFunction<OP> getOp;
+    protected final SerializableIntegerConvertFunction<REV> getReverseOp;
 
     protected final int inputBits;
     protected final int resultBits;
 
-    protected IntegerConvertNode(Function<ArithmeticOpTable, IntegerConvertOp<OP>> getOp, Function<ArithmeticOpTable, IntegerConvertOp<REV>> getReverseOp, int inputBits, int resultBits,
-                    ValueNode input) {
+    protected interface SerializableIntegerConvertFunction<T> extends Function<ArithmeticOpTable, IntegerConvertOp<T>>, Serializable {
+    }
+
+    protected IntegerConvertNode(SerializableIntegerConvertFunction<OP> getOp, SerializableIntegerConvertFunction<REV> getReverseOp, int inputBits, int resultBits, ValueNode input) {
         super(getOp.apply(ArithmeticOpTable.forStamp(input.stamp())).foldStamp(inputBits, resultBits, input.stamp()), input);
         this.getOp = getOp;
         this.getReverseOp = getReverseOp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -84,7 +84,7 @@
                 /*
                  * One of the two objects has identity, the other doesn't. In code, this looks like
                  * "Integer.valueOf(a) == new Integer(b)", which is always false.
-                 *
+                 * 
                  * In other words: an object created via valueOf can never be equal to one created
                  * by new in the same compilation unit.
                  */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import java.io.*;
 import java.util.function.*;
 
 import com.oracle.graal.compiler.common.type.*;
@@ -34,9 +35,12 @@
 @NodeInfo
 public abstract class UnaryArithmeticNode<OP> extends UnaryNode implements ArithmeticLIRLowerable {
 
-    protected final Function<ArithmeticOpTable, UnaryOp<OP>> getOp;
+    protected interface SerializableUnaryFunction<T> extends Function<ArithmeticOpTable, UnaryOp<T>>, Serializable {
+    }
 
-    protected UnaryArithmeticNode(Function<ArithmeticOpTable, UnaryOp<OP>> getOp, ValueNode value) {
+    protected final SerializableUnaryFunction<OP> getOp;
+
+    protected UnaryArithmeticNode(SerializableUnaryFunction<OP> getOp, ValueNode value) {
         super(getOp.apply(ArithmeticOpTable.forStamp(value.stamp())).foldStamp(value.stamp()), value);
         this.getOp = getOp;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -51,7 +51,7 @@
     }
 
     public static AddLocationNode create(LocationNode x, LocationNode y, Graph graph) {
-        assert x.getValueKind().equals(y.getValueKind()) && x.getLocationIdentity().equals(y.getLocationIdentity());
+        assert x.getLocationIdentity().equals(y.getLocationIdentity());
         return graph.unique(AddLocationNode.create(x, y));
     }
 
@@ -66,11 +66,6 @@
     }
 
     @Override
-    public Kind getValueKind() {
-        return getX().getValueKind();
-    }
-
-    @Override
     public LocationIdentity getLocationIdentity() {
         return getX().getLocationIdentity();
     }
@@ -88,7 +83,7 @@
             if (xIdx.getIndexScaling() == yIdx.getIndexScaling()) {
                 long displacement = xIdx.getDisplacement() + yIdx.getDisplacement();
                 ValueNode index = BinaryArithmeticNode.add(xIdx.getIndex(), yIdx.getIndex());
-                return IndexedLocationNode.create(getLocationIdentity(), getValueKind(), displacement, index, xIdx.getIndexScaling());
+                return IndexedLocationNode.create(getLocationIdentity(), displacement, index, xIdx.getIndexScaling());
             }
         }
         return this;
@@ -97,10 +92,10 @@
     private LocationNode canonical(ConstantLocationNode constant, LocationNode other) {
         if (other instanceof ConstantLocationNode) {
             ConstantLocationNode otherConst = (ConstantLocationNode) other;
-            return ConstantLocationNode.create(getLocationIdentity(), getValueKind(), otherConst.getDisplacement() + constant.getDisplacement());
+            return ConstantLocationNode.create(getLocationIdentity(), otherConst.getDisplacement() + constant.getDisplacement());
         } else if (other instanceof IndexedLocationNode) {
             IndexedLocationNode otherIdx = (IndexedLocationNode) other;
-            return IndexedLocationNode.create(getLocationIdentity(), getValueKind(), otherIdx.getDisplacement() + constant.getDisplacement(), otherIdx.getIndex(), otherIdx.getIndexScaling());
+            return IndexedLocationNode.create(getLocationIdentity(), otherIdx.getDisplacement() + constant.getDisplacement(), otherIdx.getIndex(), otherIdx.getIndexScaling());
         } else if (other instanceof AddLocationNode) {
             AddLocationNode otherAdd = (AddLocationNode) other;
             LocationNode newInner = otherAdd.canonical(constant, otherAdd.getX());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -36,32 +36,24 @@
 @NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}")
 public class ConstantLocationNode extends LocationNode {
 
-    protected final Kind valueKind;
     protected final LocationIdentity locationIdentity;
     protected final long displacement;
 
-    public static ConstantLocationNode create(LocationIdentity identity, Kind kind, long displacement, Graph graph) {
-        return graph.unique(ConstantLocationNode.create(identity, kind, displacement));
-    }
-
-    public static ConstantLocationNode create(LocationIdentity identity, Kind kind, long displacement) {
-        return new ConstantLocationNode(identity, kind, displacement);
+    public static ConstantLocationNode create(LocationIdentity identity, long displacement, Graph graph) {
+        return graph.unique(ConstantLocationNode.create(identity, displacement));
     }
 
-    protected ConstantLocationNode(LocationIdentity identity, Kind kind, long displacement) {
+    public static ConstantLocationNode create(LocationIdentity identity, long displacement) {
+        return new ConstantLocationNode(identity, displacement);
+    }
+
+    protected ConstantLocationNode(LocationIdentity identity, long displacement) {
         super(StampFactory.forVoid());
-        assert kind != Kind.Illegal && kind != Kind.Void;
-        this.valueKind = kind;
         this.locationIdentity = identity;
         this.displacement = displacement;
     }
 
     @Override
-    public Kind getValueKind() {
-        return valueKind;
-    }
-
-    @Override
     public LocationIdentity getLocationIdentity() {
         return locationIdentity;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -41,7 +41,6 @@
 @NodeInfo(nameTemplate = "IdxLoc {p#locationIdentity/s}")
 public class IndexedLocationNode extends LocationNode implements Canonicalizable {
 
-    protected final Kind valueKind;
     protected final LocationIdentity locationIdentity;
     protected final long displacement;
     @Input ValueNode index;
@@ -65,20 +64,18 @@
         return indexScaling;
     }
 
-    public static IndexedLocationNode create(LocationIdentity identity, Kind kind, long displacement, ValueNode index, Graph graph, int indexScaling) {
-        return graph.unique(IndexedLocationNode.create(identity, kind, displacement, index, indexScaling));
+    public static IndexedLocationNode create(LocationIdentity identity, long displacement, ValueNode index, Graph graph, int indexScaling) {
+        return graph.unique(IndexedLocationNode.create(identity, displacement, index, indexScaling));
     }
 
-    public static IndexedLocationNode create(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
-        return new IndexedLocationNode(identity, kind, displacement, index, indexScaling);
+    public static IndexedLocationNode create(LocationIdentity identity, long displacement, ValueNode index, int indexScaling) {
+        return new IndexedLocationNode(identity, displacement, index, indexScaling);
     }
 
-    protected IndexedLocationNode(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
+    protected IndexedLocationNode(LocationIdentity identity, long displacement, ValueNode index, int indexScaling) {
         super(StampFactory.forVoid());
         assert index != null;
         assert indexScaling != 0;
-        assert kind != Kind.Illegal && kind != Kind.Void;
-        this.valueKind = kind;
         this.locationIdentity = identity;
         this.index = index;
         this.displacement = displacement;
@@ -86,11 +83,6 @@
     }
 
     @Override
-    public Kind getValueKind() {
-        return valueKind;
-    }
-
-    @Override
     public LocationIdentity getLocationIdentity() {
         return locationIdentity;
     }
@@ -98,7 +90,7 @@
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (index.isConstant()) {
-            return ConstantLocationNode.create(getLocationIdentity(), getValueKind(), index.asJavaConstant().asLong() * indexScaling + displacement);
+            return ConstantLocationNode.create(getLocationIdentity(), index.asJavaConstant().asLong() * indexScaling + displacement);
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -36,23 +37,16 @@
 @NodeInfo
 public class JavaReadNode extends FixedAccessNode implements Lowerable, GuardingNode, Canonicalizable {
 
+    protected final Kind readKind;
     protected final boolean compressible;
 
-    public static JavaReadNode create(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
-        return new JavaReadNode(object, location, barrierType, compressible);
+    public static JavaReadNode create(Kind readKind, ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
+        return new JavaReadNode(readKind, object, location, barrierType, compressible);
     }
 
-    public static JavaReadNode create(ValueNode object, LocationNode location, Stamp readStamp, BarrierType barrierType, boolean compressible) {
-        return new JavaReadNode(object, location, readStamp, barrierType, compressible);
-    }
-
-    protected JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
-        super(object, location, StampFactory.forKind(location.getValueKind()), barrierType);
-        this.compressible = compressible;
-    }
-
-    protected JavaReadNode(ValueNode object, LocationNode location, Stamp readStamp, BarrierType barrierType, boolean compressible) {
-        super(object, location, readStamp, barrierType);
+    protected JavaReadNode(Kind readKind, ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
+        super(object, location, StampFactory.forKind(readKind), barrierType);
+        this.readKind = readKind;
         this.compressible = compressible;
     }
 
@@ -64,6 +58,10 @@
         return true;
     }
 
+    public Kind getReadKind() {
+        return readKind;
+    }
+
     public boolean isCompressible() {
         return compressible;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -33,14 +34,16 @@
 @NodeInfo
 public class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single {
 
+    protected final Kind writeKind;
     protected final boolean compressible;
 
-    public static JavaWriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
-        return new JavaWriteNode(object, value, location, barrierType, compressible, initialization);
+    public static JavaWriteNode create(Kind writeKind, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
+        return new JavaWriteNode(writeKind, object, value, location, barrierType, compressible, initialization);
     }
 
-    protected JavaWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
+    protected JavaWriteNode(Kind writeKind, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
         super(object, value, location, barrierType, initialization);
+        this.writeKind = writeKind;
         this.compressible = compressible;
     }
 
@@ -52,6 +55,10 @@
         return true;
     }
 
+    public Kind getWriteKind() {
+        return writeKind;
+    }
+
     public boolean isCompressible() {
         return compressible;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -49,11 +49,6 @@
     }
 
     /**
-     * Returns the kind of the accessed memory value.
-     */
-    public abstract Kind getValueKind();
-
-    /**
      * Returns the identity of the accessed memory location.
      */
     public abstract LocationIdentity getLocationIdentity();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -31,7 +32,6 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Reads an {@linkplain FixedAccessNode accessed} value.
@@ -171,17 +171,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        if (location() instanceof ConstantLocationNode) {
-            ConstantLocationNode constantLocation = (ConstantLocationNode) location();
-            State state = tool.getObjectState(object());
-            if (state != null && state.getState() == EscapeState.Virtual) {
-                VirtualObjectNode virtual = state.getVirtualObject();
-                int entryIndex = virtual.entryIndexForOffset(constantLocation.getDisplacement());
-                if (entryIndex != -1 && virtual.entryKind(entryIndex) == constantLocation.getValueKind()) {
-                    tool.replaceWith(state.getEntry(entryIndex));
-                }
-            }
-        }
+        throw GraalInternalError.shouldNotReachHere("unexpected ReadNode before PEA");
     }
 
     public boolean canNullCheck() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -23,12 +23,12 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.LocationNode.Location;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}.
@@ -79,18 +79,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        if (location() instanceof ConstantLocationNode) {
-            ConstantLocationNode constantLocation = (ConstantLocationNode) location();
-            State state = tool.getObjectState(object());
-            if (state != null && state.getState() == EscapeState.Virtual) {
-                VirtualObjectNode virtual = state.getVirtualObject();
-                int entryIndex = virtual.entryIndexForOffset(constantLocation.getDisplacement());
-                if (entryIndex != -1 && virtual.entryKind(entryIndex) == constantLocation.getValueKind()) {
-                    tool.setVirtualEntry(state, entryIndex, value(), false);
-                    tool.delete();
-                }
-            }
-        }
+        throw GraalInternalError.shouldNotReachHere("unexpected WriteNode before PEA");
     }
 
     public boolean canNullCheck() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -73,7 +73,7 @@
     }
 
     public void generate(NodeLIRBuilderTool gen) {
-        LocationNode location = IndexedLocationNode.create(getLocationIdentity(), delta.getKind(), 0, offset, graph(), 1);
+        LocationNode location = IndexedLocationNode.create(getLocationIdentity(), 0, offset, graph(), 1);
         Value address = location.generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(address, gen.operand(delta));
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringProvider.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringProvider.java	Fri Dec 12 20:29:35 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.spi;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -36,9 +37,10 @@
     /**
      * Reconstructs the array index from a location node that was created as a lowering of an
      * indexed access to an array.
-     * 
+     *
+     * @param elementKind the {@link Kind} of the array elements
      * @param location a location pointing to an element in an array
      * @return a node that gives the index of the element
      */
-    ValueNode reconstructArrayIndex(LocationNode location);
+    ValueNode reconstructArrayIndex(Kind elementKind, LocationNode location);
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Fri Dec 12 20:29:35 2014 +0100
@@ -24,10 +24,11 @@
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.graph.Graph.NodeEvent.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.remote.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Graph.NodeEventScope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -162,7 +163,7 @@
         if (updateExistingPhis) {
             for (MemoryPhiNode phi : merge.phis().filter(MemoryPhiNode.class)) {
                 if (existingPhis == null) {
-                    existingPhis = Context.newMap();
+                    existingPhis = CollectionsFactory.newMap();
                 }
                 phi.values().clear();
                 existingPhis.put(phi.getLocationIdentity(), phi);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java	Fri Dec 12 20:29:35 2014 +0100
@@ -33,11 +33,11 @@
 
 import java.util.Map;
 
-import static com.oracle.graal.compiler.common.GraalOptions.RelevanceCapForInlining;
 import static com.oracle.graal.phases.common.inlining.InliningPhase.Options.AlwaysInlineIntrinsics;
 
 public abstract class AbstractInliningPolicy implements InliningPolicy {
-
+    public static final float RelevanceCapForInlining = 1.0f;
+    public static final float CapInheritedRelevance = 1.0f;
     protected final Map<Invoke, Double> hints;
 
     public AbstractInliningPolicy(Map<Invoke, Double> hints) {
@@ -45,7 +45,7 @@
     }
 
     protected double computeMaximumSize(double relevance, int configuredMaximum) {
-        double inlineRatio = Math.min(RelevanceCapForInlining.getValue(), relevance);
+        double inlineRatio = Math.min(RelevanceCapForInlining, relevance);
         return configuredMaximum * inlineRatio;
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java	Fri Dec 12 20:29:35 2014 +0100
@@ -25,13 +25,12 @@
 import com.oracle.graal.api.meta.ResolvedJavaMethod;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.common.inlining.policy.*;
 import com.oracle.graal.phases.graph.FixedNodeProbabilityCache;
 
 import java.util.*;
 import java.util.function.ToDoubleFunction;
 
-import static com.oracle.graal.compiler.common.GraalOptions.CapInheritedRelevance;
-
 /**
  * <p>
  * A {@link CallsiteHolder} whose graph has been copied already and thus can be modified without
@@ -204,7 +203,7 @@
     }
 
     public double invokeRelevance(Invoke invoke) {
-        return Math.min(CapInheritedRelevance.getValue(), relevance) * computeInliningRelevance.getRelevance(invoke);
+        return Math.min(AbstractInliningPolicy.CapInheritedRelevance, relevance) * computeInliningRelevance.getRelevance(invoke);
     }
 
     @Override
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Fri Dec 12 20:29:35 2014 +0100
@@ -98,9 +98,9 @@
         if (!method.equals(curMethod) || !curDecorators.equals(decorators)) {
             cfgPrinter.printCompilation(method);
             TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile);
-            curMethod = method;
-            curDecorators = decorators;
         }
+        curMethod = method;
+        curDecorators = decorators;
         return true;
     }
 
@@ -206,6 +206,9 @@
     public void close() {
         if (cfgPrinter != null) {
             cfgPrinter.close();
+            cfgPrinter = null;
+            curDecorators = Collections.emptyList();
+            curMethod = null;
         }
     }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java	Fri Dec 12 20:29:35 2014 +0100
@@ -108,6 +108,8 @@
         try {
             printStream.close();
             fos.close();
+            printStream = null;
+            fos = null;
         } catch (IOException e) {
             throw new IllegalStateException(e);
         }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Fri Dec 12 20:29:35 2014 +0100
@@ -160,7 +160,7 @@
             final Graph graph = (Graph) object;
 
             if (printer != null) {
-                // Get all current RiResolvedMethod instances in the context.
+                // Get all current JavaMethod instances in the context.
                 List<String> inlineContext = getInlineContext();
 
                 // Reverse list such that inner method comes after outer method.
@@ -272,6 +272,7 @@
         }
         if (printer != null) {
             printer.close();
+            printer = null;
         }
     }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Fri Dec 12 20:29:35 2014 +0100
@@ -39,23 +39,23 @@
  *
  * <pre>
  *     HexCodeFile ::= Platform Delim HexCode Delim (OptionalSection Delim)*
- *
+ * 
  *     OptionalSection ::= Comment | OperandComment | JumpTable | LookupTable
- *
+ * 
  *     Platform ::= "Platform" ISA WordWidth
- *
+ * 
  *     HexCode ::= "HexCode" StartAddress HexDigits
- *
+ * 
  *     Comment ::= "Comment" Position String
- *
+ * 
  *     OperandComment ::= "OperandComment" Position String
- *
+ * 
  *     JumpTable ::= "JumpTable" Position EntrySize Low High
- *
+ * 
  *     LookupTable ::= "LookupTable" Position NPairs KeySize OffsetSize
- *
+ * 
  *     Position, EntrySize, Low, High, NPairs KeySize OffsetSize ::= int
- *
+ * 
  *     Delim := "&lt;||@"
  * </pre>
  *
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Fri Dec 12 20:29:35 2014 +0100
@@ -79,21 +79,21 @@
     @Test
     public void testWrite1() {
         for (Kind kind : KINDS) {
-            assertWrite(parseEager("write" + kind.name() + "1"), kind, true, ID);
+            assertWrite(parseEager("write" + kind.name() + "1"), true, ID);
         }
     }
 
     @Test
     public void testWrite2() {
         for (Kind kind : KINDS) {
-            assertWrite(parseEager("write" + kind.name() + "2"), kind, true, ID);
+            assertWrite(parseEager("write" + kind.name() + "2"), true, ID);
         }
     }
 
     @Test
     public void testWrite3() {
         for (Kind kind : KINDS) {
-            assertWrite(parseEager("write" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
+            assertWrite(parseEager("write" + kind.name() + "3"), true, LocationIdentity.ANY_LOCATION);
         }
     }
 
@@ -103,7 +103,6 @@
         Assert.assertEquals(graph.getParameter(0), read.object());
 
         IndexedLocationNode location = (IndexedLocationNode) read.location();
-        Assert.assertEquals(kind, location.getValueKind());
         Assert.assertEquals(locationIdentity, location.getLocationIdentity());
         Assert.assertEquals(1, location.getIndexScaling());
 
@@ -120,14 +119,13 @@
         Assert.assertEquals(read, ret.result());
     }
 
-    private static void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
+    private static void assertWrite(StructuredGraph graph, boolean indexConvert, LocationIdentity locationIdentity) {
         JavaWriteNode write = (JavaWriteNode) graph.start().next();
         Assert.assertEquals(graph.getParameter(2), write.value());
         Assert.assertEquals(graph.getParameter(0), write.object());
         Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci);
 
         IndexedLocationNode location = (IndexedLocationNode) write.location();
-        Assert.assertEquals(kind, location.getValueKind());
         Assert.assertEquals(locationIdentity, location.getLocationIdentity());
         Assert.assertEquals(1, location.getIndexScaling());
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Fri Dec 12 20:29:35 2014 +0100
@@ -85,21 +85,21 @@
     @Test
     public void testWrite1() {
         for (Kind kind : KINDS) {
-            assertWrite(parseEager("write" + kind.name() + "1"), kind, true, ID);
+            assertWrite(parseEager("write" + kind.name() + "1"), true, ID);
         }
     }
 
     @Test
     public void testWrite2() {
         for (Kind kind : KINDS) {
-            assertWrite(parseEager("write" + kind.name() + "2"), kind, true, ID);
+            assertWrite(parseEager("write" + kind.name() + "2"), true, ID);
         }
     }
 
     @Test
     public void testWrite3() {
         for (Kind kind : KINDS) {
-            assertWrite(parseEager("write" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
+            assertWrite(parseEager("write" + kind.name() + "3"), true, LocationIdentity.ANY_LOCATION);
         }
     }
 
@@ -114,7 +114,6 @@
         Assert.assertEquals(target.wordKind, cast.stamp().getStackKind());
 
         IndexedLocationNode location = (IndexedLocationNode) read.location();
-        Assert.assertEquals(kind, location.getValueKind());
         Assert.assertEquals(locationIdentity, location.getLocationIdentity());
         Assert.assertEquals(1, location.getIndexScaling());
 
@@ -131,7 +130,7 @@
         Assert.assertEquals(read, ret.result());
     }
 
-    private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
+    private void assertWrite(StructuredGraph graph, boolean indexConvert, LocationIdentity locationIdentity) {
         WordCastNode cast = (WordCastNode) graph.start().next();
 
         JavaWriteNode write = (JavaWriteNode) cast.next();
@@ -143,7 +142,6 @@
         Assert.assertEquals(target.wordKind, cast.stamp().getStackKind());
 
         IndexedLocationNode location = (IndexedLocationNode) write.location();
-        Assert.assertEquals(kind, location.getValueKind());
         Assert.assertEquals(locationIdentity, location.getLocationIdentity());
         Assert.assertEquals(1, location.getIndexScaling());
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Fri Dec 12 20:29:35 2014 +0100
@@ -211,7 +211,7 @@
     protected void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) {
         StructuredGraph graph = arrayLengthNode.graph();
         ValueNode array = arrayLengthNode.array();
-        ConstantLocationNode location = ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph);
+        ConstantLocationNode location = ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, arrayLengthOffset(), graph);
 
         ReadNode arrayLengthRead = graph.add(ReadNode.create(array, location, StampFactory.positiveInt(), BarrierType.NONE));
         arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool));
@@ -243,7 +243,7 @@
     protected void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) {
         StructuredGraph graph = n.graph();
         Kind valueKind = n.getValueKind();
-        LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1);
+        LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), 0, n.offset(), graph, 1);
 
         ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
 
@@ -312,7 +312,7 @@
 
     protected void lowerJavaReadNode(JavaReadNode read) {
         StructuredGraph graph = read.graph();
-        Kind valueKind = read.location().getValueKind();
+        Kind valueKind = read.getReadKind();
         Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible());
 
         ReadNode memoryRead = graph.add(ReadNode.create(read.object(), read.location(), loadStamp, read.getBarrierType()));
@@ -324,7 +324,7 @@
 
     protected void lowerJavaWriteNode(JavaWriteNode write) {
         StructuredGraph graph = write.graph();
-        Kind valueKind = write.location().getValueKind();
+        Kind valueKind = write.getWriteKind();
         ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible());
 
         WriteNode memoryWrite = graph.add(WriteNode.create(write.object(), value, write.location(), write.getBarrierType(), write.isInitialization()));
@@ -366,7 +366,6 @@
                         Kind entryKind = virtual.entryKind(i);
 
                         // Truffle requires some leniency in terms of what can be put where:
-                        Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind;
                         assert valueKind.getStackKind() == entryKind.getStackKind() ||
                                         (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode));
                         ConstantLocationNode location = null;
@@ -375,11 +374,11 @@
                             ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i);
                             long offset = fieldOffset(field);
                             if (offset >= 0) {
-                                location = ConstantLocationNode.create(initLocationIdentity(), accessKind, offset, graph);
+                                location = ConstantLocationNode.create(initLocationIdentity(), offset, graph);
                                 barrierType = fieldInitializationBarrier(entryKind);
                             }
                         } else {
-                            location = ConstantLocationNode.create(initLocationIdentity(), accessKind, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind), graph);
+                            location = ConstantLocationNode.create(initLocationIdentity(), arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind), graph);
                             barrierType = arrayInitializationBarrier(entryKind);
                         }
                         if (location != null) {
@@ -583,7 +582,7 @@
         int offset = fieldOffset(field);
         if (offset >= 0) {
             LocationIdentity loc = initialization ? initLocationIdentity() : field;
-            return ConstantLocationNode.create(loc, field.getKind(), offset, graph);
+            return ConstantLocationNode.create(loc, offset, graph);
         } else {
             return null;
         }
@@ -612,7 +611,7 @@
         ValueNode offset = offsetNode;
         if (offset.isConstant()) {
             long offsetValue = offset.asJavaConstant().asLong();
-            return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph());
+            return ConstantLocationNode.create(locationIdentity, offsetValue, offset.graph());
         }
 
         long displacement = 0;
@@ -673,12 +672,12 @@
             // If we were using sign extended values before restore the sign extension.
             offset = offset.graph().addOrUnique(SignExtendNode.create(offset, 64));
         }
-        return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling);
+        return IndexedLocationNode.create(locationIdentity, displacement, offset, offset.graph(), indexScaling);
     }
 
     public IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) {
         LocationIdentity loc = initialization ? initLocationIdentity() : NamedLocationIdentity.getArrayLocation(elementKind);
-        return IndexedLocationNode.create(loc, elementKind, arrayBaseOffset(elementKind), index, graph, arrayScalingFactor(elementKind));
+        return IndexedLocationNode.create(loc, arrayBaseOffset(elementKind), index, graph, arrayScalingFactor(elementKind));
     }
 
     protected GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
@@ -687,7 +686,7 @@
         ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection());
         if (arrayLength == null) {
             Stamp stamp = StampFactory.positiveInt();
-            ReadNode readArrayLength = graph.add(ReadNode.create(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE));
+            ReadNode readArrayLength = graph.add(ReadNode.create(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, arrayLengthOffset(), graph), stamp, BarrierType.NONE));
             graph.addBeforeFixed(n, readArrayLength);
             readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool));
             arrayLength = readArrayLength;
@@ -715,8 +714,7 @@
     }
 
     @Override
-    public ValueNode reconstructArrayIndex(LocationNode location) {
-        Kind elementKind = location.getValueKind();
+    public ValueNode reconstructArrayIndex(Kind elementKind, LocationNode location) {
         assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind));
 
         long base;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Dec 12 20:29:35 2014 +0100
@@ -315,10 +315,10 @@
             try {
                 Object[] args = new Object[constructor.getParameterCount()];
                 for (int i = 0; i < args.length; i++) {
-                    Object arg = snippetReflection.getSubstitutionGuardParameter(paramTypes[0]);
+                    Object arg = snippetReflection.getSubstitutionGuardParameter(paramTypes[i]);
                     if (arg != null) {
                         args[i] = arg;
-                    } else if (paramTypes[0].isInstance(target.arch)) {
+                    } else if (paramTypes[i].isInstance(target.arch)) {
                         args[i] = target.arch;
                     } else {
                         throw new GraalInternalError("Unsupported type %s in substitution guard constructor: %s", paramTypes[i].getName(), constructor);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Dec 12 20:29:35 2014 +0100
@@ -534,8 +534,9 @@
         }
     }
 
-    private static final Object UNUSED_PARAMETER = "DEAD PARAMETER";
-    private static final Object CONSTANT_PARAMETER = "CONSTANT";
+    // These values must be compared with equals() not '==' to support replay compilation.
+    private static final Object UNUSED_PARAMETER = "UNUSED_PARAMETER";
+    private static final Object CONSTANT_PARAMETER = "CONSTANT_PARAMETER";
 
     /**
      * Determines if any parameter of a given method is annotated with {@link ConstantParameter}.
@@ -905,7 +906,7 @@
                     }
                 }
             } else {
-                assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.getParameterName(i) + " -> " + parameter;
+                assert parameter.equals(CONSTANT_PARAMETER) || parameter.equals(UNUSED_PARAMETER) : "unexpected entry for parameter: " + args.info.getParameterName(i) + " -> " + parameter;
             }
         }
         return replacements;
@@ -1298,9 +1299,9 @@
             sep = ", ";
             if (value == null) {
                 buf.append("<null> ").append(name);
-            } else if (value == UNUSED_PARAMETER) {
+            } else if (value.equals(UNUSED_PARAMETER)) {
                 buf.append("<unused> ").append(name);
-            } else if (value == CONSTANT_PARAMETER) {
+            } else if (value.equals(CONSTANT_PARAMETER)) {
                 buf.append("<constant> ").append(name);
             } else if (value instanceof ParameterNode) {
                 ParameterNode param = (ParameterNode) value;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -42,30 +42,34 @@
     @Input ValueNode offset;
     protected final int displacement;
     protected final LocationIdentity locationIdentity;
+    protected final Kind storeKind;
 
-    public static DirectObjectStoreNode create(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity) {
-        return new DirectObjectStoreNode(object, displacement, offset, value, locationIdentity);
+    public static DirectObjectStoreNode create(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity, Kind storeKind) {
+        return new DirectObjectStoreNode(object, displacement, offset, value, locationIdentity, storeKind);
     }
 
-    protected DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity) {
+    protected DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity, Kind storeKind) {
         super(StampFactory.forVoid());
         this.object = object;
         this.value = value;
         this.offset = offset;
         this.displacement = displacement;
         this.locationIdentity = locationIdentity;
+        this.storeKind = storeKind;
     }
 
     @NodeIntrinsic
-    public static native void storeObject(Object obj, @ConstantNodeParameter int displacement, long offset, Object value, @ConstantNodeParameter LocationIdentity locationIdentity);
+    public static native void storeObject(Object obj, @ConstantNodeParameter int displacement, long offset, Object value, @ConstantNodeParameter LocationIdentity locationIdentity,
+                    @ConstantNodeParameter Kind storeKind);
 
     @NodeIntrinsic
-    public static native void storeLong(Object obj, @ConstantNodeParameter int displacement, long offset, long value, @ConstantNodeParameter LocationIdentity locationIdenity);
+    public static native void storeLong(Object obj, @ConstantNodeParameter int displacement, long offset, long value, @ConstantNodeParameter LocationIdentity locationIdenity,
+                    @ConstantNodeParameter Kind storeKind);
 
     @Override
     public void lower(LoweringTool tool) {
-        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, value.getKind(), displacement, offset, graph(), 1);
-        JavaWriteNode write = graph().add(JavaWriteNode.create(object, value, location, BarrierType.NONE, value.getKind() == Kind.Object, false));
+        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, displacement, offset, graph(), 1);
+        JavaWriteNode write = graph().add(JavaWriteNode.create(storeKind, object, value, location, BarrierType.NONE, storeKind == Kind.Object, false));
         graph().replaceFixedWithFixed(this, write);
 
         tool.getLowerer().lower(write, tool);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Fri Dec 12 20:29:35 2014 +0100
@@ -23,11 +23,11 @@
 package com.oracle.graal.virtual.phases.ea;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+
 import java.util.*;
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.cfg.*;
-import com.oracle.graal.compiler.common.remote.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -45,7 +45,7 @@
 
     protected final NodeMap<ValueNode> aliases;
     protected final BlockMap<GraphEffectList> blockEffects;
-    private final Map<Loop<Block>, GraphEffectList> loopMergeEffects = Context.newIdentityMap();
+    private final Map<Loop<Block>, GraphEffectList> loopMergeEffects = CollectionsFactory.newIdentityMap();
     private final Map<LoopBeginNode, BlockT> loopEntryStates = Node.newIdentityMap();
 
     protected boolean changed;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Fri Dec 12 20:29:35 2014 +0100
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.remote.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -271,7 +271,7 @@
 
     protected class MergeProcessor extends EffectsClosure<BlockT>.MergeProcessor {
 
-        private final HashMap<Object, ValuePhiNode> materializedPhis = Context.newMap();
+        private final HashMap<Object, ValuePhiNode> materializedPhis = CollectionsFactory.newMap();
         private final Map<ValueNode, ValuePhiNode[]> valuePhis = Node.newIdentityMap();
         private final Map<ValuePhiNode, VirtualObjectNode> valueObjectVirtuals = Node.newIdentityMap();
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Fri Dec 12 20:29:35 2014 +0100
@@ -48,34 +48,32 @@
 
     protected final SnippetReflectionProvider snippetReflection;
 
-    @Input ValueNode valueKind;
     @Input(InputType.Association) ValueNode locationIdentity;
     @Input ValueNode displacement;
     @Input ValueNode index;
     @Input ValueNode indexScaling;
 
-    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode identity, ValueNode kind, ValueNode displacement, ValueNode index,
-                    ValueNode indexScaling, Graph graph) {
-        return graph.unique(SnippetLocationNode.create(snippetReflection, identity, kind, displacement, index, indexScaling));
+    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode identity, ValueNode displacement, ValueNode index, ValueNode indexScaling,
+                    Graph graph) {
+        return graph.unique(SnippetLocationNode.create(snippetReflection, identity, displacement, index, indexScaling));
     }
 
-    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) {
-        return new SnippetLocationNode(snippetReflection, locationIdentity, kind, displacement);
+    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode displacement) {
+        return new SnippetLocationNode(snippetReflection, locationIdentity, displacement);
     }
 
-    protected SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) {
-        this(snippetReflection, locationIdentity, kind, displacement, null, null);
+    protected SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode displacement) {
+        this(snippetReflection, locationIdentity, displacement, null, null);
     }
 
-    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index,
+    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode displacement, ValueNode index,
                     ValueNode indexScaling) {
-        return new SnippetLocationNode(snippetReflection, locationIdentity, kind, displacement, index, indexScaling);
+        return new SnippetLocationNode(snippetReflection, locationIdentity, displacement, index, indexScaling);
     }
 
-    protected SnippetLocationNode(SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling) {
+    protected SnippetLocationNode(SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode displacement, ValueNode index, ValueNode indexScaling) {
         super(StampFactory.object());
         this.snippetReflection = snippetReflection;
-        this.valueKind = kind;
         this.locationIdentity = locationIdentity;
         this.displacement = displacement;
         this.index = index;
@@ -83,14 +81,6 @@
     }
 
     @Override
-    public Kind getValueKind() {
-        if (valueKind.isConstant()) {
-            return snippetReflection.asObject(Kind.class, valueKind.asJavaConstant());
-        }
-        throw new GraalInternalError("Cannot access kind yet because it is not constant: " + valueKind);
-    }
-
-    @Override
     public LocationIdentity getLocationIdentity() {
         if (locationIdentity.isConstant()) {
             LocationIdentity identity = snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant());
@@ -102,18 +92,17 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (valueKind.isConstant() && locationIdentity.isConstant() && displacement.isConstant() && (indexScaling == null || indexScaling.isConstant())) {
-            Kind constKind = snippetReflection.asObject(Kind.class, valueKind.asJavaConstant());
+        if (locationIdentity.isConstant() && displacement.isConstant() && (indexScaling == null || indexScaling.isConstant())) {
             LocationIdentity constLocation = snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant());
             long constDisplacement = displacement.asJavaConstant().asLong();
             int constIndexScaling = indexScaling == null ? 0 : indexScaling.asJavaConstant().asInt();
 
             if (index == null || constIndexScaling == 0) {
-                return ConstantLocationNode.create(constLocation, constKind, constDisplacement, graph());
+                return ConstantLocationNode.create(constLocation, constDisplacement, graph());
             } else if (index.isConstant()) {
-                return ConstantLocationNode.create(constLocation, constKind, index.asJavaConstant().asLong() * constIndexScaling + constDisplacement, graph());
+                return ConstantLocationNode.create(constLocation, index.asJavaConstant().asLong() * constIndexScaling + constDisplacement, graph());
             } else {
-                return IndexedLocationNode.create(constLocation, constKind, constDisplacement, index, graph(), constIndexScaling);
+                return IndexedLocationNode.create(constLocation, constDisplacement, index, graph(), constIndexScaling);
             }
         }
         return this;
@@ -130,8 +119,8 @@
     }
 
     @NodeIntrinsic
-    public static native Location constantLocation(LocationIdentity identity, Kind kind, long displacement);
+    public static native Location constantLocation(LocationIdentity identity, long displacement);
 
     @NodeIntrinsic
-    public static native Location indexedLocation(LocationIdentity identity, Kind kind, long displacement, int index, int indexScaling);
+    public static native Location indexedLocation(LocationIdentity identity, long displacement, int index, int indexScaling);
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Dec 12 20:29:35 2014 +0100
@@ -230,19 +230,19 @@
                 Kind readKind = asKind(callTargetNode.returnType());
                 LocationNode location;
                 if (arguments.size() == 2) {
-                    location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
+                    location = makeLocation(graph, arguments.get(1), ANY_LOCATION);
                 } else {
-                    location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
+                    location = makeLocation(graph, arguments.get(1), arguments.get(2));
                 }
-                replace(invoke, readOp(graph, arguments.get(0), invoke, location, operation.opcode()));
+                replace(invoke, readOp(graph, readKind, arguments.get(0), invoke, location, operation.opcode()));
                 break;
             }
             case READ_HEAP: {
                 assert arguments.size() == 3;
                 Kind readKind = asKind(callTargetNode.returnType());
-                LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
+                LocationNode location = makeLocation(graph, arguments.get(1), ANY_LOCATION);
                 BarrierType barrierType = snippetReflection.asObject(BarrierType.class, arguments.get(2).asJavaConstant());
-                replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, true));
+                replace(invoke, readOp(graph, readKind, arguments.get(0), invoke, location, barrierType, true));
                 break;
             }
             case WRITE_POINTER:
@@ -253,11 +253,11 @@
                 Kind writeKind = asKind(targetMethod.getSignature().getParameterType(targetMethod.isStatic() ? 2 : 1, targetMethod.getDeclaringClass()));
                 LocationNode location;
                 if (arguments.size() == 3) {
-                    location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION);
+                    location = makeLocation(graph, arguments.get(1), LocationIdentity.ANY_LOCATION);
                 } else {
-                    location = makeLocation(graph, arguments.get(1), writeKind, arguments.get(3));
+                    location = makeLocation(graph, arguments.get(1), arguments.get(3));
                 }
-                replace(invoke, writeOp(graph, arguments.get(0), arguments.get(2), invoke, location, operation.opcode()));
+                replace(invoke, writeOp(graph, writeKind, arguments.get(0), arguments.get(2), invoke, location, operation.opcode()));
                 break;
             }
             case ZERO:
@@ -379,28 +379,27 @@
         return materialize;
     }
 
-    protected LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, ValueNode locationIdentity) {
+    protected LocationNode makeLocation(StructuredGraph graph, ValueNode offset, ValueNode locationIdentity) {
         if (locationIdentity.isConstant()) {
-            return makeLocation(graph, offset, readKind, snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant()));
+            return makeLocation(graph, offset, snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant()));
         }
-        return SnippetLocationNode.create(snippetReflection, locationIdentity, ConstantNode.forConstant(snippetReflection.forObject(readKind), metaAccess, graph), ConstantNode.forLong(0, graph),
-                        fromSigned(graph, offset), ConstantNode.forInt(1, graph), graph);
+        return SnippetLocationNode.create(snippetReflection, locationIdentity, ConstantNode.forLong(0, graph), fromSigned(graph, offset), ConstantNode.forInt(1, graph), graph);
     }
 
-    protected LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, LocationIdentity locationIdentity) {
-        return IndexedLocationNode.create(locationIdentity, readKind, 0, fromSigned(graph, offset), graph, 1);
+    protected LocationNode makeLocation(StructuredGraph graph, ValueNode offset, LocationIdentity locationIdentity) {
+        return IndexedLocationNode.create(locationIdentity, 0, fromSigned(graph, offset), graph, 1);
     }
 
-    protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, Opcode op) {
+    protected ValueNode readOp(StructuredGraph graph, Kind readKind, ValueNode base, Invoke invoke, LocationNode location, Opcode op) {
         assert op == Opcode.READ_POINTER || op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED;
         final BarrierType barrier = (op == Opcode.READ_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE);
         final boolean compressible = (op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED);
 
-        return readOp(graph, base, invoke, location, barrier, compressible);
+        return readOp(graph, readKind, base, invoke, location, barrier, compressible);
     }
 
-    protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) {
-        JavaReadNode read = graph.add(JavaReadNode.create(base, location, barrierType, compressible));
+    protected ValueNode readOp(StructuredGraph graph, Kind readKind, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) {
+        JavaReadNode read = graph.add(JavaReadNode.create(readKind, base, location, barrierType, compressible));
         graph.addBeforeFixed(invoke.asNode(), read);
         /*
          * The read must not float outside its block otherwise it may float above an explicit zero
@@ -410,12 +409,12 @@
         return read;
     }
 
-    protected ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location, Opcode op) {
+    protected ValueNode writeOp(StructuredGraph graph, Kind writeKind, ValueNode base, ValueNode value, Invoke invoke, LocationNode location, Opcode op) {
         assert op == Opcode.WRITE_POINTER || op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED || op == Opcode.INITIALIZE;
         final BarrierType barrier = (op == Opcode.WRITE_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE);
         final boolean compressible = (op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED);
         final boolean initialize = (op == Opcode.INITIALIZE);
-        JavaWriteNode write = graph.add(JavaWriteNode.create(base, value, location, barrier, compressible, initialize));
+        JavaWriteNode write = graph.add(JavaWriteNode.create(writeKind, base, value, location, barrier, compressible, initialize));
         write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.asNode(), write);
         return write;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java	Fri Dec 12 20:02:09 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java	Fri Dec 12 20:29:35 2014 +0100
@@ -49,13 +49,14 @@
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 wasTrue = true;
             }
+            return true;
         } else {
             if (!wasFalse) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 wasFalse = true;
             }
+            return false;
         }
-        return value;
     }
 
     public boolean wasTrue() {
--- a/mx/mx_graal.py	Fri Dec 12 20:02:09 2014 +0100
+++ b/mx/mx_graal.py	Fri Dec 12 20:29:35 2014 +0100
@@ -755,7 +755,7 @@
         if not exists(opts2.export_dir):
             os.makedirs(opts2.export_dir)
         else:
-            assert os.path.isdir(opts2.export_dir), '{} is not a directory'.format(opts2.export_dir)
+            assert os.path.isdir(opts2.export_dir), '{0} is not a directory'.format(opts2.export_dir)
 
         defsPath = join(_graal_home, 'make', 'defs.make')
         with open(defsPath) as fp:
@@ -1835,7 +1835,7 @@
                         deps = d['deps']
                         makejmhdep(artifactId, groupId, deps)
             except ValueError as e:
-                mx.abort('Error parsing {}:\n{}'.format(f, e))
+                mx.abort('Error parsing {0}:\n{1}'.format(f, e))
 
 def buildjmh(args):
     """build the JMH benchmarks"""
@@ -1916,7 +1916,7 @@
                 else:
                     jmhArgs[n] = v
         except ValueError as e:
-            mx.abort('error parsing JSON input: {}\n{}'.format(j, e))
+            mx.abort('error parsing JSON input: {0}\n{1}'.format(j, e))
 
     jmhPath = _get_jmh_path()
     mx.log('Using benchmarks in ' + jmhPath)
@@ -2310,7 +2310,7 @@
                                         if not matcher.match(content):
                                             failures[f] = csConfig
     for n, v in failures.iteritems():
-        mx.log('{}: header does not match RegexpHeader defined in {}'.format(n, v))
+        mx.log('{0}: header does not match RegexpHeader defined in {1}'.format(n, v))
     return len(failures)
 
 def mx_init(suite):
--- a/mxtool/mx.py	Fri Dec 12 20:02:09 2014 +0100
+++ b/mxtool/mx.py	Fri Dec 12 20:29:35 2014 +0100
@@ -109,7 +109,7 @@
         try:
             excl = [dependency(d) for d in self.excludedDependencies]
         except SystemExit as e:
-            abort('invalid excluded dependency for {} distribution: {}'.format(self.name, e))
+            abort('invalid excluded dependency for {0} distribution: {1}'.format(self.name, e))
         return deps + [d for d in sorted_deps(self.deps, includeLibs=includeLibs) if d not in excl]
 
     def __str__(self):
@@ -698,14 +698,14 @@
         abspath = _make_absolute(path, self.suite.dir)
         if not optional and not exists(abspath):
             if not len(urls):
-                abort('Non-optional library {} must either exist at {} or specify one or more URLs from which it can be retrieved'.format(name, abspath))
+                abort('Non-optional library {0} must either exist at {1} or specify one or more URLs from which it can be retrieved'.format(name, abspath))
 
         def _checkSha1PropertyCondition(propName, cond, inputPath):
             if not cond:
                 absInputPath = _make_absolute(inputPath, self.suite.dir)
                 if exists(absInputPath):
-                    abort('Missing "{}" property for library {}. Add the following line to projects file:\nlibrary@{}@{}={}'.format(propName, name, name, propName, sha1OfFile(absInputPath)))
-                abort('Missing "{}" property for library {}'.format(propName, name))
+                    abort('Missing "{0}" property for library {1}. Add the following line to projects file:\nlibrary@{2}@{3}={4}'.format(propName, name, name, propName, sha1OfFile(absInputPath)))
+                abort('Missing "{0}" property for library {1}'.format(propName, name))
 
         _checkSha1PropertyCondition('sha1', sha1, path)
         _checkSha1PropertyCondition('sourceSha1', not sourcePath or sourceSha1, sourcePath)
@@ -1181,12 +1181,12 @@
                     finally:
                         d.optional = True
                     if not path:
-                        logv('[omitting optional library {} as {} does not exist]'.format(d, d.path))
+                        logv('[omitting optional library {0} as {1} does not exist]'.format(d, d.path))
                         del _libs[d.name]
                         self.libs.remove(d)
             elif d.isProject():
                 if java(d.javaCompliance) is None:
-                    logv('[omitting project {} as Java compliance {} cannot be satisfied by configured JDKs]'.format(d, d.javaCompliance))
+                    logv('[omitting project {0} as Java compliance {1} cannot be satisfied by configured JDKs]'.format(d, d.javaCompliance))
                     del _projects[d.name]
                     self.projects.remove(d)
                 else:
@@ -1195,19 +1195,19 @@
                         if jreLib:
                             if not jreLib.is_present_in_jdk(java(d.javaCompliance)):
                                 if jreLib.optional:
-                                    logv('[omitting project {} as dependency {} is missing]'.format(d, name))
+                                    logv('[omitting project {0} as dependency {1} is missing]'.format(d, name))
                                     del _projects[d.name]
                                     self.projects.remove(d)
                                 else:
-                                    abort('JRE library {} required by {} not found'.format(jreLib, d))
+                                    abort('JRE library {0} required by {1} not found'.format(jreLib, d))
                         elif not dependency(name, fatalIfMissing=False):
-                            logv('[omitting project {} as dependency {} is missing]'.format(d, name))
+                            logv('[omitting project {0} as dependency {1} is missing]'.format(d, name))
                             del _projects[d.name]
                             self.projects.remove(d)
         for dist in _dists.itervalues():
             for name in list(dist.deps):
                 if not dependency(name, fatalIfMissing=False):
-                    logv('[omitting {} from distribution {}]'.format(name, dist))
+                    logv('[omitting {0} from distribution {1}]'.format(name, dist))
                     dist.deps.remove(name)
 
         if hasattr(self, 'mx_post_parse_cmd_line'):
@@ -1673,6 +1673,9 @@
 
         opts = self.parse_args()
 
+        global _opts
+        _opts = opts
+
         # Give the timeout options a default value to avoid the need for hasattr() tests
         opts.__dict__.setdefault('timeout', 0)
         opts.__dict__.setdefault('ptimeout', 0)
@@ -2209,7 +2212,7 @@
     the object's value is printed and the exit status is one.
     """
 
-    if _opts.killwithsigquit:
+    if _opts and _opts.killwithsigquit:
         _send_sigquit()
 
     def is_alive(p):
@@ -2227,7 +2230,7 @@
                     _kill_process_group(p.pid, signal.SIGKILL)
             except BaseException as e:
                 if is_alive(p):
-                    log('error while killing subprocess {} "{}": {}'.format(p.pid, ' '.join(args), e))
+                    log('error while killing subprocess {0} "{1}": {2}'.format(p.pid, ' '.join(args), e))
 
     if _opts and _opts.verbose:
         import traceback
@@ -2304,7 +2307,7 @@
         return self.proj.name
 
     def logCompilation(self, compiler):
-        log('Compiling Java sources for {} with {}... [{}]'.format(self.proj.name, compiler, self.reason))
+        log('Compiling Java sources for {0} with {1}... [{2}]'.format(self.proj.name, compiler, self.reason))
 
     def execute(self):
         argfileName = join(self.proj.dir, 'javafilelist.txt')
@@ -2469,22 +2472,6 @@
     if args.java:
         ideinit([], refreshOnly=True, buildProcessorJars=False)
 
-    def prepareOutputDirs(p, clean):
-        outputDir = p.output_dir()
-        if exists(outputDir):
-            if clean:
-                log('Cleaning {0}...'.format(outputDir))
-                shutil.rmtree(outputDir)
-                os.mkdir(outputDir)
-        else:
-            os.mkdir(outputDir)
-        genDir = p.source_gen_dir()
-        if genDir != '' and exists(genDir) and clean:
-            log('Cleaning {0}...'.format(genDir))
-            for f in os.listdir(genDir):
-                shutil.rmtree(join(genDir, f))
-        return outputDir
-
     tasks = {}
     updatedAnnotationProcessorDists = set()
     for p in sortedProjects:
@@ -2508,10 +2495,15 @@
         jdk = java(requiredCompliance)
         assert jdk
 
-        outputDir = prepareOutputDirs(p, args.clean)
+        outputDir = p.output_dir()
 
         sourceDirs = p.source_dirs()
-        buildReason = 'forced build' if args.force else None
+        buildReason = None
+        if args.force:
+            buildReason = 'forced build'
+        elif args.clean:
+            buildReason = 'clean'
+
         taskDeps = []
         for dep in p.all_deps([], includeLibs=False, includeAnnotationProcessors=True):
             taskDep = tasks.get(dep.name)
@@ -2520,52 +2512,14 @@
                     buildReason = dep.name + ' rebuilt'
                 taskDeps.append(taskDep)
 
-        jasminAvailable = None
         javafilelist = []
+        nonjavafiletuples = []
         for sourceDir in sourceDirs:
             for root, _, files in os.walk(sourceDir):
                 javafiles = [join(root, name) for name in files if name.endswith('.java') and name != 'package-info.java']
                 javafilelist += javafiles
 
-                # Copy all non Java resources or assemble Jasmin files
-                nonjavafilelist = [join(root, name) for name in files if not name.endswith('.java')]
-                for src in nonjavafilelist:
-                    if src.endswith('.jasm'):
-                        className = None
-                        with open(src) as f:
-                            for line in f:
-                                if line.startswith('.class '):
-                                    className = line.split()[-1]
-                                    break
-
-                        if className is not None:
-                            jasminOutputDir = p.jasmin_output_dir()
-                            classFile = join(jasminOutputDir, className.replace('/', os.sep) + '.class')
-                            if exists(dirname(classFile)) and (not exists(classFile) or os.path.getmtime(classFile) < os.path.getmtime(src)):
-                                if jasminAvailable is None:
-                                    try:
-                                        with open(os.devnull) as devnull:
-                                            subprocess.call('jasmin', stdout=devnull, stderr=subprocess.STDOUT)
-                                        jasminAvailable = True
-                                    except OSError:
-                                        jasminAvailable = False
-
-                                if jasminAvailable:
-                                    log('Assembling Jasmin file ' + src)
-                                    run(['jasmin', '-d', jasminOutputDir, src])
-                                else:
-                                    log('The jasmin executable could not be found - skipping ' + src)
-                                    with file(classFile, 'a'):
-                                        os.utime(classFile, None)
-
-                        else:
-                            log('could not file .class directive in Jasmin source: ' + src)
-                    else:
-                        dst = join(outputDir, src[len(sourceDir) + 1:])
-                        if not exists(dirname(dst)):
-                            os.makedirs(dirname(dst))
-                        if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)):
-                            shutil.copyfile(src, dst)
+                nonjavafiletuples += [(sourceDir, [join(root, name) for name in files if not name.endswith('.java')])]
 
                 if not buildReason:
                     for javafile in javafiles:
@@ -2580,8 +2534,11 @@
 
         if not buildReason:
             logv('[all class files for {0} are up to date - skipping]'.format(p.name))
+            _handleNonJavaFiles(outputDir, p, False, nonjavafiletuples)
             continue
 
+        _handleNonJavaFiles(outputDir, p, True, nonjavafiletuples)
+
         if len(javafilelist) == 0:
             logv('[no Java sources for {0} - skipping]'.format(p.name))
             continue
@@ -2688,8 +2645,8 @@
         failed += joinTasks(active)
         if len(failed):
             for t in failed:
-                log('Compiling {} failed'.format(t.proj.name))
-            abort('{} Java compilation tasks failed'.format(len(failed)))
+                log('Compiling {0} failed'.format(t.proj.name))
+            abort('{0} Java compilation tasks failed'.format(len(failed)))
 
     if args.java:
         for dist in sorted_dists():
@@ -2700,6 +2657,64 @@
         return args
     return None
 
+def _handleNonJavaFiles(outputDir, p, clean, nonjavafiletuples):
+    if exists(outputDir):
+        if clean:
+            log('Cleaning {0}...'.format(outputDir))
+            shutil.rmtree(outputDir)
+            os.mkdir(outputDir)
+    else:
+        os.mkdir(outputDir)
+    genDir = p.source_gen_dir()
+    if genDir != '' and exists(genDir) and clean:
+        log('Cleaning {0}...'.format(genDir))
+        for f in os.listdir(genDir):
+            shutil.rmtree(join(genDir, f))
+
+    # Copy all non Java resources or assemble Jasmin files
+    jasminAvailable = None
+    for nonjavafiletuple in nonjavafiletuples:
+        sourceDir = nonjavafiletuple[0]
+        nonjavafilelist = nonjavafiletuple[1]
+
+        for src in nonjavafilelist:
+            if src.endswith('.jasm'):
+                className = None
+                with open(src) as f:
+                    for line in f:
+                        if line.startswith('.class '):
+                            className = line.split()[-1]
+                            break
+
+                if className is not None:
+                    jasminOutputDir = p.jasmin_output_dir()
+                    classFile = join(jasminOutputDir, className.replace('/', os.sep) + '.class')
+                    if exists(dirname(classFile)) and (not exists(classFile) or os.path.getmtime(classFile) < os.path.getmtime(src)):
+                        if jasminAvailable is None:
+                            try:
+                                with open(os.devnull) as devnull:
+                                    subprocess.call('jasmin', stdout=devnull, stderr=subprocess.STDOUT)
+                                jasminAvailable = True
+                            except OSError:
+                                jasminAvailable = False
+
+                        if jasminAvailable:
+                            log('Assembling Jasmin file ' + src)
+                            run(['jasmin', '-d', jasminOutputDir, src])
+                        else:
+                            log('The jasmin executable could not be found - skipping ' + src)
+                            with file(classFile, 'a'):
+                                os.utime(classFile, None)
+
+                else:
+                    log('could not file .class directive in Jasmin source: ' + src)
+            else:
+                dst = join(outputDir, src[len(sourceDir) + 1:])
+                if not exists(dirname(dst)):
+                    os.makedirs(dirname(dst))
+                if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)):
+                    shutil.copyfile(src, dst)
+
 def _chunk_files_for_command_line(files, limit=None, pathFunction=None):
     """
     Returns a generator for splitting up a list of files into chunks such that the
@@ -3039,7 +3054,7 @@
                     candidates.difference_update(c.all_deps([], False, False))
                 candidates = [d.name for d in candidates]
 
-                abort('{} does not use any packages defined in these projects: {}\nComputed project dependencies: {}'.format(
+                abort('{0} does not use any packages defined in these projects: {1}\nComputed project dependencies: {2}'.format(
                     p, ', '.join(ignoredDeps), ','.join(candidates)))
 
             excess = frozenset(p.deps) - set(p.canonical_deps())
@@ -3166,7 +3181,7 @@
                                 if name == 'file':
                                     source[0] = attrs['name']
                                 elif name == 'error':
-                                    errors.append('{}:{}: {}'.format(source[0], attrs['line'], attrs['message']))
+                                    errors.append('{0}:{1}: {2}'.format(source[0], attrs['line'], attrs['message']))
 
                             xp = xml.parsers.expat.ParserCreate()
                             xp.StartElementHandler = start_element
@@ -4782,9 +4797,9 @@
                 if not 'version' in subprocess.check_output(['dot', '-V'], stderr=subprocess.STDOUT):
                     dotErr = 'dot -V does not print a string containing "version"'
             except subprocess.CalledProcessError as e:
-                dotErr = 'error calling "dot -V": {}'.format(e)
+                dotErr = 'error calling "dot -V": {0}'.format(e)
             except OSError as e:
-                dotErr = 'error calling "dot -V": {}'.format(e)
+                dotErr = 'error calling "dot -V": {0}'.format(e)
 
             if dotErr != None:
                 abort('cannot generate dependency graph: ' + dotErr)
@@ -4824,7 +4839,7 @@
 
             # Create HTML that embeds the svg file in an <object> frame
             with open(html, 'w') as fp:
-                print >> fp, '<html><body><object data="{}.svg" type="image/svg+xml"></object></body></html>'.format(args.dot_output_base)
+                print >> fp, '<html><body><object data="{0}.svg" type="image/svg+xml"></object></body></html>'.format(args.dot_output_base)
 
         if exists(args.base):
             shutil.rmtree(args.base)
@@ -5177,9 +5192,9 @@
         abort('no primary suite found')
 
     opts, commandAndArgs = _argParser._parse_cmd_line()
-
-    global _opts, _java_homes
-    _opts = opts
+    assert _opts == opts
+
+    global _java_homes
     defaultJdk = JavaConfig(opts.java_home, opts.java_dbg_port)
     _java_homes = [defaultJdk]
     if opts.extra_java_homes:
--- a/src/cpu/x86/vm/nativeInst_x86.hpp	Fri Dec 12 20:02:09 2014 +0100
+++ b/src/cpu/x86/vm/nativeInst_x86.hpp	Fri Dec 12 20:29:35 2014 +0100
@@ -562,26 +562,24 @@
                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
 inline bool NativeInstruction::is_safepoint_poll() {
 #ifdef AMD64
-  if (Assembler::is_polling_page_far()) {
-    // two cases, depending on the choice of the base register in the address.
-    if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
-         ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
-         (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
-        ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
-        (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
-      return true;
-    } else {
-      return false;
-    }
-  } else {
-    if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
-        ubyte_at(1) == 0x05) { // 00 rax 101
-      address fault = addr_at(6) + int_at(2);
-      return os::is_poll_address(fault);
-    } else {
-      return false;
-    }
+  // Try decoding a near safepoint first:
+  if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+      ubyte_at(1) == 0x05) { // 00 rax 101
+    address fault = addr_at(6) + int_at(2);
+    NOT_GRAAL(assert(!Assembler::is_polling_page_far(), "unexpected poll encoding");)
+    return os::is_poll_address(fault);
   }
+  // Now try decoding a far safepoint:
+  // two cases, depending on the choice of the base register in the address.
+  if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
+       ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
+       (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
+      ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+      (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
+    NOT_GRAAL(assert(Assembler::is_polling_page_far(), "unexpected poll encoding");)
+    return true;
+  }
+  return false;
 #else
   return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
            ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Dec 12 20:02:09 2014 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Fri Dec 12 20:29:35 2014 +0100
@@ -962,6 +962,9 @@
       case POLL_RETURN_FAR:
         pd_relocate_poll(pc, id);
         break;
+      case CARD_TABLE_SHIFT:
+      case CARD_TABLE_ADDRESS:
+        break;
       default:
         ShouldNotReachHere();
         break;
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Fri Dec 12 20:02:09 2014 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Fri Dec 12 20:29:35 2014 +0100
@@ -47,6 +47,8 @@
     POLL_RETURN_NEAR           = 12,
     POLL_FAR                   = 13,
     POLL_RETURN_FAR            = 14,
+    CARD_TABLE_ADDRESS         = 15,
+    CARD_TABLE_SHIFT           = 16,
     INVOKE_INVALID             = -1
   };
 
--- a/src/share/vm/graal/graalRuntime.cpp	Fri Dec 12 20:02:09 2014 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Fri Dec 12 20:29:35 2014 +0100
@@ -627,7 +627,7 @@
     case 's': tty->print("%d", (jshort) value); break;
     case 'i': tty->print("%d", (jint) value); break;
     case 'f': tty->print("%f", uu.f); break;
-    case 'j': tty->print(INT64_FORMAT, value); break;
+    case 'j': tty->print(JLONG_FORMAT, value); break;
     case 'd': tty->print("%lf", uu.d); break;
     default: assert(false, "unknown typeChar"); break;
   }
@@ -679,6 +679,7 @@
 
 // private static TruffleRuntime Truffle.createRuntime()
 JVM_ENTRY(jobject, JVM_CreateTruffleRuntime(JNIEnv *env, jclass c))
+  GraalRuntime::ensure_graal_class_loader_is_initialized();
   TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime", CHECK_NULL);
   KlassHandle klass = GraalRuntime::resolve_or_fail(name, CHECK_NULL);
 
@@ -906,7 +907,7 @@
       if (num_read == -1) {
         warning("Error reading file %s due to %s", path, strerror(errno));
       } else if (num_read != st.st_size) {
-        warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, st.st_size, path);
+        warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path);
       }
       os::close(file_handle);
       if (num_read == st.st_size) {
--- a/src/share/vm/graal/vmStructs_graal.hpp	Fri Dec 12 20:02:09 2014 +0100
+++ b/src/share/vm/graal/vmStructs_graal.hpp	Fri Dec 12 20:29:35 2014 +0100
@@ -73,6 +73,8 @@
   declare_constant(CodeInstaller::POLL_RETURN_NEAR)                                               \
   declare_constant(CodeInstaller::POLL_FAR)                                                       \
   declare_constant(CodeInstaller::POLL_RETURN_FAR)                                                \
+  declare_constant(CodeInstaller::CARD_TABLE_SHIFT)                                               \
+  declare_constant(CodeInstaller::CARD_TABLE_ADDRESS)                                             \
   declare_constant(CodeInstaller::INVOKE_INVALID)                                                 \
                                                                                                   \
   declare_constant(Method::invalid_vtable_index)                                                  \