changeset 18655:86269e451920

removed (most) replay compilation support
author Doug Simon <doug.simon@oracle.com>
date Tue, 09 Dec 2014 23:44:07 +0100
parents 7c31de47cf48
children de362aafce05
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/CollectionsFactory.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/LinkedIdentityHashMap.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.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstantImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java
diffstat 17 files changed, 388 insertions(+), 1060 deletions(-) [+]
line wrap: on
line diff
--- /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	Tue Dec 09 23:44:07 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);
+    }
+}
--- /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	Tue Dec 09 23:44:07 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	Tue Dec 09 22:28:22 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	Tue Dec 09 22:28:22 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	Tue Dec 09 22:28:22 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	Tue Dec 09 22:28:22 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	Tue Dec 09 22:28:22 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/src/com/oracle/graal/compiler/gen/PhiResolver.java	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Tue Dec 09 23:44:07 2014 +0100
@@ -29,7 +29,7 @@
 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.lir.gen.*;
 import com.oracle.graal.nodes.*;
 
@@ -120,7 +120,7 @@
     /**
      * Maps operands to nodes.
      */
-    private final HashMap<Value, PhiResolverNode> operandToNodeMap = Context.newMap();
+    private final HashMap<Value, PhiResolverNode> operandToNodeMap = CollectionsFactory.newMap();
 
     public PhiResolver(LIRGeneratorTool gen) {
         this.gen = gen;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Dec 09 23:44:07 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.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Tue Dec 09 23:44:07 2014 +0100
@@ -25,7 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.compiler.common.remote.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
@@ -46,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 = Context.newMap();
+    private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = CollectionsFactory.newMap();
 
     public AMD64HotSpotLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, Object stub) {
         super(lir, frameMapBuilder);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Dec 09 23:44:07 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,10 @@
         }
     }
 
-    /**
-     * 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.
-     */
-    public static boolean checkRuntimeAccess() {
-        return Context.assertInLocal("Cannot access HotSpotGraalRuntime statically in replay/remote context");
+    private static Predicate<Void> runtimeAccessCheck;
+
+    public static void setRuntimeAccessCheck(Predicate<Void> predicate) {
+        runtimeAccessCheck = predicate;
     }
 
     /**
@@ -94,7 +91,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/meta/HotSpotMetaspaceConstantImpl.java	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstantImpl.java	Tue Dec 09 23:44:07 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	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java	Tue Dec 09 23:44:07 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.loop/src/com/oracle/graal/loop/LoopsData.java	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Tue Dec 09 23:44:07 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.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Dec 09 23:44:07 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.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Tue Dec 09 23:44:07 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	Tue Dec 09 22:28:22 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Dec 09 23:44:07 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();