changeset 22273:706aa848a8d7

Merge with basic-graal
author Doug Simon <doug.simon@oracle.com>
date Tue, 21 Jul 2015 16:15:22 +0200
parents 9bbd878b17af (current diff) b6d504612b3f (diff)
children ed0b8310ac56
files jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotTargetDescription.java jvmci/jdk.internal.jvmci.options.processor/src/jdk/internal/jvmci/options/processor/JVMCIJars.java mx.jvmci/mx_jvmci.py mx.jvmci/mx_jvmci_makefile.py mx.jvmci/suite.py
diffstat 54 files changed, 3051 insertions(+), 371 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Jul 21 15:16:01 2015 +0200
+++ b/.hgignore	Tue Jul 21 16:15:22 2015 +0200
@@ -87,7 +87,7 @@
 jacoco.exec
 workingsets.xml
 .buildbot/
-graal.options
+jvmci.options
 agent/build/*
 agent/make/filelist
 agent/make/sa17.tar.gz
--- a/.hgtags	Tue Jul 21 15:16:01 2015 +0200
+++ b/.hgtags	Tue Jul 21 16:15:22 2015 +0200
@@ -617,3 +617,4 @@
 f4822d12204179e6a3e7aaf98991b6171670cbf2 jdk8u45-b11
 dc29108bcbcbfcd49eaa9135368306dc85db73a6 jdk8u45-b12
 efbf340fc7f56e49735111c23cef030413146409 jdk8u45-b13
+3c622007e098d8905d8e0947362a3894a629a5f1 graal-0.8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAAssertionsTest.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2015, 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.test.ea;
+
+import jdk.internal.jvmci.code.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.directives.*;
+import com.oracle.graal.compiler.test.*;
+
+public class PEAAssertionsTest extends GraalCompilerTest {
+
+    public static Object field;
+
+    public static void snippet1(int i) {
+        Integer object = new Integer(i);
+        GraalDirectives.ensureVirtualized(object);
+    }
+
+    @Test
+    public void test1() {
+        test("snippet1", 1);
+    }
+
+    public static void snippet2(int i) {
+        Integer object = new Integer(i);
+        GraalDirectives.ensureVirtualized(object);
+        field = object; // assert here
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void test2() {
+        test("snippet2", 1);
+    }
+
+    public static void snippet3(int i) {
+        Integer object = new Integer(i);
+        field = object;
+        GraalDirectives.ensureVirtualized(object); // assert here
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void test3() {
+        test("snippet3", 1);
+    }
+
+    public static void snippetHere1(int i) {
+        Integer object = new Integer(i);
+        GraalDirectives.ensureVirtualizedHere(object);
+    }
+
+    @Test
+    public void testHere1() {
+        test("snippetHere1", 1);
+    }
+
+    public static void snippetHere2(int i) {
+        Integer object = new Integer(i);
+        GraalDirectives.ensureVirtualizedHere(object);
+        field = object;
+    }
+
+    @Test
+    public void testHere2() {
+        test("snippetHere2", 1);
+    }
+
+    public static void snippetHere3(int i) {
+        Integer object = new Integer(i);
+        field = object;
+        GraalDirectives.ensureVirtualizedHere(object); // assert here
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void testHere3() {
+        test("snippetHere3", 1);
+    }
+
+    public static void snippetBoxing1(int i) {
+        Integer object = i;
+        GraalDirectives.ensureVirtualizedHere(object); // assert here
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void testBoxing1() {
+        test("snippetBoxing1", 1);
+    }
+
+    public static void snippetBoxing2(int i) {
+        Integer object = i;
+        GraalDirectives.ensureVirtualized(object); // assert here
+        field = object;
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void testBoxing2() {
+        test("snippetBoxing2", 1);
+    }
+
+    public static void snippetControlFlow1(boolean b, int i) {
+        Integer object = new Integer(i);
+        if (b) {
+            GraalDirectives.ensureVirtualized(object);
+        }
+        field = object;
+    }
+
+    @Test
+    public void testControlFlow1() {
+        test("snippetControlFlow1", true, 1);
+    }
+
+    public static void snippetControlFlow2(boolean b, int i) {
+        Integer object = new Integer(i);
+        if (b) {
+            GraalDirectives.ensureVirtualized(object);
+        } else {
+            GraalDirectives.ensureVirtualized(object);
+        }
+        field = object; // assert here
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void testControlFlow2() {
+        test("snippetControlFlow2", true, 1);
+    }
+
+    public static void snippetControlFlow3(boolean b, int i) {
+        Integer object = new Integer(i);
+        GraalDirectives.ensureVirtualized(object);
+        if (b) {
+            field = 1;
+        } else {
+            field = 2;
+        }
+        field = object; // assert here
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void testControlFlow3() {
+        test("snippetControlFlow3", true, 1);
+    }
+
+    public static void snippetControlFlow4(boolean b, int i) {
+        Integer object = new Integer(i);
+        if (b) {
+            field = object;
+        } else {
+            field = 2;
+        }
+        GraalDirectives.ensureVirtualized(object); // assert here
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void testControlFlow4() {
+        test("snippetControlFlow4", true, 1);
+    }
+
+    public static void snippetControlFlow5(boolean b, int i) {
+        Integer object = new Integer(i);
+        if (b) {
+            field = object;
+        } else {
+            field = 2;
+        }
+        GraalDirectives.ensureVirtualizedHere(object); // assert here
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void testControlFlow5() {
+        test("snippetControlFlow5", true, 1);
+    }
+
+    public static final class TestClass {
+        Object a;
+        Object b;
+    }
+
+    public static void snippetIndirect1(boolean b, int i) {
+        Integer object = new Integer(i);
+        TestClass t = new TestClass();
+        t.a = object;
+        GraalDirectives.ensureVirtualized(object);
+
+        if (b) {
+            field = t; // assert here
+        } else {
+            field = 2;
+        }
+    }
+
+    @Test(expected = SourceStackTrace.class)
+    public void testIndirect1() {
+        test("snippetIndirect1", true, 1);
+    }
+
+    public static void snippetIndirect2(boolean b, int i) {
+        Integer object = new Integer(i);
+        TestClass t = new TestClass();
+        t.a = object;
+        GraalDirectives.ensureVirtualized(t);
+
+        if (b) {
+            field = object;
+        } else {
+            field = 2;
+        }
+    }
+
+    @Test
+    public void testIndirect2() {
+        test("snippetIndirect2", true, 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2015, 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 jdk.internal.jvmci.hotspot.*;
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
+
+/**
+ * A direct call that complies with the conventions for such calls in HotSpot. It doesn't use an
+ * inline cache so it's just a patchable call site.
+ */
+@Opcode("CALL_DIRECT")
+final class AMD64HotSpotDirectStaticCallOp extends DirectCallOp {
+    public static final LIRInstructionClass<AMD64HotSpotDirectStaticCallOp> TYPE = LIRInstructionClass.create(AMD64HotSpotDirectStaticCallOp.class);
+
+    private final InvokeKind invokeKind;
+    private final HotSpotVMConfig config;
+
+    AMD64HotSpotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, HotSpotVMConfig config) {
+        super(TYPE, target, result, parameters, temps, state);
+        assert invokeKind.isDirect();
+        this.invokeKind = invokeKind;
+        this.config = config;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        crb.recordMark(invokeKind == InvokeKind.Static ? config.MARKID_INVOKESTATIC : config.MARKID_INVOKESPECIAL);
+        super.emitCode(crb, masm);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ConstantPoolSubstitutionsTests.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015, 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.*;
+
+import jdk.internal.jvmci.debug.*;
+import jdk.internal.jvmci.debug.Debug.*;
+import sun.misc.*;
+import sun.reflect.*;
+
+public class ConstantPoolSubstitutionsTests extends GraalCompilerTest {
+
+    protected StructuredGraph test(final String snippet) {
+        try (Scope s = Debug.scope("ConstantPoolSubstitutionsTests", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) {
+            StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
+            compile(graph.method(), graph);
+            assertNotInGraph(graph, Invoke.class);
+            Debug.dump(graph, snippet);
+            return graph;
+        } catch (Throwable e) {
+            throw Debug.handle(e);
+        }
+    }
+
+    protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class<?> clazz) {
+        for (Node node : graph.getNodes()) {
+            if (clazz.isInstance(node)) {
+                fail(node.toString());
+            }
+        }
+        return graph;
+    }
+
+    @Test
+    public void testGetSize() {
+        ConstantPool cp = SharedSecrets.getJavaLangAccess().getConstantPool(Object.class);
+        test("getSize", cp);
+    }
+
+    @Test
+    public void testGetIntAt() {
+        test("getIntAt");
+    }
+
+    @Test
+    public void testGetLongAt() {
+        test("getLongAt");
+    }
+
+    @Test
+    public void testGetFloatAt() {
+        test("getFloatAt");
+    }
+
+    @Test
+    public void testGetDoubleAt() {
+        test("getDoubleAt");
+    }
+
+    // @Test
+    public void testGetUTF8At() {
+        test("getUTF8At");
+    }
+
+    public int getSize(ConstantPool cp) {
+        return cp.getSize();
+    }
+
+    public int getIntAt(ConstantPool cp) {
+        return cp.getIntAt(0);
+    }
+
+    public long getLongAt(ConstantPool cp) {
+        return cp.getLongAt(0);
+    }
+
+    public float getFloatAt(ConstantPool cp) {
+        return cp.getFloatAt(0);
+    }
+
+    public double getDoubleAt(ConstantPool cp) {
+        return cp.getDoubleAt(0);
+    }
+
+    public String getUTF8At(ConstantPool cp) {
+        return cp.getUTF8At(0);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMapBuilder.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2009, 2015, 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 jdk.internal.jvmci.code.ValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.framemap.*;
+
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.hotspot.*;
+import jdk.internal.jvmci.meta.*;
+
+public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder {
+
+    private int maxRegisterSize;
+
+    private final ArrayList<Value> objectValues;
+    private int objectCount;
+
+    private final TargetDescription target;
+    private final int totalFrameSize;
+
+    public HotSpotReferenceMapBuilder(TargetDescription target, int totalFrameSize) {
+        this.objectValues = new ArrayList<>();
+        this.objectCount = 0;
+
+        this.target = target;
+        this.totalFrameSize = totalFrameSize;
+    }
+
+    @Override
+    public void addLiveValue(Value v) {
+        if (isConstant(v)) {
+            return;
+        }
+        LIRKind lirKind = v.getLIRKind();
+        if (!lirKind.isValue()) {
+            objectValues.add(v);
+            if (lirKind.isUnknownReference()) {
+                objectCount++;
+            } else {
+                objectCount += lirKind.getReferenceCount();
+            }
+        }
+        if (isRegister(v)) {
+            int size = target.getSizeInBytes(lirKind.getPlatformKind());
+            if (size > maxRegisterSize) {
+                maxRegisterSize = size;
+            }
+        }
+    }
+
+    @Override
+    public ReferenceMap finish(LIRFrameState state) {
+        Location[] objects = new Location[objectCount];
+        Location[] derivedBase = new Location[objectCount];
+        int[] sizeInBytes = new int[objectCount];
+
+        int idx = 0;
+        for (Value obj : objectValues) {
+            LIRKind kind = obj.getLIRKind();
+            int bytes = bytesPerElement(kind);
+            if (kind.isUnknownReference()) {
+                throw JVMCIError.unimplemented("derived references not yet implemented");
+            } else {
+                Location base = null;
+                if (kind.isDerivedReference()) {
+                    Variable baseVariable = (Variable) kind.getDerivedReferenceBase();
+                    Value baseValue = state.getLiveBasePointers().get(baseVariable.index);
+                    assert baseValue.getPlatformKind().getVectorLength() == 1 && baseValue.getLIRKind().isReference(0) && !baseValue.getLIRKind().isDerivedReference();
+                    base = toLocation(baseValue, 0);
+                }
+
+                for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) {
+                    if (kind.isReference(i)) {
+                        objects[idx] = toLocation(obj, i * bytes);
+                        derivedBase[idx] = base;
+                        sizeInBytes[idx] = bytes;
+                        idx++;
+                    }
+                }
+            }
+        }
+
+        return new HotSpotReferenceMap(objects, derivedBase, sizeInBytes, maxRegisterSize);
+    }
+
+    private int bytesPerElement(LIRKind kind) {
+        PlatformKind platformKind = kind.getPlatformKind();
+        return target.getSizeInBytes(platformKind) / platformKind.getVectorLength();
+    }
+
+    private Location toLocation(Value v, int offset) {
+        if (isRegister(v)) {
+            return Location.subregister(asRegister(v), offset);
+        } else {
+            StackSlot s = asStackSlot(v);
+            return Location.stack(s.getOffset(totalFrameSize) + offset);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ConstantPoolSubstitutions.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015, 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 static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.hotspot.word.*;
+import com.oracle.graal.word.*;
+
+import sun.reflect.*;
+
+/**
+ * Substitutions for {@link sun.reflect.ConstantPool} methods.
+ */
+@ClassSubstitution(sun.reflect.ConstantPool.class)
+public class ConstantPoolSubstitutions {
+
+    /**
+     * Get the metaspace {@code ConstantPool} pointer for the given holder class.
+     *
+     * @param constantPoolOop the holder class as {@link Object}
+     * @return a metaspace {@code ConstantPool} pointer
+     */
+    private static Word metaspaceConstantPool(Object constantPoolOop) {
+        // ConstantPool.constantPoolOop is in fact the holder class.
+        Class<?> constantPoolHolder = (Class<?>) constantPoolOop;
+        KlassPointer klass = ClassGetHubNode.readClass(constantPoolHolder);
+        return klass.readWord(instanceKlassConstantsOffset(), INSTANCE_KLASS_CONSTANTS);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    private static int getSize0(@SuppressWarnings("unused") final ConstantPool thisObj, Object constantPoolOop) {
+        return metaspaceConstantPool(constantPoolOop).readInt(constantPoolLengthOffset());
+    }
+
+    @MethodSubstitution(isStatic = false)
+    private static int getIntAt0(@SuppressWarnings("unused") final ConstantPool thisObj, Object constantPoolOop, int index) {
+        return metaspaceConstantPool(constantPoolOop).readInt(constantPoolSize() + index * wordSize());
+    }
+
+    @MethodSubstitution(isStatic = false)
+    private static long getLongAt0(@SuppressWarnings("unused") final ConstantPool thisObj, Object constantPoolOop, int index) {
+        return metaspaceConstantPool(constantPoolOop).readLong(constantPoolSize() + index * wordSize());
+    }
+
+    @MethodSubstitution(isStatic = false)
+    private static float getFloatAt0(@SuppressWarnings("unused") final ConstantPool thisObj, Object constantPoolOop, int index) {
+        return metaspaceConstantPool(constantPoolOop).readFloat(constantPoolSize() + index * wordSize());
+    }
+
+    @MethodSubstitution(isStatic = false)
+    private static double getDoubleAt0(@SuppressWarnings("unused") final ConstantPool thisObj, Object constantPoolOop, int index) {
+        return metaspaceConstantPool(constantPoolOop).readDouble(constantPoolSize() + index * wordSize());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, 2015, 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.arraycopy;
+
+import static jdk.internal.jvmci.meta.LocationIdentity.*;
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo
+public class ArrayCopyUnrollNode extends ArrayRangeWriteNode implements MemoryCheckpoint.Single, Lowerable, MemoryAccess {
+
+    public static final NodeClass<ArrayCopyUnrollNode> TYPE = NodeClass.create(ArrayCopyUnrollNode.class);
+
+    @Input protected ValueNode src;
+    @Input protected ValueNode srcPos;
+    @Input protected ValueNode dest;
+    @Input protected ValueNode destPos;
+    @Input protected ValueNode length;
+
+    private Kind elementKind;
+
+    private int unrolledLength;
+
+    @OptionalInput(InputType.Memory) private MemoryNode lastLocationAccess;
+
+    public ArrayCopyUnrollNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, int unrolledLength, Kind elementKind) {
+        super(TYPE, StampFactory.forKind(Kind.Void));
+        this.src = src;
+        this.srcPos = srcPos;
+        this.dest = dest;
+        this.destPos = destPos;
+        this.length = length;
+        this.unrolledLength = unrolledLength;
+        assert elementKind != null && elementKind != Kind.Illegal;
+        this.elementKind = elementKind;
+    }
+
+    public ValueNode getSource() {
+        return src;
+    }
+
+    public ValueNode getSourcePosition() {
+        return srcPos;
+    }
+
+    public ValueNode getDestination() {
+        return dest;
+    }
+
+    public ValueNode getDestinationPosition() {
+        return destPos;
+    }
+
+    @Override
+    public ValueNode getLength() {
+        return length;
+    }
+
+    @Override
+    public ValueNode getArray() {
+        return dest;
+    }
+
+    @Override
+    public ValueNode getIndex() {
+        return destPos;
+    }
+
+    @Override
+    public boolean isObjectArray() {
+        return elementKind == Kind.Object;
+    }
+
+    @Override
+    public boolean isInitialization() {
+        return false;
+    }
+
+    @NodeIntrinsic
+    public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter int unrolledLength, @ConstantNodeParameter Kind elementKind);
+
+    public int getUnrollLength() {
+        return unrolledLength;
+    }
+
+    public Kind getElementKind() {
+        return elementKind;
+    }
+
+    @Override
+    public LocationIdentity getLocationIdentity() {
+        if (elementKind != null) {
+            return NamedLocationIdentity.getArrayLocation(elementKind);
+        }
+        return any();
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
+    public MemoryNode getLastLocationAccess() {
+        return lastLocationAccess;
+    }
+
+    public void setLastLocationAccess(MemoryNode lla) {
+        updateUsagesInterface(lastLocationAccess, lla);
+        lastLocationAccess = lla;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ConstantLoadTest.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, 2015, 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.jtt.micro;
+
+import org.junit.*;
+
+import com.oracle.graal.jtt.*;
+
+public class ConstantLoadTest extends JTTTest {
+
+    private static final class MyClass {
+        public long a;
+        public long b;
+
+        MyClass(long a, long b) {
+            this.a = a;
+            this.b = b;
+        }
+    }
+
+    private static final MyClass myClass = new MyClass(Long.MIN_VALUE, Long.MAX_VALUE);
+    private static final long myLong = Long.MAX_VALUE;
+
+    public static long test(int arg) {
+        if (arg == 0) {
+            return myClass.a / arg + myLong;
+        }
+        if (arg == 1) {
+            return myClass.b - arg + myLong;
+        }
+        long r = 1;
+        for (int i = 0; i < arg; i++) {
+            r *= i;
+        }
+        return r;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", 0);
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", -1);
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        runTest("test", 1);
+    }
+
+    @Test
+    public void run3() throws Throwable {
+        runTest("test", 2);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/VarArgs_Unroll.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 2015, 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.jtt.micro;
+
+import org.junit.*;
+
+import com.oracle.graal.jtt.*;
+
+/*
+ */
+public class VarArgs_Unroll extends JTTTest {
+
+    public static boolean test(String a, String b) {
+        return check(a, b);
+    }
+
+    private static boolean check(String... args) {
+        if (args.length == 0) {
+            return true;
+        }
+        String s = args[0];
+        for (String t : args) {
+            if (!t.equals(s)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", "ab", "ab");
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", "ab", "abc");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.jtt/src/com/oracle/graal/lir/jtt/ConstantStackCastTest.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, 2015, 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.lir.jtt;
+
+import static jdk.internal.jvmci.code.ValueUtil.*;
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.meta.*;
+
+import org.junit.*;
+
+import com.oracle.graal.lir.framemap.*;
+import com.oracle.graal.lir.gen.*;
+
+/**
+ * Tests move from a constant to a wider stack slot (e.g. byte constant to integer stack slot).
+ */
+public class ConstantStackCastTest extends LIRTest {
+
+    private static class LoadConstantStackSpec extends LIRTestSpecification {
+        protected final LIRKind dstKind;
+        protected final LIRKind srcKind;
+
+        public LoadConstantStackSpec(LIRKind dstKind, LIRKind srcKind) {
+            this.dstKind = dstKind;
+            this.srcKind = srcKind;
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool gen, Value value) {
+            FrameMapBuilder frameMapBuilder = gen.getResult().getFrameMapBuilder();
+            // create slots
+            StackSlotValue s1 = frameMapBuilder.allocateSpillSlot(dstKind);
+            // move stuff around
+            Value srcValue = isConstant(value) ? getConstant(srcKind, value) : value;
+            gen.emitMove(s1, srcValue);
+            gen.emitBlackhole(s1);
+            setResult(gen.emitMove(s1));
+        }
+
+        private static PrimitiveConstant getConstant(LIRKind srcKind, Value value) {
+
+            switch ((Kind) srcKind.getPlatformKind()) {
+                case Byte:
+                    return JavaConstant.forByte((byte) asConstant(value).asInt());
+                default:
+                    throw JVMCIError.shouldNotReachHere("Kind not supported: " + srcKind);
+            }
+        }
+    }
+
+    private static final LoadConstantStackSpec stackCopyByte = new LoadConstantStackSpec(LIRKind.value(Kind.Int), LIRKind.value(Kind.Byte));
+
+    @LIRIntrinsic
+    public static byte testCopyByte(@SuppressWarnings("unused") LoadConstantStackSpec spec, byte value) {
+        return value;
+    }
+
+    public byte testByte(byte value) {
+        return testCopyByte(stackCopyByte, value);
+    }
+
+    @Test
+    public void runByte() throws Throwable {
+        runTest("testByte", (byte) 0);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LiveValueSet.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, 2015, 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.lir.dfa;
+
+import jdk.internal.jvmci.meta.*;
+
+abstract class LiveValueSet<S extends LiveValueSet<S>> {
+
+    public abstract void put(Value v);
+
+    public abstract void remove(Value v);
+
+    public abstract void putAll(S s);
+
+    public abstract S copy();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LocationMarker.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2014, 2015, 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.lir.dfa;
+
+import static jdk.internal.jvmci.code.ValueUtil.*;
+
+import java.util.*;
+
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.debug.*;
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.framemap.*;
+
+public abstract class LocationMarker<T extends AbstractBlockBase<T>, S extends LiveValueSet<S>> {
+
+    private final LIR lir;
+    private final BlockMap<S> liveInMap;
+    private final BlockMap<S> liveOutMap;
+
+    protected final FrameMap frameMap;
+
+    protected LocationMarker(LIR lir, FrameMap frameMap) {
+        this.lir = lir;
+        this.frameMap = frameMap;
+        liveInMap = new BlockMap<>(lir.getControlFlowGraph());
+        liveOutMap = new BlockMap<>(lir.getControlFlowGraph());
+    }
+
+    protected abstract S newLiveValueSet();
+
+    protected abstract boolean shouldProcessValue(Value operand);
+
+    protected abstract void processState(LIRInstruction op, LIRFrameState info, S values);
+
+    @SuppressWarnings("unchecked")
+    void build() {
+        UniqueWorkList<T> worklist = new UniqueWorkList<>(lir.getControlFlowGraph().getBlocks().size());
+        for (int i = lir.getControlFlowGraph().getBlocks().size() - 1; i >= 0; i--) {
+            worklist.add((T) lir.getControlFlowGraph().getBlocks().get(i));
+        }
+        for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
+            liveInMap.put(block, newLiveValueSet());
+        }
+        while (!worklist.isEmpty()) {
+            AbstractBlockBase<T> block = worklist.poll();
+            processBlock(block, worklist);
+        }
+    }
+
+    /**
+     * Merge outSet with in-set of successors.
+     */
+    private boolean updateOutBlock(AbstractBlockBase<T> block) {
+        S union = newLiveValueSet();
+        for (T succ : block.getSuccessors()) {
+            union.putAll(liveInMap.get(succ));
+        }
+        S outSet = liveOutMap.get(block);
+        // check if changed
+        if (outSet == null || !union.equals(outSet)) {
+            liveOutMap.put(block, union);
+            return true;
+        }
+        return false;
+    }
+
+    private void processBlock(AbstractBlockBase<T> block, UniqueWorkList<T> worklist) {
+        if (updateOutBlock(block)) {
+            try (Indent indent = Debug.logAndIndent("handle block %s", block)) {
+                currentSet = liveOutMap.get(block).copy();
+                List<LIRInstruction> instructions = lir.getLIRforBlock(block);
+                for (int i = instructions.size() - 1; i >= 0; i--) {
+                    LIRInstruction inst = instructions.get(i);
+                    processInstructionBottomUp(inst);
+                }
+                liveInMap.put(block, currentSet);
+                currentSet = null;
+                worklist.addAll(block.getPredecessors());
+            }
+        }
+    }
+
+    private static final EnumSet<OperandFlag> REGISTER_FLAG_SET = EnumSet.of(OperandFlag.REG);
+    private static final LIRKind REFERENCE_KIND = LIRKind.reference(Kind.Object);
+
+    private S currentSet;
+
+    /**
+     * Process all values of an instruction bottom-up, i.e. definitions before usages. Values that
+     * start or end at the current operation are not included.
+     */
+    private void processInstructionBottomUp(LIRInstruction op) {
+        try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) {
+            // kills
+
+            op.visitEachTemp(defConsumer);
+            op.visitEachOutput(defConsumer);
+            if (frameMap != null && op.destroysCallerSavedRegisters()) {
+                for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) {
+                    defConsumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET);
+                }
+            }
+
+            // gen - values that are considered alive for this state
+            op.visitEachAlive(useConsumer);
+            op.visitEachState(useConsumer);
+            // mark locations
+            op.forEachState(stateConsumer);
+            // gen
+            op.visitEachInput(useConsumer);
+        }
+    }
+
+    InstructionStateProcedure stateConsumer = new InstructionStateProcedure() {
+        public void doState(LIRInstruction inst, LIRFrameState info) {
+            processState(inst, info, currentSet);
+        }
+    };
+
+    ValueConsumer useConsumer = new ValueConsumer() {
+        public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+            if (shouldProcessValue(operand)) {
+                // no need to insert values and derived reference
+                if (Debug.isLogEnabled()) {
+                    Debug.log("set operand: %s", operand);
+                }
+                currentSet.put(operand);
+            }
+        }
+    };
+
+    ValueConsumer defConsumer = new ValueConsumer() {
+        public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+            if (shouldProcessValue(operand)) {
+                if (Debug.isLogEnabled()) {
+                    Debug.log("clear operand: %s", operand);
+                }
+                currentSet.remove(operand);
+            } else {
+                assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format("Illegal PlatformKind is only allowed for TEMP mode: %s, %s",
+                                operand, mode);
+            }
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LocationMarkerPhase.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014, 2015, 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.lir.dfa;
+
+import static jdk.internal.jvmci.code.ValueUtil.*;
+
+import java.util.*;
+
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.compiler.common.alloc.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.framemap.*;
+import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory;
+import com.oracle.graal.lir.phases.*;
+
+/**
+ * Mark all live references for a frame state. The frame state use this information to build the OOP
+ * maps.
+ */
+public final class LocationMarkerPhase extends AllocationPhase {
+
+    @Override
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
+        new Marker<B>(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build();
+    }
+
+    private static final class Marker<T extends AbstractBlockBase<T>> extends LocationMarker<T, Marker<T>.RegStackValueSet> {
+
+        private final class RegStackValueSet extends LiveValueSet<Marker<T>.RegStackValueSet> {
+
+            private final ValueSet registers;
+            private final ValueSet stack;
+            private Set<Value> extraStack;
+
+            public RegStackValueSet() {
+                registers = new ValueSet();
+                stack = new ValueSet();
+            }
+
+            private RegStackValueSet(RegStackValueSet s) {
+                registers = new ValueSet(s.registers);
+                stack = new ValueSet(s.stack);
+                if (s.extraStack != null) {
+                    extraStack = new HashSet<>(s.extraStack);
+                }
+            }
+
+            @Override
+            public Marker<T>.RegStackValueSet copy() {
+                return new RegStackValueSet(this);
+            }
+
+            @Override
+            public void put(Value v) {
+                if (isRegister(v)) {
+                    int index = asRegister(v).getReferenceMapIndex();
+                    registers.put(index, v);
+                } else if (isStackSlot(v)) {
+                    int index = frameMap.offsetForStackSlot(asStackSlot(v));
+                    assert index >= 0;
+                    if (index % 4 == 0) {
+                        stack.put(index / 4, v);
+                    } else {
+                        if (extraStack == null) {
+                            extraStack = new HashSet<>();
+                        }
+                        extraStack.add(v);
+                    }
+                }
+            }
+
+            @Override
+            public void putAll(RegStackValueSet v) {
+                registers.putAll(v.registers);
+                stack.putAll(v.stack);
+                if (v.extraStack != null) {
+                    if (extraStack == null) {
+                        extraStack = new HashSet<>();
+                    }
+                    extraStack.addAll(v.extraStack);
+                }
+            }
+
+            @Override
+            public void remove(Value v) {
+                if (isRegister(v)) {
+                    int index = asRegister(v).getReferenceMapIndex();
+                    registers.put(index, null);
+                } else if (isStackSlot(v)) {
+                    int index = frameMap.offsetForStackSlot(asStackSlot(v));
+                    assert index >= 0;
+                    if (index % 4 == 0) {
+                        stack.put(index / 4, null);
+                    } else if (extraStack != null) {
+                        extraStack.remove(v);
+                    }
+                }
+            }
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public boolean equals(Object obj) {
+                if (obj instanceof Marker.RegStackValueSet) {
+                    RegStackValueSet other = (RegStackValueSet) obj;
+                    return registers.equals(other.registers) && stack.equals(other.stack) && Objects.equals(extraStack, other.extraStack);
+                } else {
+                    return false;
+                }
+            }
+
+            @Override
+            public int hashCode() {
+                throw new UnsupportedOperationException();
+            }
+
+            public void addLiveValues(ReferenceMapBuilder refMap) {
+                registers.addLiveValues(refMap);
+                stack.addLiveValues(refMap);
+                if (extraStack != null) {
+                    for (Value v : extraStack) {
+                        refMap.addLiveValue(v);
+                    }
+                }
+            }
+        }
+
+        private final RegisterAttributes[] registerAttributes;
+
+        private Marker(LIR lir, FrameMap frameMap) {
+            super(lir, frameMap);
+            this.registerAttributes = frameMap.getRegisterConfig().getAttributesMap();
+        }
+
+        @Override
+        protected Marker<T>.RegStackValueSet newLiveValueSet() {
+            return new RegStackValueSet();
+        }
+
+        @Override
+        protected boolean shouldProcessValue(Value operand) {
+            return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal;
+        }
+
+        /**
+         * This method does the actual marking.
+         */
+        @Override
+        protected void processState(LIRInstruction op, LIRFrameState info, RegStackValueSet values) {
+            if (!info.hasDebugInfo()) {
+                info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !frameMap.getRegisterConfig().areAllAllocatableRegistersCallerSaved());
+            }
+
+            ReferenceMapBuilder refMap = frameMap.newReferenceMapBuilder();
+            frameMap.addLiveValues(refMap);
+            values.addLiveValues(refMap);
+
+            info.debugInfo().setReferenceMap(refMap.finish(info));
+        }
+
+        /**
+         * Gets an object describing the attributes of a given register according to this register
+         * configuration.
+         */
+        private RegisterAttributes attributes(Register reg) {
+            return registerAttributes[reg.number];
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/MarkBasePointersPhase.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015, 2015, 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.lir.dfa;
+
+import java.util.*;
+
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.compiler.common.alloc.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.framemap.*;
+import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory;
+import com.oracle.graal.lir.phases.*;
+
+/**
+ * Record all derived reference base pointers in a frame state.
+ */
+public final class MarkBasePointersPhase extends AllocationPhase {
+
+    @Override
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
+        new Marker<B>(lirGenRes.getLIR(), null).build();
+    }
+
+    private static final class Marker<T extends AbstractBlockBase<T>> extends LocationMarker<T, Marker<T>.BasePointersSet> {
+
+        private final class BasePointersSet extends LiveValueSet<Marker<T>.BasePointersSet> {
+
+            private final ValueSet variables;
+
+            public BasePointersSet() {
+                variables = new ValueSet();
+            }
+
+            private BasePointersSet(BasePointersSet s) {
+                variables = new ValueSet(s.variables);
+            }
+
+            @Override
+            public Marker<T>.BasePointersSet copy() {
+                return new BasePointersSet(this);
+            }
+
+            @Override
+            public void put(Value v) {
+                Variable base = (Variable) v.getLIRKind().getDerivedReferenceBase();
+                variables.put(base.index, base);
+            }
+
+            @Override
+            public void putAll(BasePointersSet v) {
+                variables.putAll(v.variables);
+            }
+
+            @Override
+            public void remove(Value v) {
+                Variable base = (Variable) v.getLIRKind().getDerivedReferenceBase();
+                variables.put(base.index, null);
+            }
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public boolean equals(Object obj) {
+                if (obj instanceof Marker.BasePointersSet) {
+                    BasePointersSet other = (BasePointersSet) obj;
+                    return variables.equals(other.variables);
+                } else {
+                    return false;
+                }
+            }
+
+            @Override
+            public int hashCode() {
+                throw new UnsupportedOperationException();
+            }
+        }
+
+        private Marker(LIR lir, FrameMap frameMap) {
+            super(lir, frameMap);
+        }
+
+        @Override
+        protected Marker<T>.BasePointersSet newLiveValueSet() {
+            return new BasePointersSet();
+        }
+
+        @Override
+        protected boolean shouldProcessValue(Value operand) {
+            return operand.getLIRKind().isDerivedReference();
+        }
+
+        @Override
+        protected void processState(LIRInstruction op, LIRFrameState info, BasePointersSet values) {
+            info.setLiveBasePointers(new ValueSet(values.variables));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/UniqueWorkList.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2015, 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.lir.dfa;
+
+import java.util.*;
+
+import com.oracle.graal.compiler.common.cfg.*;
+
+/**
+ * Ensures that an element is only in the worklist once.
+ *
+ * @param <T>
+ */
+class UniqueWorkList<T extends AbstractBlockBase<T>> extends ArrayDeque<T> {
+    private static final long serialVersionUID = 8009554570990975712L;
+    BitSet valid;
+
+    public UniqueWorkList(int size) {
+        this.valid = new BitSet(size);
+    }
+
+    @Override
+    public T poll() {
+        T result = super.poll();
+        if (result != null) {
+            valid.set(result.getId(), false);
+        }
+        return result;
+    }
+
+    @Override
+    public boolean add(T pred) {
+        if (!valid.get(pred.getId())) {
+            valid.set(pred.getId(), true);
+            return super.add(pred);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends T> collection) {
+        boolean changed = false;
+        for (T element : collection) {
+            if (!valid.get(element.getId())) {
+                valid.set(element.getId(), true);
+                super.add(element);
+                changed = true;
+            }
+        }
+        return changed;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/ValueSet.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2014, 2015, 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.lir.dfa;
+
+import java.util.*;
+
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.framemap.*;
+
+public final class ValueSet {
+    private Value[] values;
+
+    ValueSet() {
+        values = Value.NO_VALUES;
+    }
+
+    ValueSet(ValueSet other) {
+        int limit = other.values.length;
+        while (limit > 0) {
+            if (other.values[limit - 1] == null) {
+                limit--;
+                continue;
+            }
+            break;
+        }
+        values = new Value[limit];
+        System.arraycopy(other.values, 0, values, 0, values.length);
+    }
+
+    public Value get(int index) {
+        return values[index];
+    }
+
+    void put(int index, Value value) {
+        if (value != null && value.getLIRKind().isValue()) {
+            return;
+        }
+        if (values.length <= index) {
+            if (value == null) {
+                return;
+            }
+            Value[] newValues = new Value[index + 1];
+            System.arraycopy(values, 0, newValues, 0, values.length);
+            values = newValues;
+            values[index] = value;
+        } else {
+            values[index] = value;
+        }
+    }
+
+    public void putAll(ValueSet stack) {
+        Value[] otherValues = stack.values;
+        int limit = otherValues.length;
+        if (limit > values.length) {
+            while (limit > 0) {
+                if (otherValues[limit - 1] == null) {
+                    limit--;
+                    continue;
+                }
+                break;
+            }
+            if (limit > values.length) {
+                Value[] newValues = new Value[limit];
+                System.arraycopy(values, 0, newValues, 0, values.length);
+                values = newValues;
+            }
+        }
+        for (int i = 0; i < limit; i++) {
+            Value value = otherValues[i];
+            if (value != null) {
+                values[i] = value;
+            }
+        }
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof ValueSet) {
+            ValueSet that = (ValueSet) other;
+            int limit = Math.min(values.length, that.values.length);
+            for (int i = 0; i < limit; i++) {
+                if (!Objects.equals(values[i], that.values[i])) {
+                    return false;
+                }
+            }
+            for (int i = limit; i < values.length; i++) {
+                if (values[i] != null) {
+                    return false;
+                }
+            }
+            for (int i = limit; i < that.values.length; i++) {
+                if (that.values[i] != null) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public void addLiveValues(ReferenceMapBuilder refMap) {
+        for (Value v : values) {
+            if (v != null) {
+                refMap.addLiveValue(v);
+            }
+        }
+    }
+
+    public void forEach(LIRInstruction inst, OperandMode mode, EnumSet<OperandFlag> flags, InstructionValueProcedure proc) {
+        for (int i = 0; i < values.length; i++) {
+            if (values[i] != null) {
+                values[i] = proc.doValue(inst, values[i], mode, flags);
+            }
+        }
+    }
+
+    public void forEach(LIRInstruction inst, OperandMode mode, EnumSet<OperandFlag> flags, InstructionValueConsumer consumer) {
+        for (Value v : values) {
+            if (v != null) {
+                consumer.visitValue(inst, v, mode, flags);
+            }
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("[");
+        boolean comma = false;
+
+        for (int i = 0; i < values.length; i++) {
+            if (values[i] != null) {
+                if (comma) {
+                    sb.append(", ");
+                } else {
+                    comma = true;
+                }
+
+                sb.append(i);
+                sb.append(": ");
+                sb.append(values[i]);
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/ReferenceMapBuilder.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 2015, 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.lir.framemap;
+
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.lir.*;
+
+public abstract class ReferenceMapBuilder {
+
+    public abstract void addLiveValue(Value value);
+
+    public abstract ReferenceMap finish(LIRFrameState state);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CanonicalizableLocation.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.memory.address.*;
+
+public interface CanonicalizableLocation {
+    ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeValueMap.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, 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.nodes.spi;
+
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+public interface NodeValueMap {
+
+    /**
+     * Returns the operand that has been previously initialized by
+     * {@link #setResult(ValueNode, Value)} with the result of an instruction. It's a code
+     * generation error to ask for the operand of ValueNode that doesn't have one yet.
+     *
+     * @param node A node that produces a result value.
+     */
+    Value operand(Node node);
+
+    /**
+     * @return {@code true} if there is an {@link Value operand} associated with the {@code node} in
+     *         the current block.
+     */
+    boolean hasOperand(Node node);
+
+    /**
+     * Associates {@code operand} with the {@code node} in the current block.
+     *
+     * @return {@code operand}
+     */
+    Value setResult(ValueNode node, Value operand);
+
+    /**
+     * Gets the the {@link ValueNode} that produced a {@code value}. If the {@code value} is not
+     * associated with a {@link ValueNode} {@code null} is returned.
+     *
+     * This method is intended for debugging purposes only.
+     */
+    ValueNode valueForOperand(Value value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EnsureVirtualizedNode.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.virtual;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
+
+@NodeInfo
+public final class EnsureVirtualizedNode extends FixedWithNextNode implements Virtualizable, Lowerable {
+
+    public static final NodeClass<EnsureVirtualizedNode> TYPE = NodeClass.create(EnsureVirtualizedNode.class);
+
+    @Input ValueNode object;
+    private final boolean localOnly;
+
+    public EnsureVirtualizedNode(ValueNode object, boolean localOnly) {
+        super(TYPE, StampFactory.forVoid());
+        this.object = object;
+        this.localOnly = localOnly;
+    }
+
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(object);
+        if (state != null && state.getState() == EscapeState.Virtual) {
+            if (state.getVirtualObject() instanceof VirtualBoxingNode) {
+                Throwable exception = new VerificationError("ensureVirtual is not valid for boxing objects: %s", state.getVirtualObject().type().getName());
+                throw GraphUtil.approxSourceException(this, exception);
+            }
+            if (!localOnly) {
+                state.setEnsureVirtualized(true);
+            }
+            tool.delete();
+        }
+    }
+
+    public void lower(LoweringTool tool) {
+        ensureVirtualFailure(this, object.stamp());
+    }
+
+    public static void ensureVirtualFailure(Node location, Stamp stamp) {
+        Throwable exception = new VerificationError("Object should not be materialized (stamp=%s):", stamp);
+        throw GraphUtil.approxSourceException(location, exception);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DerivedOopTest.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2015, 2015, 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.replacements.test;
+
+import java.util.*;
+
+import jdk.internal.jvmci.meta.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.directives.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.word.*;
+import com.oracle.graal.word.nodes.*;
+
+/**
+ * Tests for derived oops in reference maps.
+ */
+public class DerivedOopTest extends GraalCompilerTest implements Snippets {
+
+    private static class Pointers {
+        public long basePointer;
+        public long internalPointer;
+
+        public long delta() {
+            return internalPointer - basePointer;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof Pointers)) {
+                return false;
+            }
+
+            Pointers other = (Pointers) obj;
+            return this.delta() == other.delta();
+        }
+
+        @Override
+        public int hashCode() {
+            return (int) delta();
+        }
+    }
+
+    private static class Result {
+        public Pointers beforeGC;
+        public Pointers afterGC;
+
+        public Result() {
+            beforeGC = new Pointers();
+            afterGC = new Pointers();
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((afterGC == null) ? 0 : afterGC.hashCode());
+            result = prime * result + ((beforeGC == null) ? 0 : beforeGC.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof Result)) {
+                return false;
+            }
+            Result other = (Result) obj;
+            return Objects.equals(this.beforeGC, other.beforeGC) && Objects.equals(this.afterGC, other.afterGC);
+        }
+    }
+
+    @Test
+    public void testFieldOffset() {
+        Result r = new Result();
+        test("fieldOffsetSnippet", r, 16L);
+
+        Assert.assertEquals(r.beforeGC.delta(), r.afterGC.delta());
+    }
+
+    static long getRawPointer(Object obj) {
+        // fake implementation for interpreter
+        return obj.hashCode();
+    }
+
+    static long getRawPointerIntrinsic(Object obj) {
+        return Word.fromObject(obj).rawValue();
+    }
+
+    public static Result fieldOffsetSnippet(Result obj, long offset) {
+        long internalPointer = getRawPointer(obj) + offset;
+
+        // make sure the internal pointer is computed before the safepoint
+        GraalDirectives.blackhole(internalPointer);
+
+        obj.beforeGC.basePointer = getRawPointer(obj);
+        obj.beforeGC.internalPointer = internalPointer;
+
+        System.gc();
+
+        obj.afterGC.basePointer = getRawPointer(obj);
+        obj.afterGC.internalPointer = internalPointer;
+
+        return obj;
+    }
+
+    @Override
+    protected Plugins getDefaultGraphBuilderPlugins() {
+        Plugins plugins = super.getDefaultGraphBuilderPlugins();
+        Registration r = new Registration(plugins.getInvocationPlugins(), DerivedOopTest.class);
+
+        ResolvedJavaMethod intrinsic = getResolvedJavaMethod("getRawPointerIntrinsic");
+        r.register1("getRawPointer", Object.class, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) {
+                b.intrinsify(targetMethod, intrinsic, new ValueNode[]{arg});
+                return true;
+            }
+        });
+
+        return plugins;
+    }
+
+    @Override
+    protected boolean checkHighTierGraph(StructuredGraph graph) {
+        assert graph.getNodes().filter(WordCastNode.class).count() > 0 : "DerivedOopTest.toLong should be intrinsified";
+        return super.checkHighTierGraph(graph);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.sl.disable	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,21 @@
+/* 
+ * This tests that simple arithmetic gets inlined.
+ */
+function add(a, b) {
+    deoptimizeWhenCompiled(a == 50); 
+    return a + b;
+}
+
+
+function test() {
+    i = 0;
+    while (i < 100) {
+        i = add(i, 1);
+    }
+    return i;
+}
+
+function main() {
+    waitForOptimization(callUntilOptimized(test, 1 == 2));
+    test();
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/MockLanguage.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test;
+
+import com.oracle.truffle.api.TruffleLanguage;
+
+public abstract class MockLanguage extends TruffleLanguage {
+    public MockLanguage(Env env) {
+        super(env);
+    }
+}
--- a/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/BytecodeFrame.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/BytecodeFrame.java	Tue Jul 21 16:15:22 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, 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
@@ -197,7 +197,7 @@
                     assert values.length > i + 1 : String.format("missing second word %s", this);
                     assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal : this;
                 }
-                assert derivedOk || ValueUtil.isIllegal(values[i]) || !values[i].getLIRKind().isDerivedReference() : "Unexpected derived value: " + values[i];
+                assert derivedOk || ValueUtil.isIllegal(values[i]) || !values[i].getLIRKind().isUnknownReference() : "Unexpected derived value: " + values[i];
             }
         }
         return true;
--- a/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/DebugInfo.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/DebugInfo.java	Tue Jul 21 16:15:22 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, 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
@@ -24,8 +24,6 @@
 
 import java.util.*;
 
-import jdk.internal.jvmci.meta.*;
-
 /**
  * Represents the debugging information for a particular point of execution. This information
  * includes:
@@ -41,8 +39,8 @@
 public final class DebugInfo {
 
     private final BytecodePosition bytecodePosition;
-    private final ReferenceMap referenceMap;
-    @SuppressWarnings("unused") private final Value[] virtualObjectMapping;
+    private ReferenceMap referenceMap;
+    @SuppressWarnings("unused") private final VirtualObject[] virtualObjectMapping;
     private RegisterSaveLayout calleeSaveInfo;
 
     /**
@@ -50,17 +48,19 @@
      *
      * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame
      *            frame} info
-     * @param referenceMap the reference map
      * @param virtualObjectMapping the mapping of {@link VirtualObject}s to their real values
      */
-    public DebugInfo(BytecodePosition codePos, ReferenceMap referenceMap, Value[] virtualObjectMapping) {
+    public DebugInfo(BytecodePosition codePos, VirtualObject[] virtualObjectMapping) {
         this.bytecodePosition = codePos;
-        this.referenceMap = referenceMap;
         this.virtualObjectMapping = virtualObjectMapping;
     }
 
     public DebugInfo(BytecodePosition codePos) {
-        this(codePos, null, null);
+        this(codePos, null);
+    }
+
+    public void setReferenceMap(ReferenceMap referenceMap) {
+        this.referenceMap = referenceMap;
     }
 
     /**
--- a/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/ReferenceMap.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/ReferenceMap.java	Tue Jul 21 16:15:22 2015 +0200
@@ -22,24 +22,5 @@
  */
 package jdk.internal.jvmci.code;
 
-import jdk.internal.jvmci.meta.*;
-
 public abstract class ReferenceMap {
-
-    /**
-     * Empty out the reference map.
-     */
-    public abstract void reset();
-
-    /**
-     * Add {@code value} to the current set of reference values.
-     *
-     * @param v
-     */
-    public abstract void addLiveValue(Value v);
-
-    /**
-     * Perform any final encoding needed before use.
-     */
-    public abstract void finish();
 }
--- a/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/TargetDescription.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/TargetDescription.java	Tue Jul 21 16:15:22 2015 +0200
@@ -29,7 +29,7 @@
  * Represents the target machine for a compiler, including the CPU architecture, the size of
  * pointers and references, alignment of stacks, caches, etc.
  */
-public abstract class TargetDescription {
+public class TargetDescription {
 
     public final Architecture arch;
 
@@ -136,6 +136,4 @@
                 return LIRKind.Illegal;
         }
     }
-
-    public abstract ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount, int totalFrameSize);
 }
--- a/jvmci/jdk.internal.jvmci.hotspot.amd64/src/jdk/internal/jvmci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot.amd64/src/jdk/internal/jvmci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Tue Jul 21 16:15:22 2015 +0200
@@ -103,7 +103,7 @@
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = true;
-        return new HotSpotTargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        return new TargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
     protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) {
--- a/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Tue Jul 21 16:15:22 2015 +0200
@@ -44,7 +44,7 @@
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = false;
-        return new HotSpotTargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        return new TargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
     protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
--- a/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Tue Jul 21 16:15:22 2015 +0200
@@ -110,7 +110,8 @@
                         // and the current register handler would ignore this fact if the called
                         // method still does not modify registers, in fact o7 is modified by the Call instruction
                         // There would be some extra handlin necessary to be able to handle the o7 properly for local usage
-                        o0, o1, o2, o3, o4, o5, /*o6, o7,*/
+                        g1, g4, g5,
+                        o0, o1, o2, o3, o4, o5, /*o6,o7,*/
                         l0, l1, l2, l3, l4, l5, l6, l7,
                         i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
                         //f0, f1, f2, f3, f4, f5, f6, f7,
@@ -125,6 +126,7 @@
             // @formatter:off
             registers = new Register[]{
                         // TODO this is not complete
+                        g1, g4, g5,
                         o0, o1, o2, o3, o4, o5, /*o6, o7,*/
                         l0, l1, l2, l3, l4, l5, l6, l7,
                         i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/CompilerToVMImpl.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/CompilerToVMImpl.java	Tue Jul 21 16:15:22 2015 +0200
@@ -25,6 +25,7 @@
 
 import static jdk.internal.jvmci.hotspot.InitTimer.*;
 import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.common.*;
 import jdk.internal.jvmci.meta.*;
 
 /**
@@ -72,19 +73,39 @@
 
     public native Object resolveConstantInPool(long metaspaceConstantPool, int cpi);
 
-    public native Object resolvePossiblyCachedConstantInPool(long metaspaceConstantPool, int cpi);
+    public Object resolvePossiblyCachedConstantInPool(long metaspaceConstantPool, int cpi) {
+        JVMCIError.guarantee(!HotSpotConstantPool.Options.UseConstantPoolCacheJavaCode.getValue(), "");
+        return resolvePossiblyCachedConstantInPool0(metaspaceConstantPool, cpi);
+    }
+
+    private native Object resolvePossiblyCachedConstantInPool0(long metaspaceConstantPool, int cpi);
 
     @Override
     public native int lookupNameAndTypeRefIndexInPool(long metaspaceConstantPool, int cpi);
 
     @Override
-    public native String lookupNameRefInPool(long metaspaceConstantPool, int cpi);
+    public String lookupNameRefInPool(long metaspaceConstantPool, int cpi) {
+        JVMCIError.guarantee(!HotSpotConstantPool.Options.UseConstantPoolCacheJavaCode.getValue(), "");
+        return lookupNameRefInPool0(metaspaceConstantPool, cpi);
+    }
+
+    private native String lookupNameRefInPool0(long metaspaceConstantPool, int cpi);
 
     @Override
-    public native String lookupSignatureRefInPool(long metaspaceConstantPool, int cpi);
+    public String lookupSignatureRefInPool(long metaspaceConstantPool, int cpi) {
+        JVMCIError.guarantee(!HotSpotConstantPool.Options.UseConstantPoolCacheJavaCode.getValue(), "");
+        return lookupSignatureRefInPool0(metaspaceConstantPool, cpi);
+    }
+
+    private native String lookupSignatureRefInPool0(long metaspaceConstantPool, int cpi);
 
     @Override
-    public native int lookupKlassRefIndexInPool(long metaspaceConstantPool, int cpi);
+    public int lookupKlassRefIndexInPool(long metaspaceConstantPool, int cpi) {
+        JVMCIError.guarantee(!HotSpotConstantPool.Options.UseConstantPoolCacheJavaCode.getValue(), "");
+        return lookupKlassRefIndexInPool0(metaspaceConstantPool, cpi);
+    }
+
+    private native int lookupKlassRefIndexInPool0(long metaspaceConstantPool, int cpi);
 
     public native long constantPoolKlassAt(long metaspaceConstantPool, int cpi);
 
@@ -97,10 +118,20 @@
     @Override
     public native long resolveField(long metaspaceConstantPool, int cpi, byte opcode, long[] info);
 
-    public native int constantPoolRemapInstructionOperandFromCache(long metaspaceConstantPool, int cpi);
+    public int constantPoolRemapInstructionOperandFromCache(long metaspaceConstantPool, int cpi) {
+        JVMCIError.guarantee(!HotSpotConstantPool.Options.UseConstantPoolCacheJavaCode.getValue(), "");
+        return constantPoolRemapInstructionOperandFromCache0(metaspaceConstantPool, cpi);
+    }
+
+    private native int constantPoolRemapInstructionOperandFromCache0(long metaspaceConstantPool, int cpi);
 
     @Override
-    public native Object lookupAppendixInPool(long metaspaceConstantPool, int cpi);
+    public Object lookupAppendixInPool(long metaspaceConstantPool, int cpi) {
+        JVMCIError.guarantee(!HotSpotConstantPool.Options.UseConstantPoolCacheJavaCode.getValue(), "");
+        return lookupAppendixInPool0(metaspaceConstantPool, cpi);
+    }
+
+    private native Object lookupAppendixInPool0(long metaspaceConstantPool, int cpi);
 
     @Override
     public native void initializeConfiguration(HotSpotVMConfig config);
@@ -191,7 +222,12 @@
 
     public native long getTimeStamp();
 
-    public native String getSymbol(long metaspaceSymbol);
+    public String getSymbol(long metaspaceSymbol) {
+        JVMCIError.guarantee(!HotSpotConstantPool.Options.UseConstantPoolCacheJavaCode.getValue(), "");
+        return getSymbol0(metaspaceSymbol);
+    }
+
+    private native String getSymbol0(long metaspaceSymbol);
 
     public native void resolveInvokeDynamic(long metaspaceConstantPool, int index);
 
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotConstantPool.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotConstantPool.java	Tue Jul 21 16:15:22 2015 +0200
@@ -26,15 +26,24 @@
 import static jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime.*;
 
 import java.lang.invoke.*;
+import java.util.*;
 
 import jdk.internal.jvmci.common.*;
 import jdk.internal.jvmci.meta.*;
+import jdk.internal.jvmci.options.*;
 
 /**
  * Implementation of {@link ConstantPool} for HotSpot.
  */
 public class HotSpotConstantPool implements ConstantPool, HotSpotProxified {
 
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Use Java code to access the constant pool cache and resolved references array", type = OptionType.Expert)
+        public static final OptionValue<Boolean> UseConstantPoolCacheJavaCode = new OptionValue<>(false);
+        // @formatter:on
+    }
+
     /**
      * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}.
      */
@@ -179,8 +188,232 @@
     private final long metaspaceConstantPool;
     private volatile LookupTypeCacheElement lastLookupType;
 
+    /**
+     * The constant pool cache of this constant pool.
+     */
+    private final Cache cache;
+
+    /**
+     * Represents a {@code ConstantPoolCache}. The cache needs to be lazy since the constant pool
+     * cache is created when the methods of this class are rewritten and rewriting happens when the
+     * class is linked.
+     */
+    private final class Cache {
+
+        private long address;
+
+        public Cache() {
+            // Maybe the constant pool cache already exists...
+            queryAddress();
+        }
+
+        /**
+         * Queries the current value of {@code ConstantPool::_cache} if the current address is null.
+         */
+        private void queryAddress() {
+            if (address == 0) {
+                address = unsafe.getAddress(metaspaceConstantPool + runtime().getConfig().constantPoolCacheOffset);
+            }
+        }
+
+        /**
+         * Returns whether a constant pool cache for this constant pool exists.
+         *
+         * @return true if it exists, false otherwise
+         */
+        public boolean exists() {
+            queryAddress();
+            return address != 0;
+        }
+
+        /**
+         * Represents a {@code ConstantPoolCacheEntry}.
+         */
+        private final class Entry {
+
+            private final long address;
+
+            public Entry(final long address) {
+                this.address = address;
+            }
+
+            /**
+             * {@code ConstantPoolCacheEntry::_indices} is volatile of type {@code intx}.
+             *
+             * @return value of field {@code _indices}
+             */
+            private long getIndices() {
+                assert runtime().getHostJVMCIBackend().getTarget().wordSize == 8 : "port to non-64-bit platform";
+                return unsafe.getLongVolatile(null, address + runtime().getConfig().constantPoolCacheEntryIndicesOffset);
+            }
+
+            /**
+             * {@code ConstantPoolCacheEntry::_f1} is volatile of type {@code Metadata*}.
+             *
+             * @return value of field {@code _f1}
+             */
+            private long getF1() {
+                assert runtime().getHostJVMCIBackend().getTarget().wordSize == 8 : "port to non-64-bit platform";
+                return unsafe.getLongVolatile(null, address + runtime().getConfig().constantPoolCacheEntryF1Offset);
+            }
+
+            /**
+             * {@code ConstantPoolCacheEntry::_f2} is volatile of type {@code intx}.
+             *
+             * @return value of field {@code _f2}
+             */
+            private long getF2() {
+                assert runtime().getHostJVMCIBackend().getTarget().wordSize == 8 : "port to non-64-bit platform";
+                return unsafe.getLongVolatile(null, address + runtime().getConfig().constantPoolCacheEntryF2Offset);
+            }
+
+            /**
+             * {@code ConstantPoolCacheEntry::_flags} is volatile of type {@code intx}.
+             *
+             * @return flag bits
+             */
+            private long flags() {
+                assert runtime().getHostJVMCIBackend().getTarget().wordSize == 8 : "port to non-64-bit platform";
+                return unsafe.getLongVolatile(null, address + runtime().getConfig().constantPoolCacheEntryFlagsOffset);
+            }
+
+            private boolean isF1Null() {
+                final long f1 = getF1();
+                return f1 == 0;
+            }
+
+            /**
+             * Returns the constant pool index for this entry. See
+             * {@code ConstantPoolCacheEntry::constant_pool_index()}
+             *
+             * @return the constant pool index for this entry
+             */
+            public int getConstantPoolIndex() {
+                return ((int) getIndices()) & runtime().getConfig().constantPoolCacheEntryCpIndexMask;
+            }
+
+            /**
+             * See {@code ConstantPoolCache::has_appendix()}.
+             *
+             * @return true if there is an appendix, false otherwise
+             */
+            private boolean hasAppendix() {
+                return (!isF1Null()) && (flags() & (1 << runtime().getConfig().constantPoolCacheEntryHasAppendixShift)) != 0;
+            }
+
+            /**
+             * See {@code ConstantPoolCache::appendix_if_resolved()}.
+             */
+            public Object getAppendixIfResolved() {
+                if (!hasAppendix()) {
+                    return null;
+                }
+                final int index = ((int) getF2()) + runtime().getConfig().constantPoolCacheEntryIndyResolvedReferencesAppendixOffset;
+                return resolvedReferences.getArray()[index];
+            }
+        }
+
+        /**
+         * Get the constant pool cache entry at index {@code index}.
+         *
+         * @param index index of entry to return
+         * @return constant pool cache entry at given index
+         */
+        public Entry getEntryAt(int index) {
+            queryAddress();
+            assert exists();
+            HotSpotVMConfig config = runtime().getConfig();
+            return new Entry(address + config.constantPoolCacheSize + config.constantPoolCacheEntrySize * index);
+        }
+
+        /**
+         * Maps the constant pool cache index back to a constant pool index. See
+         * {@code ConstantPool::remap_instruction_operand_from_cache}.
+         *
+         * @param index the constant pool cache index
+         * @return constant pool index
+         */
+        public int constantPoolCacheIndexToConstantPoolIndex(int index) {
+            final int cacheIndex = index - runtime().getConfig().constantPoolCpCacheIndexTag;
+            return getEntryAt(cacheIndex).getConstantPoolIndex();
+        }
+
+    }
+
+    /**
+     * Resolved references of this constant pool.
+     */
+    private final ResolvedReferences resolvedReferences = new ResolvedReferences();
+
+    /**
+     * Hide the resolved references array in a private class so it cannot be accessed directly. The
+     * reason is the resolved references array is created when the constant pool cache is created.
+     *
+     * @see Cache
+     */
+    private final class ResolvedReferences {
+
+        /**
+         * Pointer to the {@code ConstantPool::_resolved_references} array.
+         */
+        private Object[] resolvedReferences;
+
+        /**
+         * Map of constant pool indexes to {@code ConstantPool::_resolved_references} indexes.
+         */
+        private final HashMap<Integer, Integer> referenceMap = new HashMap<>();
+
+        /**
+         * Returns the {@code ConstantPool::_resolved_references} array for this constant pool.
+         *
+         * @return resolved references array if exists, null otherwise
+         */
+        public Object[] getArray() {
+            if (resolvedReferences == null) {
+                final long handle = unsafe.getAddress(metaspaceConstantPool + runtime().getConfig().constantPoolResolvedReferencesOffset);
+                if (handle != 0) {
+                    resolvedReferences = (Object[]) runtime().getCompilerToVM().readUncompressedOop(handle + runtime().getConfig().handleHandleOffset);
+                    fillReferenceMap();
+                }
+            }
+            return resolvedReferences;
+        }
+
+        /**
+         * Fills the {@link #referenceMap} with all the values from
+         * {@code ConstantPool::_reference_map} for faster lookup.
+         */
+        private void fillReferenceMap() {
+            // It is possible there is a resolved references array but no reference map.
+            final long address = unsafe.getAddress(metaspaceConstantPool + runtime().getConfig().constantPoolReferenceMapOffset);
+            if (address != 0) {
+                final int length = unsafe.getInt(null, address + runtime().getConfig().arrayU1LengthOffset);
+                for (int i = 0; i < length; i++) {
+                    final int value = unsafe.getShort(address + runtime().getConfig().arrayU2DataOffset + i * Short.BYTES);
+                    referenceMap.put(value, i);
+                }
+            }
+        }
+
+        /**
+         * See {@code ConstantPool::cp_to_object_index}.
+         *
+         * @param cpi constant pool index
+         * @return resolved references array index
+         */
+        public int constantPoolIndexToResolvedReferencesIndex(int cpi) {
+            final Integer index = referenceMap.get(cpi);
+            // We might not find the index for jsr292 call.
+            return (index == null) ? -1 : index;
+        }
+
+    }
+
     public HotSpotConstantPool(long metaspaceConstantPool) {
         this.metaspaceConstantPool = metaspaceConstantPool;
+
+        // Cache constructor needs metaspaceConstantPool.
+        cache = new Cache();
     }
 
     /**
@@ -201,7 +434,7 @@
      * @param opcode bytecode to convert the index for
      * @return constant pool index
      */
-    private static int toConstantPoolIndex(int rawIndex, int opcode) {
+    private static int rawIndexToConstantPoolIndex(int rawIndex, int opcode) {
         int index;
         if (opcode == Bytecodes.INVOKEDYNAMIC) {
             index = rawIndex;
@@ -348,7 +581,12 @@
      * @return name as {@link String}
      */
     private String getNameRefAt(int index) {
-        return runtime().getCompilerToVM().lookupNameRefInPool(metaspaceConstantPool, index);
+        if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+            final int nameRefIndex = getNameRefIndexAt(getNameAndTypeRefIndexAt(index));
+            return new HotSpotSymbol(getEntryAt(nameRefIndex)).asString();
+        } else {
+            return runtime().getCompilerToVM().lookupNameRefInPool(metaspaceConstantPool, index);
+        }
     }
 
     /**
@@ -372,7 +610,12 @@
      * @return signature as {@link String}
      */
     private String getSignatureRefAt(int index) {
-        return runtime().getCompilerToVM().lookupSignatureRefInPool(metaspaceConstantPool, index);
+        if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+            final int signatureRefIndex = getSignatureRefIndexAt(getNameAndTypeRefIndexAt(index));
+            return new HotSpotSymbol(getEntryAt(signatureRefIndex)).asString();
+        } else {
+            return runtime().getCompilerToVM().lookupSignatureRefInPool(metaspaceConstantPool, index);
+        }
     }
 
     /**
@@ -389,13 +632,38 @@
     }
 
     /**
-     * Gets the klass reference index constant pool entry at index {@code index}.
+     * Gets the klass reference index constant pool entry at index {@code index}. See
+     * {@code ConstantPool::klass_ref_index_at}.
+     *
+     * @param index constant pool index
+     * @param cached whether to go through the constant pool cache
+     * @return klass reference index
+     */
+    private int getKlassRefIndexAt(int index, boolean cached) {
+        int cpi = index;
+        if (cached && cache.exists()) {
+            // change byte-ordering and go via cache
+            cpi = cache.constantPoolCacheIndexToConstantPoolIndex(index);
+        }
+        assertTagIsFieldOrMethod(cpi);
+        final int refIndex = unsafe.getInt(metaspaceConstantPool + runtime().getConfig().constantPoolSize + cpi * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        // klass ref index is in the low 16-bits.
+        return refIndex & 0xFFFF;
+    }
+
+    /**
+     * Gets the klass reference index constant pool entry at index {@code index}. See
+     * {@code ConstantPool::klass_ref_index_at}.
      *
      * @param index constant pool index
      * @return klass reference index
      */
     private int getKlassRefIndexAt(int index) {
-        return runtime().getCompilerToVM().lookupKlassRefIndexInPool(metaspaceConstantPool, index);
+        if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+            return getKlassRefIndexAt(index, true);
+        } else {
+            return runtime().getCompilerToVM().lookupKlassRefIndexInPool(metaspaceConstantPool, index);
+        }
     }
 
     /**
@@ -406,10 +674,14 @@
      * @return klass reference index
      */
     private int getUncachedKlassRefIndexAt(int index) {
-        assert getTagAt(index) == JVM_CONSTANT.Fieldref || getTagAt(index) == JVM_CONSTANT.MethodRef || getTagAt(index) == JVM_CONSTANT.InterfaceMethodref;
-        final int refIndex = unsafe.getInt(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
-        // klass ref index is in the low 16-bits.
-        return refIndex & 0xFFFF;
+        if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+            return getKlassRefIndexAt(index, false);
+        } else {
+            assertTagIsFieldOrMethod(index);
+            final int refIndex = unsafe.getInt(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+            // klass ref index is in the low 16-bits.
+            return refIndex & 0xFFFF;
+        }
     }
 
     /**
@@ -428,7 +700,19 @@
      * @param tag expected tag
      */
     private void assertTag(int index, JVM_CONSTANT tag) {
-        assert getTagAt(index) == tag : "constant pool tag at index " + index + " is " + getTagAt(index) + " but expected " + tag;
+        final JVM_CONSTANT tagAt = getTagAt(index);
+        assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag;
+    }
+
+    /**
+     * Asserts that the constant pool tag at index {@code index} is a {@link JVM_CONSTANT#Fieldref},
+     * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}.
+     *
+     * @param index constant pool index
+     */
+    private void assertTagIsFieldOrMethod(int index) {
+        final JVM_CONSTANT tagAt = getTagAt(index);
+        assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt;
     }
 
     @Override
@@ -455,7 +739,38 @@
                 final int opcode = -1;  // opcode is not used
                 return lookupType(cpi, opcode);
             case String:
-                Object string = runtime().getCompilerToVM().resolvePossiblyCachedConstantInPool(metaspaceConstantPool, cpi);
+                /*
+                 * Normally, we would expect a String here, but anonymous classes can have
+                 * "pseudo strings" (arbitrary live objects) patched into a String entry. Such
+                 * entries do not have a symbol in the constant pool slot.
+                 */
+                Object string;
+                if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+                    // See: ConstantPool::resolve_constant_at_impl
+                    /*
+                     * Note: Call getArray() before constantPoolIndexToResolvedReferencesIndex()
+                     * because it fills the map if the array exists.
+                     */
+                    Object[] localResolvedReferences = resolvedReferences.getArray();
+                    final int index = resolvedReferences.constantPoolIndexToResolvedReferencesIndex(cpi);
+                    assert index >= 0;
+                    // See: ConstantPool::string_at_impl
+                    string = localResolvedReferences[index];
+                    if (string != null) {
+                        assert string instanceof String || getEntryAt(index) == 0L;
+                        return HotSpotObjectConstantImpl.forObject(string);
+                    } else {
+                        final long metaspaceSymbol = getEntryAt(cpi);
+                        if (metaspaceSymbol != 0L) {
+                            HotSpotSymbol symbol = new HotSpotSymbol(metaspaceSymbol);
+                            string = symbol.asString().intern();
+                            // See: ConstantPool::string_at_put
+                            localResolvedReferences[index] = string;
+                        }
+                    }
+                } else {
+                    string = runtime().getCompilerToVM().resolvePossiblyCachedConstantInPool(metaspaceConstantPool, cpi);
+                }
                 return HotSpotObjectConstantImpl.forObject(string);
             case MethodHandle:
             case MethodHandleInError:
@@ -471,7 +786,18 @@
     @Override
     public String lookupUtf8(int cpi) {
         assertTag(cpi, JVM_CONSTANT.Utf8);
-        return runtime().getCompilerToVM().getSymbol(getEntryAt(cpi));
+        String s;
+        if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+            HotSpotSymbol symbol = new HotSpotSymbol(getEntryAt(cpi));
+            s = symbol.asString();
+            // It shouldn't but just in case something went wrong...
+            if (s == null) {
+                throw JVMCIError.shouldNotReachHere("malformed UTF-8 string in constant pool");
+            }
+        } else {
+            s = runtime().getCompilerToVM().getSymbol(getEntryAt(cpi));
+        }
+        return s;
     }
 
     @Override
@@ -482,12 +808,26 @@
     @Override
     public JavaConstant lookupAppendix(int cpi, int opcode) {
         assert Bytecodes.isInvoke(opcode);
-        final int index = toConstantPoolIndex(cpi, opcode);
-        Object result = runtime().getCompilerToVM().lookupAppendixInPool(metaspaceConstantPool, index);
-        if (result == null) {
+        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
+
+        Object appendix = null;
+
+        if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+            if (!cache.exists()) {
+                // Nothing to load yet.
+                return null;
+            }
+            final int cacheIndex = decodeConstantPoolCacheIndex(index);
+            Cache.Entry entry = cache.getEntryAt(cacheIndex);
+            appendix = entry.getAppendixIfResolved();
+        } else {
+            appendix = runtime().getCompilerToVM().lookupAppendixInPool(metaspaceConstantPool, index);
+        }
+
+        if (appendix == null) {
             return null;
         } else {
-            return HotSpotObjectConstantImpl.forObject(result);
+            return HotSpotObjectConstantImpl.forObject(appendix);
         }
     }
 
@@ -502,7 +842,17 @@
         HotSpotVMConfig config = runtime.getConfig();
         if ((metaspacePointer & config.compilerToVMSymbolTag) != 0) {
             final long metaspaceSymbol = metaspacePointer & ~config.compilerToVMSymbolTag;
-            String name = runtime.getCompilerToVM().getSymbol(metaspaceSymbol);
+            String name;
+            if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+                HotSpotSymbol symbol = new HotSpotSymbol(metaspaceSymbol);
+                name = symbol.asString();
+                // It shouldn't but just in case something went wrong...
+                if (name == null) {
+                    throw JVMCIError.shouldNotReachHere("malformed UTF-8 string in constant pool");
+                }
+            } else {
+                name = runtime.getCompilerToVM().getSymbol(metaspaceSymbol);
+            }
             return HotSpotUnresolvedJavaType.create(runtime(), "L" + name + ";");
         } else {
             assert (metaspacePointer & config.compilerToVMKlassTag) == 0;
@@ -512,7 +862,7 @@
 
     @Override
     public JavaMethod lookupMethod(int cpi, int opcode) {
-        final int index = toConstantPoolIndex(cpi, opcode);
+        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
         final long metaspaceMethod = runtime().getCompilerToVM().lookupMethodInPool(metaspaceConstantPool, index, (byte) opcode);
         if (metaspaceMethod != 0L) {
             HotSpotResolvedJavaMethod result = HotSpotResolvedJavaMethodImpl.fromMetaspace(metaspaceMethod);
@@ -550,7 +900,7 @@
 
     @Override
     public JavaField lookupField(int cpi, int opcode) {
-        final int index = toConstantPoolIndex(cpi, opcode);
+        final int index = rawIndexToConstantPoolIndex(cpi, opcode);
         final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
         final int nameIndex = getNameRefIndexAt(nameAndTypeIndex);
         String name = lookupUtf8(nameIndex);
@@ -597,14 +947,44 @@
             case Bytecodes.LDC2_W:
                 index = cpi;
                 break;
-            case Bytecodes.INVOKEDYNAMIC:
+            case Bytecodes.INVOKEDYNAMIC: {
                 // invokedynamic instructions point to a constant pool cache entry.
-                index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag;
-                index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, index);
+                if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+                    // index = decodeConstantPoolCacheIndex(cpi) +
+                    // runtime().getConfig().constantPoolCpCacheIndexTag;
+                    // index = cache.constantPoolCacheIndexToConstantPoolIndex(index);
+                    final int cacheIndex = cpi;
+                    index = cache.getEntryAt(decodeInvokedynamicIndex(cacheIndex)).getConstantPoolIndex();
+                    // JVMCIError.guarantee(index == x, index + " != " + x);
+                } else {
+                    index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag;
+                    index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, index);
+                }
                 break;
+            }
+            case Bytecodes.GETSTATIC:
+            case Bytecodes.PUTSTATIC:
+            case Bytecodes.GETFIELD:
+            case Bytecodes.PUTFIELD:
+            case Bytecodes.INVOKEVIRTUAL:
+            case Bytecodes.INVOKESPECIAL:
+            case Bytecodes.INVOKESTATIC:
+            case Bytecodes.INVOKEINTERFACE: {
+                // invoke and field instructions point to a constant pool cache entry.
+                if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+                    // index = rawIndexToConstantPoolIndex(cpi, opcode);
+                    // index = cache.constantPoolCacheIndexToConstantPoolIndex(index);
+                    final int cacheIndex = cpi;
+                    index = cache.getEntryAt(cacheIndex).getConstantPoolIndex();
+                    // JVMCIError.guarantee(index == x, index + " != " + x);
+                } else {
+                    index = rawIndexToConstantPoolIndex(cpi, opcode);
+                    index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, index);
+                }
+                break;
+            }
             default:
-                index = toConstantPoolIndex(cpi, opcode);
-                index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, index);
+                throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
         }
 
         final JVM_CONSTANT tag = getTagAt(index);
@@ -633,7 +1013,7 @@
                 switch (tag) {
                     case MethodRef:
                         if (Bytecodes.isInvokeHandleAlias(opcode)) {
-                            final int methodRefCacheIndex = toConstantPoolIndex(cpi, opcode);
+                            final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
                             if (isInvokeHandle(methodRefCacheIndex, type)) {
                                 runtime().getCompilerToVM().resolveInvokeHandle(metaspaceConstantPool, methodRefCacheIndex);
                             }
@@ -652,7 +1032,13 @@
     }
 
     private boolean isInvokeHandle(int methodRefCacheIndex, HotSpotResolvedObjectTypeImpl klass) {
-        assertTag(runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+        int index;
+        if (Options.UseConstantPoolCacheJavaCode.getValue()) {
+            index = cache.constantPoolCacheIndexToConstantPoolIndex(methodRefCacheIndex);
+        } else {
+            index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, methodRefCacheIndex);
+        }
+        assertTag(index, JVM_CONSTANT.MethodRef);
         return ResolvedJavaMethod.isSignaturePolymorphic(klass, getNameRefAt(methodRefCacheIndex), runtime().getHostJVMCIBackend().getMetaAccess());
     }
 
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotReferenceMap.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotReferenceMap.java	Tue Jul 21 16:15:22 2015 +0200
@@ -22,107 +22,22 @@
  */
 package jdk.internal.jvmci.hotspot;
 
-import static jdk.internal.jvmci.code.ValueUtil.*;
-
 import java.util.*;
 
 import jdk.internal.jvmci.code.*;
-import jdk.internal.jvmci.common.*;
-import jdk.internal.jvmci.meta.*;
 
 public final class HotSpotReferenceMap extends ReferenceMap {
 
-    private Location[] objects;
-    private Location[] derivedBase;
-    private int[] sizeInBytes;
-    private int maxRegisterSize;
-
-    private ArrayList<Value> objectValues;
-    private int objectCount;
-
-    private final TargetDescription target;
-    private final int totalFrameSize;
-
-    public HotSpotReferenceMap(TargetDescription target, int totalFrameSize) {
-        this.target = target;
-        this.objectCount = 0;
-        this.totalFrameSize = totalFrameSize;
-    }
-
-    @Override
-    public void reset() {
-        objects = null;
-        derivedBase = null;
-        sizeInBytes = null;
-        maxRegisterSize = 0;
-
-        objectValues = new ArrayList<>();
-        objectCount = 0;
-    }
+    final Location[] objects;
+    final Location[] derivedBase;
+    final int[] sizeInBytes;
+    final int maxRegisterSize;
 
-    @Override
-    public void addLiveValue(Value v) {
-        if (isConstant(v)) {
-            return;
-        }
-        LIRKind lirKind = v.getLIRKind();
-        if (!lirKind.isValue()) {
-            objectValues.add(v);
-            if (lirKind.isDerivedReference()) {
-                objectCount++;
-            } else {
-                objectCount += lirKind.getReferenceCount();
-            }
-        }
-        if (isRegister(v)) {
-            int size = target.getSizeInBytes(lirKind.getPlatformKind());
-            if (size > maxRegisterSize) {
-                maxRegisterSize = size;
-            }
-        }
-    }
-
-    @Override
-    public void finish() {
-        objects = new Location[objectCount];
-        derivedBase = new Location[objectCount];
-        sizeInBytes = new int[objectCount];
-
-        int idx = 0;
-        for (Value obj : objectValues) {
-            LIRKind kind = obj.getLIRKind();
-            int bytes = bytesPerElement(kind);
-            if (kind.isDerivedReference()) {
-                throw JVMCIError.unimplemented("derived references not yet implemented");
-            } else {
-                for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) {
-                    if (kind.isReference(i)) {
-                        objects[idx] = toLocation(obj, i * bytes);
-                        derivedBase[idx] = null;
-                        sizeInBytes[idx] = bytes;
-                        idx++;
-                    }
-                }
-            }
-        }
-
-        assert idx == objectCount;
-        objectValues = null;
-        objectCount = 0;
-    }
-
-    private int bytesPerElement(LIRKind kind) {
-        PlatformKind platformKind = kind.getPlatformKind();
-        return target.getSizeInBytes(platformKind) / platformKind.getVectorLength();
-    }
-
-    private Location toLocation(Value v, int offset) {
-        if (isRegister(v)) {
-            return Location.subregister(asRegister(v), offset);
-        } else {
-            StackSlot s = asStackSlot(v);
-            return Location.stack(s.getOffset(totalFrameSize) + offset);
-        }
+    public HotSpotReferenceMap(Location[] objects, Location[] derivedBase, int[] sizeInBytes, int maxRegisterSize) {
+        this.objects = objects;
+        this.derivedBase = derivedBase;
+        this.sizeInBytes = sizeInBytes;
+        this.maxRegisterSize = maxRegisterSize;
     }
 
     @Override
@@ -137,7 +52,7 @@
         }
         if (obj instanceof HotSpotReferenceMap) {
             HotSpotReferenceMap that = (HotSpotReferenceMap) obj;
-            if (Arrays.equals(objects, that.objects) && this.target.equals(that.target)) {
+            if (Arrays.equals(objects, that.objects)) {
                 return true;
             }
         }
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectType.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectType.java	Tue Jul 21 16:15:22 2015 +0200
@@ -88,6 +88,8 @@
 
     long prototypeMarkWord();
 
+    int layoutHelper();
+
     HotSpotResolvedObjectType getEnclosingType();
 
     ResolvedJavaMethod getClassInitializer();
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java	Tue Jul 21 16:15:22 2015 +0200
@@ -430,7 +430,7 @@
         assert !isInterface();
 
         HotSpotVMConfig config = runtime().getConfig();
-        final int layoutHelper = unsafe.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
+        final int layoutHelper = layoutHelper();
         assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
 
         // See: Klass::layout_helper_size_in_bytes
@@ -442,6 +442,11 @@
         return needsSlowPath ? -size : size;
     }
 
+    public int layoutHelper() {
+        HotSpotVMConfig config = runtime().getConfig();
+        return unsafe.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
+    }
+
     public synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
         HotSpotResolvedJavaMethod method = null;
         if (methodCache == null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotSymbol.java	Tue Jul 21 16:15:22 2015 +0200
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2013, 2015, 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 jdk.internal.jvmci.hotspot;
+
+import static jdk.internal.jvmci.common.UnsafeAccess.*;
+import static jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Represents a metaspace {@code Symbol}.
+ */
+public class HotSpotSymbol {
+
+    private final long metaspaceSymbol;
+
+    public HotSpotSymbol(long metaspaceSymbol) {
+        assert metaspaceSymbol != 0;
+        this.metaspaceSymbol = metaspaceSymbol;
+    }
+
+    /**
+     * Decodes this {@code Symbol} and returns the symbol string as {@link java.lang.String}.
+     *
+     * @return the decoded string, or null if there was a decoding error
+     */
+    public String asString() {
+        return readModifiedUTF8(asByteArray());
+    }
+
+    /**
+     * Reads the modified UTF-8 string in {@code buf} and converts it to a {@link String}. The
+     * implementation is taken from {@link java.io.DataInputStream#readUTF(DataInput)} and adapted
+     * to operate on a {@code byte} array directly for performance reasons.
+     *
+     * @see java.io.DataInputStream#readUTF(DataInput)
+     */
+    private static String readModifiedUTF8(byte[] buf) {
+        final int utflen = buf.length;
+        byte[] bytearr = null;
+        char[] chararr = new char[utflen];
+
+        int c;
+        int char2;
+        int char3;
+        int count = 0;
+        int chararrCount = 0;
+
+        bytearr = buf;
+
+        while (count < utflen) {
+            c = bytearr[count] & 0xff;
+            if (c > 127) {
+                break;
+            }
+            count++;
+            chararr[chararrCount++] = (char) c;
+        }
+
+        while (count < utflen) {
+            c = bytearr[count] & 0xff;
+            switch (c >> 4) {
+                case 0:
+                case 1:
+                case 2:
+                case 3:
+                case 4:
+                case 5:
+                case 6:
+                case 7:
+                    /* 0xxxxxxx */
+                    count++;
+                    chararr[chararrCount++] = (char) c;
+                    break;
+                case 12:
+                case 13:
+                    /* 110x xxxx 10xx xxxx */
+                    count += 2;
+                    if (count > utflen) {
+                        // malformed input: partial character at end
+                        return null;
+                    }
+                    char2 = bytearr[count - 1];
+                    if ((char2 & 0xC0) != 0x80) {
+                        // malformed input around byte
+                        return null;
+                    }
+                    chararr[chararrCount++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
+                    break;
+                case 14:
+                    /* 1110 xxxx 10xx xxxx 10xx xxxx */
+                    count += 3;
+                    if (count > utflen) {
+                        // malformed input: partial character at end
+                        return null;
+                    }
+                    char2 = bytearr[count - 2];
+                    char3 = bytearr[count - 1];
+                    if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
+                        // malformed input around byte
+                        return null;
+                    }
+                    chararr[chararrCount++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
+                    break;
+                default:
+                    /* 10xx xxxx, 1111 xxxx */
+                    // malformed input around byte
+                    return null;
+            }
+        }
+        // The number of chars produced may be less than utflen
+        char[] value = Arrays.copyOf(chararr, chararrCount);
+        return new String(value);
+    }
+
+    private byte[] asByteArray() {
+        final int length = getLength();
+        byte[] result = new byte[length];
+        for (int index = 0; index < length; index++) {
+            result[index] = getByteAt(index);
+        }
+        return result;
+    }
+
+    private int getLength() {
+        return unsafe.getShort(metaspaceSymbol + runtime().getConfig().symbolLengthOffset);
+    }
+
+    private byte getByteAt(int index) {
+        return unsafe.getByte(metaspaceSymbol + runtime().getConfig().symbolBodyOffset + index);
+    }
+}
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotTargetDescription.java	Tue Jul 21 15:16:01 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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 jdk.internal.jvmci.hotspot;
-
-import jdk.internal.jvmci.code.*;
-
-public class HotSpotTargetDescription extends TargetDescription {
-
-    public HotSpotTargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects) {
-        super(arch, isMP, stackAlignment, implicitNullCheckLimit, inlineObjects);
-    }
-
-    @Override
-    public ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount, int totalFrameSize) {
-        return new HotSpotReferenceMap(this, totalFrameSize);
-    }
-}
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVMConfig.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVMConfig.java	Tue Jul 21 16:15:22 2015 +0200
@@ -808,6 +808,8 @@
     @HotSpotVMField(name = "oopDesc::_mark", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset;
     @HotSpotVMField(name = "oopDesc::_metadata._klass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset;
 
+    @HotSpotVMField(name = "Handle::_handle", type = "oop*", get = HotSpotVMField.Type.OFFSET) @Stable public int handleHandleOffset;
+
     @HotSpotVMField(name = "Klass::_prototype_header", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int prototypeMarkWordOffset;
     @HotSpotVMField(name = "Klass::_subklass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int subklassOffset;
     @HotSpotVMField(name = "Klass::_next_sibling", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int nextSiblingOffset;
@@ -1090,11 +1092,29 @@
 
     @HotSpotVMType(name = "ConstantPool", get = HotSpotVMType.Type.SIZE) @Stable public int constantPoolSize;
     @HotSpotVMField(name = "ConstantPool::_tags", type = "Array<u1>*", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolTagsOffset;
+    @HotSpotVMField(name = "ConstantPool::_cache", type = "ConstantPoolCache*", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolCacheOffset;
     @HotSpotVMField(name = "ConstantPool::_pool_holder", type = "InstanceKlass*", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolHolderOffset;
     @HotSpotVMField(name = "ConstantPool::_length", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolLengthOffset;
+    @HotSpotVMField(name = "ConstantPool::_resolved_references", type = "jobject", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolResolvedReferencesOffset;
+    @HotSpotVMField(name = "ConstantPool::_reference_map", type = "Array<u2>*", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolReferenceMapOffset;
 
     @HotSpotVMConstant(name = "ConstantPool::CPCACHE_INDEX_TAG") @Stable public int constantPoolCpCacheIndexTag;
 
+    @HotSpotVMType(name = "ConstantPoolCache", get = HotSpotVMType.Type.SIZE) @Stable public int constantPoolCacheSize;
+    @HotSpotVMField(name = "ConstantPoolCache::_length", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolCacheLengthOffset;
+
+    @HotSpotVMType(name = "ConstantPoolCacheEntry", get = HotSpotVMType.Type.SIZE) @Stable public int constantPoolCacheEntrySize;
+    @HotSpotVMField(name = "ConstantPoolCacheEntry::_indices", type = "intx", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolCacheEntryIndicesOffset;
+    @HotSpotVMField(name = "ConstantPoolCacheEntry::_f1", type = "volatile Metadata*", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolCacheEntryF1Offset;
+    @HotSpotVMField(name = "ConstantPoolCacheEntry::_f2", type = "intx", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolCacheEntryF2Offset;
+    @HotSpotVMField(name = "ConstantPoolCacheEntry::_flags", type = "intx", get = HotSpotVMField.Type.OFFSET) @Stable public int constantPoolCacheEntryFlagsOffset;
+
+    @HotSpotVMConstant(name = "ConstantPoolCacheEntry::has_appendix_shift") @Stable public int constantPoolCacheEntryHasAppendixShift;
+
+    @HotSpotVMConstant(name = "ConstantPoolCacheEntry::cp_index_mask") @Stable public int constantPoolCacheEntryCpIndexMask;
+
+    @HotSpotVMConstant(name = "ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset") @Stable public int constantPoolCacheEntryIndyResolvedReferencesAppendixOffset;
+
     @HotSpotVMConstant(name = "JVM_CONSTANT_Utf8") @Stable public int jvmConstantUtf8;
     @HotSpotVMConstant(name = "JVM_CONSTANT_Integer") @Stable public int jvmConstantInteger;
     @HotSpotVMConstant(name = "JVM_CONSTANT_Long") @Stable public int jvmConstantLong;
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVmSymbols.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVmSymbols.java	Tue Jul 21 16:15:22 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -24,6 +24,8 @@
 
 import static jdk.internal.jvmci.common.UnsafeAccess.*;
 import static jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime.*;
+
+import jdk.internal.jvmci.common.*;
 import sun.misc.*;
 
 /**
@@ -43,6 +45,17 @@
         HotSpotVMConfig config = runtime.getConfig();
         assert config.vmSymbolsFirstSID <= index && index < config.vmSymbolsSIDLimit : "index " + index + " is out of bounds";
         assert config.symbolPointerSize == Unsafe.ADDRESS_SIZE : "the following address read is broken";
-        return runtime.getCompilerToVM().getSymbol(unsafe.getAddress(config.vmSymbolsSymbols + index * config.symbolPointerSize));
+        final long metaspaceSymbol = unsafe.getAddress(config.vmSymbolsSymbols + index * config.symbolPointerSize);
+        if (HotSpotConstantPool.Options.UseConstantPoolCacheJavaCode.getValue()) {
+            HotSpotSymbol symbol = new HotSpotSymbol(metaspaceSymbol);
+            String s = symbol.asString();
+            // It shouldn't but just in case something went wrong...
+            if (s == null) {
+                throw JVMCIError.shouldNotReachHere("malformed UTF-8 string in constant pool");
+            }
+            return s;
+        } else {
+            return runtime.getCompilerToVM().getSymbol(metaspaceSymbol);
+        }
     }
 }
--- a/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/LIRKind.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/LIRKind.java	Tue Jul 21 16:15:22 2015 +0200
@@ -27,7 +27,7 @@
 /**
  * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the
  * low level representation of the value, and a {@link #referenceMask} that describes the location
- * of object references in the value.
+ * of object references in the value, and optionally a {@link #derivedReferenceBase}.
  *
  * <h2>Constructing {@link LIRKind} instances</h2>
  *
@@ -37,49 +37,54 @@
  *
  * <p>
  * If the result value is created from one or more input values, the {@link LIRKind} should be
- * created with {@link LIRKind#derive}(inputs). If the result has a different {@link PlatformKind}
- * than the inputs, {@link LIRKind#derive}(inputs).{@link #changeType}(resultKind) should be used.
+ * created with {@link LIRKind#combine}(inputs). If the result has a different {@link PlatformKind}
+ * than the inputs, {@link LIRKind#combine}(inputs).{@link #changeType}(resultKind) should be used.
  * <p>
  * If the result is an exact copy of one of the inputs, {@link Value#getLIRKind()} can be used. Note
  * that this is only correct for move-like operations, like conditional move or compare-and-swap.
- * For convert operations, {@link LIRKind#derive} should be used.
+ * For convert operations, {@link LIRKind#combine} should be used.
  * <p>
  * If it is known that the result will be a reference (e.g. pointer arithmetic where the end result
  * is a valid oop), {@link LIRKind#reference} should be used.
  * <p>
  * If it is known that the result will neither be a reference nor be derived from a reference,
  * {@link LIRKind#value} can be used. If the operation producing this value has inputs, this is very
- * likely wrong, and {@link LIRKind#derive} should be used instead.
+ * likely wrong, and {@link LIRKind#combine} should be used instead.
  * <p>
- * If it is known that the result is derived from a reference, {@link LIRKind#derivedReference} can
- * be used. In most cases, {@link LIRKind#derive} should be used instead, since it is able to detect
- * this automatically.
+ * If it is known that the result is derived from a reference in a way that the garbage collector
+ * can not track, {@link LIRKind#unknownReference} can be used. In most cases,
+ * {@link LIRKind#combine} should be used instead, since it is able to detect this automatically.
  */
 public final class LIRKind {
 
     /**
-     * The non-type. This uses {@link #derivedReference}, so it can never be part of an oop map.
+     * The non-type. This uses {@link #unknownReference}, so it can never be part of an oop map.
      */
-    public static final LIRKind Illegal = derivedReference(Kind.Illegal);
+    public static final LIRKind Illegal = unknownReference(Kind.Illegal);
 
     private final PlatformKind platformKind;
     private final int referenceMask;
 
-    private static final int DERIVED_REFERENCE = -1;
+    private AllocatableValue derivedReferenceBase;
 
-    private LIRKind(PlatformKind platformKind, int referenceMask) {
+    private static final int UNKNOWN_REFERENCE = -1;
+
+    private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) {
         this.platformKind = platformKind;
         this.referenceMask = referenceMask;
+        this.derivedReferenceBase = derivedReferenceBase;
+
+        assert derivedReferenceBase == null || !derivedReferenceBase.getLIRKind().isDerivedReference() : "derived reference can't have another derived reference as base";
     }
 
     /**
      * Create a {@link LIRKind} of type {@code platformKind} that contains a primitive value. Should
      * be only used when it's guaranteed that the value is not even indirectly derived from a
-     * reference. Otherwise, {@link #derive(Value...)} should be used instead.
+     * reference. Otherwise, {@link #combine(Value...)} should be used instead.
      */
     public static LIRKind value(PlatformKind platformKind) {
         assert platformKind != Kind.Object : "Object should always be used as reference type";
-        return new LIRKind(platformKind, 0);
+        return new LIRKind(platformKind, 0, null);
     }
 
     /**
@@ -87,37 +92,62 @@
      * reference.
      */
     public static LIRKind reference(PlatformKind platformKind) {
+        return derivedReference(platformKind, null);
+    }
+
+    /**
+     * Create a {@link LIRKind} of type {@code platformKind} that contains a derived reference.
+     */
+    public static LIRKind derivedReference(PlatformKind platformKind, AllocatableValue base) {
         int length = platformKind.getVectorLength();
         assert 0 < length && length < 32 : "vector of " + length + " references not supported";
-        return new LIRKind(platformKind, (1 << length) - 1);
+        return new LIRKind(platformKind, (1 << length) - 1, base);
     }
 
     /**
      * Create a {@link LIRKind} of type {@code platformKind} that contains a value that is derived
-     * from a reference. Values of this {@link LIRKind} can not be live at safepoints. In most
-     * cases, this should not be called directly. {@link #derive} should be used instead to
-     * automatically propagate this information.
+     * from a reference in a non-linear way. Values of this {@link LIRKind} can not be live at
+     * safepoints. In most cases, this should not be called directly. {@link #combine} should be
+     * used instead to automatically propagate this information.
      */
-    public static LIRKind derivedReference(PlatformKind platformKind) {
-        return new LIRKind(platformKind, DERIVED_REFERENCE);
+    public static LIRKind unknownReference(PlatformKind platformKind) {
+        return new LIRKind(platformKind, UNKNOWN_REFERENCE, null);
+    }
+
+    /**
+     * Create a derived reference.
+     *
+     * @param base An {@link AllocatableValue} containing the base pointer of the derived reference.
+     */
+    public LIRKind makeDerivedReference(AllocatableValue base) {
+        assert !isUnknownReference() && derivedReferenceBase == null;
+        if (Value.ILLEGAL.equals(base)) {
+            return makeUnknownReference();
+        } else {
+            if (isValue()) {
+                return derivedReference(platformKind, base);
+            } else {
+                return new LIRKind(platformKind, referenceMask, base);
+            }
+        }
     }
 
     /**
      * Derive a new type from inputs. The result will have the {@link PlatformKind} of one of the
-     * inputs. If all inputs are values, the result is a value. Otherwise, the result is a derived
+     * inputs. If all inputs are values, the result is a value. Otherwise, the result is an unknown
      * reference.
      *
      * This method should be used to construct the result {@link LIRKind} of any operation that
      * modifies values (e.g. arithmetics).
      */
-    public static LIRKind derive(Value... inputs) {
+    public static LIRKind combine(Value... inputs) {
         assert inputs.length > 0;
         for (Value input : inputs) {
             LIRKind kind = input.getLIRKind();
-            if (kind.isDerivedReference()) {
+            if (kind.isUnknownReference()) {
                 return kind;
             } else if (!kind.isValue()) {
-                return kind.makeDerivedReference();
+                return kind.makeUnknownReference();
             }
         }
 
@@ -128,10 +158,10 @@
     /**
      * Merge the types of the inputs. The result will have the {@link PlatformKind} of one of the
      * inputs. If all inputs are values (references), the result is a value (reference). Otherwise,
-     * the result is a derived reference.
+     * the result is an unknown reference.
      *
-     * This method should be used to construct the result {@link LIRKind} of merge operation that do
-     * not modify values (e.g. phis).
+     * This method should be used to construct the result {@link LIRKind} of merge operation that
+     * does not modify values (e.g. phis).
      */
     public static LIRKind merge(Value... inputs) {
         assert inputs.length > 0;
@@ -143,6 +173,42 @@
     }
 
     /**
+     * Helper method to construct derived reference kinds. Returns the base value of a reference or
+     * derived reference. For values it returns {@code null}, and for unknown references it returns
+     * {@link Value#ILLEGAL}.
+     */
+    public static AllocatableValue derivedBaseFromValue(AllocatableValue value) {
+        LIRKind kind = value.getLIRKind();
+        if (kind.isValue()) {
+            return null;
+        } else if (kind.isDerivedReference()) {
+            return kind.getDerivedReferenceBase();
+        } else if (kind.isUnknownReference()) {
+            return Value.ILLEGAL;
+        } else {
+            // kind is a reference
+            return value;
+        }
+    }
+
+    /**
+     * Helper method to construct derived reference kinds. If one of {@code base1} or {@code base2}
+     * are set, it creates a derived reference using it as the base. If both are set, the result is
+     * an unknown reference.
+     */
+    public static LIRKind combineDerived(LIRKind kind, AllocatableValue base1, AllocatableValue base2) {
+        if (base1 == null && base2 == null) {
+            return kind;
+        } else if (base1 == null) {
+            return kind.makeDerivedReference(base2);
+        } else if (base2 == null) {
+            return kind.makeDerivedReference(base1);
+        } else {
+            return kind.makeUnknownReference();
+        }
+    }
+
+    /**
      * @see #merge(Value...)
      */
     public static LIRKind merge(Iterable<LIRKind> kinds) {
@@ -150,14 +216,13 @@
 
         for (LIRKind kind : kinds) {
 
-            assert mergeKind == null || verifyMoveKinds(mergeKind, kind) : String.format("Input kinds do not match %s vs. %s", mergeKind, kind);
-
-            if (kind.isDerivedReference()) {
+            if (kind.isUnknownReference()) {
                 /**
-                 * Kind is a derived reference therefore the result can only be also a derived
+                 * Kind is an unknown reference, therefore the result can only be also an unknown
                  * reference.
                  */
-                return kind;
+                mergeKind = kind;
+                break;
             }
             if (mergeKind == null) {
                 mergeKind = kind;
@@ -168,29 +233,38 @@
                 /* Kind is a value. */
                 if (mergeKind.referenceMask != 0) {
                     /*
-                     * Inputs consists of values and references. Make the result a derived
+                     * Inputs consists of values and references. Make the result an unknown
                      * reference.
                      */
-                    return mergeKind.makeDerivedReference();
+                    mergeKind = mergeKind.makeUnknownReference();
+                    break;
                 }
                 /* Check that other inputs are also values. */
             } else {
                 /* Kind is a reference. */
                 if (mergeKind.referenceMask != kind.referenceMask) {
                     /*
-                     * Reference maps do not match so the result can only be a derived reference.
+                     * Reference maps do not match so the result can only be an unknown reference.
                      */
-                    return mergeKind.makeDerivedReference();
+                    mergeKind = mergeKind.makeUnknownReference();
+                    break;
                 }
             }
 
         }
-        assert mergeKind != null;
+        assert mergeKind != null && verifyMerge(mergeKind, kinds);
 
         // all inputs are values or references, just return one of them
         return mergeKind;
     }
 
+    private static boolean verifyMerge(LIRKind mergeKind, Iterable<LIRKind> kinds) {
+        for (LIRKind kind : kinds) {
+            assert mergeKind == null || verifyMoveKinds(mergeKind, kind) : String.format("Input kinds do not match %s vs. %s", mergeKind, kind);
+        }
+        return true;
+    }
+
     /**
      * Create a new {@link LIRKind} with the same reference information and a new
      * {@linkplain #getPlatformKind platform kind}. If the new kind is a longer vector than this,
@@ -199,17 +273,17 @@
     public LIRKind changeType(PlatformKind newPlatformKind) {
         if (newPlatformKind == platformKind) {
             return this;
-        } else if (isDerivedReference()) {
-            return derivedReference(newPlatformKind);
+        } else if (isUnknownReference()) {
+            return unknownReference(newPlatformKind);
         } else if (referenceMask == 0) {
             // value type
-            return new LIRKind(newPlatformKind, 0);
+            return LIRKind.value(newPlatformKind);
         } else {
             // reference type
             int newLength = Math.min(32, newPlatformKind.getVectorLength());
             int newReferenceMask = referenceMask & (0xFFFFFFFF >>> (32 - newLength));
-            assert newReferenceMask != DERIVED_REFERENCE;
-            return new LIRKind(newPlatformKind, newReferenceMask);
+            assert newReferenceMask != UNKNOWN_REFERENCE;
+            return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase);
         }
     }
 
@@ -218,11 +292,11 @@
      * new kind is longer than this, the reference positions are repeated to fill the vector.
      */
     public LIRKind repeat(PlatformKind newPlatformKind) {
-        if (isDerivedReference()) {
-            return derivedReference(newPlatformKind);
+        if (isUnknownReference()) {
+            return unknownReference(newPlatformKind);
         } else if (referenceMask == 0) {
             // value type
-            return new LIRKind(newPlatformKind, 0);
+            return LIRKind.value(newPlatformKind);
         } else {
             // reference type
             int oldLength = platformKind.getVectorLength();
@@ -235,16 +309,17 @@
                 newReferenceMask |= referenceMask << i;
             }
 
-            assert newReferenceMask != DERIVED_REFERENCE;
-            return new LIRKind(newPlatformKind, newReferenceMask);
+            assert newReferenceMask != UNKNOWN_REFERENCE;
+            return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase);
         }
     }
 
     /**
-     * Create a new {@link LIRKind} with the same type, but marked as containing a derivedReference.
+     * Create a new {@link LIRKind} with the same type, but marked as containing an
+     * {@link LIRKind#unknownReference}.
      */
-    public LIRKind makeDerivedReference() {
-        return new LIRKind(platformKind, DERIVED_REFERENCE);
+    public LIRKind makeUnknownReference() {
+        return new LIRKind(platformKind, UNKNOWN_REFERENCE, null);
     }
 
     /**
@@ -255,15 +330,37 @@
     }
 
     /**
-     * Check whether this value is derived from a reference. If this returns {@code true}, this
-     * value must not be live at safepoints.
+     * Check whether this value is a derived reference.
      */
     public boolean isDerivedReference() {
-        return referenceMask == DERIVED_REFERENCE;
+        return getDerivedReferenceBase() != null;
+    }
+
+    /**
+     * Get the base value of a derived reference.
+     */
+    public AllocatableValue getDerivedReferenceBase() {
+        return derivedReferenceBase;
+    }
+
+    /**
+     * Change the base value of a derived reference. This must be called on derived references only.
+     */
+    public void setDerivedReferenceBase(AllocatableValue derivedReferenceBase) {
+        assert isDerivedReference();
+        this.derivedReferenceBase = derivedReferenceBase;
+    }
+
+    /**
+     * Check whether this value is derived from a reference in a non-linear way. If this returns
+     * {@code true}, this value must not be live at safepoints.
+     */
+    public boolean isUnknownReference() {
+        return referenceMask == UNKNOWN_REFERENCE;
     }
 
     public int getReferenceCount() {
-        assert !isDerivedReference();
+        assert !isUnknownReference();
         return Integer.bitCount(referenceMask);
     }
 
@@ -276,7 +373,7 @@
      */
     public boolean isReference(int idx) {
         assert 0 <= idx && idx < platformKind.getVectorLength() : "invalid index " + idx + " in " + this;
-        return !isDerivedReference() && (referenceMask & 1 << idx) != 0;
+        return !isUnknownReference() && (referenceMask & 1 << idx) != 0;
     }
 
     /**
@@ -290,7 +387,7 @@
     public String toString() {
         if (isValue()) {
             return platformKind.name();
-        } else if (isDerivedReference()) {
+        } else if (isUnknownReference()) {
             return platformKind.name() + "[*]";
         } else {
             StringBuilder ret = new StringBuilder();
@@ -340,7 +437,7 @@
          * (phi-)moves from e.g. integer to short can happen. Therefore we compare stack kinds.
          */
         if (toStackKind(src.getPlatformKind()).equals(toStackKind(dst.getPlatformKind()))) {
-            return !src.isDerivedReference() || dst.isDerivedReference();
+            return !src.isUnknownReference() || dst.isUnknownReference();
         }
         return false;
     }
--- a/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/NamedLocationIdentity.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/NamedLocationIdentity.java	Tue Jul 21 16:15:22 2015 +0200
@@ -29,18 +29,17 @@
 /**
  * A {@link LocationIdentity} with a name.
  */
-public final class NamedLocationIdentity extends LocationIdentity implements FormatWithToString {
+public class NamedLocationIdentity extends LocationIdentity implements FormatWithToString {
 
     /**
      * Map for asserting all {@link NamedLocationIdentity} instances have a unique name.
      */
     static class DB {
-        private static final HashMap<String, NamedLocationIdentity> map = new HashMap<>();
+        private static final HashSet<String> map = new HashSet<>();
 
-        static boolean checkUnique(NamedLocationIdentity identity) {
-            NamedLocationIdentity oldValue = map.put(identity.name, identity);
-            if (oldValue != null) {
-                throw new AssertionError("identity " + identity + " already exists");
+        static boolean checkUnique(String name) {
+            if (!map.add(name)) {
+                throw new AssertionError("identity " + name + " already exists");
             }
             return true;
         }
@@ -49,9 +48,10 @@
     private final String name;
     private final boolean immutable;
 
-    private NamedLocationIdentity(String name, boolean immutable) {
+    protected NamedLocationIdentity(String name, boolean immutable) {
         this.name = name;
         this.immutable = immutable;
+        assert DB.checkUnique(name);
     }
 
     /**
@@ -82,9 +82,7 @@
      * @param immutable true if the location is immutable
      */
     private static NamedLocationIdentity create(String name, boolean immutable) {
-        NamedLocationIdentity id = new NamedLocationIdentity(name, immutable);
-        assert DB.checkUnique(id);
-        return id;
+        return new NamedLocationIdentity(name, immutable);
     }
 
     @Override
--- a/jvmci/jdk.internal.jvmci.options.processor/src/jdk/internal/jvmci/options/processor/JVMCIJars.java	Tue Jul 21 15:16:01 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2015, 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 jdk.internal.jvmci.options.processor;
-
-import java.io.*;
-import java.util.*;
-import java.util.stream.*;
-import java.util.zip.*;
-
-public class JVMCIJars implements Iterable<ZipEntry> {
-    private final List<ZipFile> jars = new ArrayList<>(2);
-
-    public JVMCIJars() {
-        String classPath = System.getProperty("java.class.path");
-        for (String e : classPath.split(File.pathSeparator)) {
-            if (e.endsWith(File.separatorChar + "graal.jar") || e.endsWith(File.separatorChar + "graal-truffle.jar")) {
-                try {
-                    jars.add(new ZipFile(e));
-                } catch (IOException ioe) {
-                    throw new InternalError(ioe);
-                }
-            }
-        }
-        if (jars.size() != 2) {
-            throw new InternalError("Could not find graal.jar or graal-truffle.jar on class path: " + classPath);
-        }
-    }
-
-    public Iterator<ZipEntry> iterator() {
-        Stream<ZipEntry> entries = jars.stream().flatMap(ZipFile::stream);
-        return entries.iterator();
-    }
-
-    public InputStream getInputStream(String classFilePath) throws IOException {
-        for (ZipFile jar : jars) {
-            ZipEntry entry = jar.getEntry(classFilePath);
-            if (entry != null) {
-                return jar.getInputStream(entry);
-            }
-        }
-        return null;
-    }
-}
--- a/jvmci/jdk.internal.jvmci.sparc/src/jdk/internal/jvmci/sparc/SPARC.java	Tue Jul 21 15:16:01 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.sparc/src/jdk/internal/jvmci/sparc/SPARC.java	Tue Jul 21 16:15:22 2015 +0200
@@ -286,8 +286,10 @@
     public PlatformKind getLargestStorableKind(RegisterCategory category) {
         if (category.equals(CPU)) {
             return Kind.Long;
+        } else if (category.equals(FPUd)) {
+            return Kind.Double;
         } else if (category.equals(FPUs)) {
-            return Kind.Double;
+            return Kind.Float;
         } else {
             return Kind.Illegal;
         }
@@ -316,6 +318,10 @@
         return true;
     }
 
+    public static boolean isGlobalRegister(Register r) {
+        return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number;
+    }
+
     public static boolean isSingleFloatRegister(Register r) {
         return r.name.startsWith("f");
     }
--- a/make/defs.make	Tue Jul 21 15:16:01 2015 +0200
+++ b/make/defs.make	Tue Jul 21 16:15:22 2015 +0200
@@ -376,6 +376,7 @@
 CONDITIONAL_EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/jdk.internal.jvmci.hotspot.events.EventProvider
 endif
 
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotConstantPool
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotConstantReflectionProvider
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotResolvedJavaFieldImpl
--- a/mx.jvmci/mx_jvmci_makefile.py	Tue Jul 21 15:16:01 2015 +0200
+++ b/mx.jvmci/mx_jvmci_makefile.py	Tue Jul 21 16:15:22 2015 +0200
@@ -55,8 +55,7 @@
     if not opts.selectedDists:
         opts.selectedDists = [d.name for d in mx_jvmci.jdkDeployedDists if d.partOfHotSpot]
     mf = Makefile()
-    commandline = " ".join(["mx.sh", "makefile"] + args)
-    if do_build_makefile(mf, opts.selectedDists, commandline):
+    if do_build_makefile(mf, opts.selectedDists):
         contents = mf.generate()
         if opts.output == None:
             print contents
@@ -128,7 +127,7 @@
 
 
 
-def do_build_makefile(mf, selectedDists, commandline):
+def do_build_makefile(mf, selectedDists):
     java = mx.java()
     bootClassPath = java.bootclasspath()
     bootClassPath = bootClassPath.replace(os.path.realpath(java.jdk), "$(ABS_BOOTDIR)")
--- a/mx.jvmci/suite.py	Tue Jul 21 15:16:01 2015 +0200
+++ b/mx.jvmci/suite.py	Tue Jul 21 16:15:22 2015 +0200
@@ -9,9 +9,9 @@
     # ------------- Libraries -------------
 
     "HCFDIS" : {
-      "path" : "lib/hcfdis-2.jar",
-      "urls" : ["http://lafo.ssw.uni-linz.ac.at/hcfdis-2.jar"],
-      "sha1" : "bc8b2253436485e9dbaf81771c259ccfa1a24c80",
+      "path" : "lib/hcfdis-3.jar",
+      "urls" : ["http://lafo.ssw.uni-linz.ac.at/hcfdis-3.jar"],
+      "sha1" : "a71247c6ddb90aad4abf7c77e501acc60674ef57",
     },
 
     "C1VISUALIZER_DIST" : {
--- a/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp	Tue Jul 21 15:16:01 2015 +0200
+++ b/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp	Tue Jul 21 16:15:22 2015 +0200
@@ -76,10 +76,11 @@
         _instructions->relocate(pc + NativeMovConstReg::add_offset, internal_word_Relocation::spec((address) dest));
       }
       TRACE_jvmci_3("relocating at %p (+%d) with destination at %d", pc, pc_offset, data_offset);
-  } else {
+  }else {
+    int const_size = align_size_up(_constants->end()-_constants->start(), CodeEntryAlignment);
     NativeMovRegMem* load = nativeMovRegMem_at(pc);
-    // The base pointer is set 4k off (see SPARCLoadConstantTableBaseOp)
-    load->set_offset(data_offset - (1<<12));
+    // This offset must match with SPARCLoadConstantTableBaseOp.emitCode
+    load->set_offset(- (const_size - data_offset + Assembler::min_simm13()));
     TRACE_jvmci_3("relocating ld at %p (+%d) with destination at %d", pc, pc_offset, data_offset);
   }
 }
--- a/src/share/vm/code/nmethod.cpp	Tue Jul 21 15:16:01 2015 +0200
+++ b/src/share/vm/code/nmethod.cpp	Tue Jul 21 16:15:22 2015 +0200
@@ -43,6 +43,21 @@
 #include "utilities/dtrace.hpp"
 #include "utilities/events.hpp"
 #include "utilities/xmlstream.hpp"
+#ifdef TARGET_ARCH_x86
+# include "nativeInst_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "nativeInst_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "nativeInst_zero.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "nativeInst_arm.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "nativeInst_ppc.hpp"
+#endif
 #ifdef SHARK
 #include "shark/sharkCompiler.hpp"
 #endif
@@ -2610,6 +2625,14 @@
   memcpy(scopes_data_begin(), buffer, size);
 }
 
+// When using JVMCI the address might be off by the size of a call instruction.
+bool nmethod::is_deopt_entry(address pc) {
+  return pc == deopt_handler_begin()
+#ifdef JVMCI
+    || pc == (deopt_handler_begin() + NativeCall::instruction_size)
+#endif // JVMCI
+    ;
+}
 
 #ifdef ASSERT
 static PcDesc* linear_search(nmethod* nm, int pc_offset, bool approximate) {
--- a/src/share/vm/code/nmethod.hpp	Tue Jul 21 15:16:01 2015 +0200
+++ b/src/share/vm/code/nmethod.hpp	Tue Jul 21 16:15:22 2015 +0200
@@ -694,24 +694,7 @@
   // Deopt
   // Return true is the PC is one would expect if the frame is being deopted.
   bool is_deopt_pc      (address pc) { return is_deopt_entry(pc) || is_deopt_mh_entry(pc); }
-
-  // (thomaswue) When using jvmci, the address might be off by 5 (because this is the size of the call instruction.
-  // (thomaswue) TODO: Replace this by a more general mechanism.
-  // (sanzinger) SPARC has another offset, looked for some variable existing in HotSpot which describes this offset, but i have not
-  // found anything.
-  bool is_deopt_entry   (address pc) {
-    return pc == deopt_handler_begin()
-#ifdef JVMCI
-      || pc == deopt_handler_begin() +
-#ifdef TARGET_ARCH_sparc
-  8
-#endif // sparc
-#ifdef TARGET_ARCH_x86
-  5
-#endif // x86
-#endif // JVMCI
-      ;
-  }
+  bool is_deopt_entry(address pc);
   bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
   // Accessor/mutator for the original pc of a frame before a frame was deopted.
   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
--- a/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Tue Jul 21 15:16:01 2015 +0200
+++ b/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Tue Jul 21 16:15:22 2015 +0200
@@ -1072,16 +1072,16 @@
   {CC"shouldInlineMethod",                           CC"("METASPACE_METHOD")Z",                                                FN_PTR(shouldInlineMethod)},
   {CC"lookupType",                                   CC"("STRING CLASS"Z)"METASPACE_KLASS,                                     FN_PTR(lookupType)},
   {CC"resolveConstantInPool",                        CC"("METASPACE_CONSTANT_POOL"I)"OBJECT,                                   FN_PTR(resolveConstantInPool)},
-  {CC"resolvePossiblyCachedConstantInPool",          CC"("METASPACE_CONSTANT_POOL"I)"OBJECT,                                   FN_PTR(resolvePossiblyCachedConstantInPool)},
-  {CC"lookupNameRefInPool",                          CC"("METASPACE_CONSTANT_POOL"I)"STRING,                                   FN_PTR(lookupNameRefInPool)},
+  {CC"resolvePossiblyCachedConstantInPool0",         CC"("METASPACE_CONSTANT_POOL"I)"OBJECT,                                   FN_PTR(resolvePossiblyCachedConstantInPool)},
+  {CC"lookupNameRefInPool0",                         CC"("METASPACE_CONSTANT_POOL"I)"STRING,                                   FN_PTR(lookupNameRefInPool)},
   {CC"lookupNameAndTypeRefIndexInPool",              CC"("METASPACE_CONSTANT_POOL"I)I",                                        FN_PTR(lookupNameAndTypeRefIndexInPool)},
-  {CC"lookupSignatureRefInPool",                     CC"("METASPACE_CONSTANT_POOL"I)"STRING,                                   FN_PTR(lookupSignatureRefInPool)},
-  {CC"lookupKlassRefIndexInPool",                    CC"("METASPACE_CONSTANT_POOL"I)I",                                        FN_PTR(lookupKlassRefIndexInPool)},
+  {CC"lookupSignatureRefInPool0",                    CC"("METASPACE_CONSTANT_POOL"I)"STRING,                                   FN_PTR(lookupSignatureRefInPool)},
+  {CC"lookupKlassRefIndexInPool0",                   CC"("METASPACE_CONSTANT_POOL"I)I",                                        FN_PTR(lookupKlassRefIndexInPool)},
   {CC"constantPoolKlassAt",                          CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_KLASS,                          FN_PTR(constantPoolKlassAt)},
   {CC"lookupKlassInPool",                            CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_KLASS,                          FN_PTR(lookupKlassInPool)},
-  {CC"lookupAppendixInPool",                         CC"("METASPACE_CONSTANT_POOL"I)"OBJECT,                                   FN_PTR(lookupAppendixInPool)},
+  {CC"lookupAppendixInPool0",                        CC"("METASPACE_CONSTANT_POOL"I)"OBJECT,                                   FN_PTR(lookupAppendixInPool)},
   {CC"lookupMethodInPool",                           CC"("METASPACE_CONSTANT_POOL"IB)"METASPACE_METHOD,                        FN_PTR(lookupMethodInPool)},
-  {CC"constantPoolRemapInstructionOperandFromCache", CC"("METASPACE_CONSTANT_POOL"I)I",                                        FN_PTR(constantPoolRemapInstructionOperandFromCache)},
+  {CC"constantPoolRemapInstructionOperandFromCache0",CC"("METASPACE_CONSTANT_POOL"I)I",                                        FN_PTR(constantPoolRemapInstructionOperandFromCache)},
   {CC"resolveField",                                 CC"("METASPACE_CONSTANT_POOL"IB[J)"METASPACE_KLASS,                       FN_PTR(resolveField)},
   {CC"resolveInvokeDynamic",                         CC"("METASPACE_CONSTANT_POOL"I)V",                                        FN_PTR(resolveInvokeDynamic)},
   {CC"resolveInvokeHandle",                          CC"("METASPACE_CONSTANT_POOL"I)V",                                        FN_PTR(resolveInvokeHandle)},
@@ -1109,7 +1109,7 @@
   {CC"allocateCompileId",                            CC"("METASPACE_METHOD"I)I",                                               FN_PTR(allocateCompileId)},
   {CC"isMature",                                     CC"("METASPACE_METHOD_DATA")Z",                                           FN_PTR(isMature)},
   {CC"hasCompiledCodeForOSR",                        CC"("METASPACE_METHOD"II)Z",                                              FN_PTR(hasCompiledCodeForOSR)},
-  {CC"getSymbol",                                    CC"(J)"STRING,                                                            FN_PTR(getSymbol)},
+  {CC"getSymbol0",                                   CC"(J)"STRING,                                                            FN_PTR(getSymbol)},
   {CC"getTimeStamp",                                 CC"()J",                                                                  FN_PTR(getTimeStamp)},
   {CC"getNextStackFrame",                            CC"("HS_STACK_FRAME_REF "[JI)"HS_STACK_FRAME_REF,                         FN_PTR(getNextStackFrame)},
   {CC"materializeVirtualObjects",                    CC"("HS_STACK_FRAME_REF"Z)V",                                             FN_PTR(materializeVirtualObjects)},
--- a/src/share/vm/jvmci/jvmciJavaAccess.hpp	Tue Jul 21 15:16:01 2015 +0200
+++ b/src/share/vm/jvmci/jvmciJavaAccess.hpp	Tue Jul 21 16:15:22 2015 +0200
@@ -155,7 +155,7 @@
     oop_field(DebugInfo, bytecodePosition, "Ljdk/internal/jvmci/code/BytecodePosition;")                                                                         \
     oop_field(DebugInfo, referenceMap, "Ljdk/internal/jvmci/code/ReferenceMap;")                                                                                 \
     oop_field(DebugInfo, calleeSaveInfo, "Ljdk/internal/jvmci/code/RegisterSaveLayout;")                                                                         \
-    objArrayOop_field(DebugInfo, virtualObjectMapping, "[Ljdk/internal/jvmci/meta/Value;")                                                                       \
+    objArrayOop_field(DebugInfo, virtualObjectMapping, "[Ljdk/internal/jvmci/code/VirtualObject;")                                                               \
   end_class                                                                                                                                                    \
   start_class(HotSpotReferenceMap)                                                                                                                             \
     objArrayOop_field(HotSpotReferenceMap, objects, "[Ljdk/internal/jvmci/code/Location;")                                                                       \
--- a/src/share/vm/runtime/handles.hpp	Tue Jul 21 15:16:01 2015 +0200
+++ b/src/share/vm/runtime/handles.hpp	Tue Jul 21 16:15:22 2015 +0200
@@ -62,6 +62,7 @@
 // used operators for ease of use.
 
 class Handle VALUE_OBJ_CLASS_SPEC {
+  friend class VMStructs;
  private:
   oop* _handle;
 
--- a/src/share/vm/runtime/vmStructs.cpp	Tue Jul 21 15:16:01 2015 +0200
+++ b/src/share/vm/runtime/vmStructs.cpp	Tue Jul 21 16:15:22 2015 +0200
@@ -1010,6 +1010,9 @@
   /*********************************/                                                                                                \
   /* JNIHandles and JNIHandleBlock */                                                                                                \
   /*********************************/                                                                                                \
+                                                                                                                                     \
+  nonstatic_field(Handle,                      _handle,                                       oop*)                                  \
+                                                                                                                                     \
      static_field(JNIHandles,                  _global_handles,                               JNIHandleBlock*)                       \
      static_field(JNIHandles,                  _weak_global_handles,                          JNIHandleBlock*)                       \
      static_field(JNIHandles,                  _deleted_handle,                               oop)                                   \
@@ -1742,6 +1745,8 @@
   /* JNIHandles and JNIHandleBlock */                                     \
   /*********************************/                                     \
                                                                           \
+  declare_toplevel_type(Handle)                                           \
+                                                                          \
   declare_toplevel_type(JNIHandles)                                       \
   declare_toplevel_type(JNIHandleBlock)                                   \
   declare_toplevel_type(jobject)                                          \
@@ -2538,9 +2543,22 @@
   declare_constant(ConstantPoolCacheEntry::is_final_shift)                \
   declare_constant(ConstantPoolCacheEntry::is_forced_virtual_shift)       \
   declare_constant(ConstantPoolCacheEntry::is_vfinal_shift)               \
+  declare_constant(ConstantPoolCacheEntry::has_appendix_shift)            \
+  declare_constant(ConstantPoolCacheEntry::has_method_type_shift)         \
   declare_constant(ConstantPoolCacheEntry::is_field_entry_shift)          \
   declare_constant(ConstantPoolCacheEntry::tos_state_shift)               \
                                                                           \
+  declare_constant(ConstantPoolCacheEntry::cp_index_bits)                 \
+  declare_constant(ConstantPoolCacheEntry::cp_index_mask)                 \
+  declare_constant(ConstantPoolCacheEntry::bytecode_1_shift)              \
+  declare_constant(ConstantPoolCacheEntry::bytecode_1_mask)               \
+  declare_constant(ConstantPoolCacheEntry::bytecode_2_shift)              \
+  declare_constant(ConstantPoolCacheEntry::bytecode_2_mask)               \
+                                                                          \
+  declare_constant(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset) \
+  declare_constant(ConstantPoolCacheEntry::_indy_resolved_references_method_type_offset) \
+  declare_constant(ConstantPoolCacheEntry::_indy_resolved_references_entries) \
+                                                                          \
   /***************************************/                               \
   /* java_lang_Thread::ThreadStatus enum */                               \
   /***************************************/                               \