changeset 10753:64740220db85

Merge
author Andreas Woess <andreas.woess@jku.at>
date Mon, 15 Jul 2013 14:09:44 +0200
parents 3811d04d933e (diff) e2f5ae9afdc5 (current diff)
children 4c12d3756015
files
diffstat 37 files changed, 1253 insertions(+), 159 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerStampTest.java	Mon Jul 15 14:09:44 2013 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * This class tests that integer stamps are created correctly for constants.
+ */
+public class IntegerStampTest extends GraalCompilerTest {
+
+    private StructuredGraph graph;
+
+    @Before
+    public void before() {
+        graph = new StructuredGraph();
+    }
+
+    @Test
+    public void testBooleanConstant() {
+        assertEquals(new IntegerStamp(Kind.Int, 1, 1, 0x1), ConstantNode.forBoolean(true, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forBoolean(false, graph).integerStamp());
+    }
+
+    @Test
+    public void testByteConstant() {
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forByte((byte) 0, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 16, 16, 0x10), ConstantNode.forByte((byte) 16, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, -16, -16, 0xf0), ConstantNode.forByte((byte) -16, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 127, 127, 0x7f), ConstantNode.forByte((byte) 127, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0x80), ConstantNode.forByte((byte) -128, graph).integerStamp());
+    }
+
+    @Test
+    public void testShortConstant() {
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forShort((short) 0, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forShort((short) 128, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xff80), ConstantNode.forShort((short) -128, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 32767, 32767, 0x7fff), ConstantNode.forShort((short) 32767, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, -32768, -32768, 0x8000), ConstantNode.forShort((short) -32768, graph).integerStamp());
+    }
+
+    @Test
+    public void testCharConstant() {
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forChar((char) 0, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 'A', 'A', 'A'), ConstantNode.forChar('A', graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forChar((char) 128, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 65535, 65535, 0xffff), ConstantNode.forChar((char) 65535, graph).integerStamp());
+    }
+
+    @Test
+    public void testIntConstant() {
+        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0), ConstantNode.forInt(0, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80), ConstantNode.forInt(128, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xffffff80L), ConstantNode.forInt(-128, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Int, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).integerStamp());
+    }
+
+    @Test
+    public void testLongConstant() {
+        assertEquals(new IntegerStamp(Kind.Long, 0, 0, 0x0), ConstantNode.forLong(0, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Long, 128, 128, 0x80), ConstantNode.forLong(128, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Long, -128, -128, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Long, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).integerStamp());
+        assertEquals(new IntegerStamp(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).integerStamp());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Jul 15 14:09:44 2013 +0200
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test.ea;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.virtual.phases.ea.*;
+
+public class PEAReadEliminationTest extends GraalCompilerTest {
+
+    private StructuredGraph graph;
+
+    public static Object staticField;
+
+    public static class TestObject implements Callable<Integer> {
+
+        public int x;
+        public int y;
+
+        public TestObject(int x, int y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public Integer call() throws Exception {
+            return x;
+        }
+    }
+
+    public static class TestObject2 {
+
+        public Object x;
+        public Object y;
+
+        public TestObject2(Object x, Object y) {
+            this.x = x;
+            this.y = y;
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static int testSimpleSnippet(TestObject a) {
+        a.x = 2;
+        staticField = a;
+        return a.x;
+    }
+
+    @Test
+    public void testSimple() {
+        ValueNode result = getReturn("testSimpleSnippet").result();
+        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
+        assertTrue(result.isConstant());
+        assertEquals(2, result.asConstant().asInt());
+    }
+
+    @SuppressWarnings("all")
+    public static int testSimpleConflictSnippet(TestObject a, TestObject b) {
+        a.x = 2;
+        b.x = 3;
+        staticField = a;
+        return a.x;
+    }
+
+    @Test
+    public void testSimpleConflict() {
+        ValueNode result = getReturn("testSimpleConflictSnippet").result();
+        assertFalse(result.isConstant());
+        assertTrue(result instanceof LoadFieldNode);
+    }
+
+    @SuppressWarnings("all")
+    public static int testParamSnippet(TestObject a, int b) {
+        a.x = b;
+        return a.x;
+    }
+
+    @Test
+    public void testParam() {
+        ValueNode result = getReturn("testParamSnippet").result();
+        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
+        assertEquals(graph.getLocal(1), result);
+    }
+
+    @SuppressWarnings("all")
+    public static int testMaterializedSnippet(int a) {
+        TestObject obj = new TestObject(a, 0);
+        staticField = obj;
+        return obj.x;
+    }
+
+    @Test
+    public void testMaterialized() {
+        ValueNode result = getReturn("testMaterializedSnippet").result();
+        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
+        assertEquals(graph.getLocal(0), result);
+    }
+
+    @SuppressWarnings("all")
+    public static int testSimpleLoopSnippet(TestObject obj, int a, int b) {
+        obj.x = a;
+        for (int i = 0; i < 10; i++) {
+            staticField = obj;
+        }
+        return obj.x;
+    }
+
+    @Test
+    public void testSimpleLoop() {
+        ValueNode result = getReturn("testSimpleLoopSnippet").result();
+        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
+        assertEquals(graph.getLocal(1), result);
+    }
+
+    @SuppressWarnings("all")
+    public static int testBadLoopSnippet(TestObject obj, TestObject obj2, int a, int b) {
+        obj.x = a;
+        for (int i = 0; i < 10; i++) {
+            staticField = obj;
+            obj2.x = 10;
+            obj.x = 0;
+        }
+        return obj.x;
+    }
+
+    @Test
+    public void testBadLoop() {
+        ValueNode result = getReturn("testBadLoopSnippet").result();
+        assertEquals(0, graph.getNodes(LoadFieldNode.class).count());
+        assertTrue(result instanceof ProxyNode);
+        assertTrue(((ProxyNode) result).value() instanceof PhiNode);
+    }
+
+    @SuppressWarnings("all")
+    public static int testBadLoop2Snippet(TestObject obj, TestObject obj2, int a, int b) {
+        obj.x = a;
+        for (int i = 0; i < 10; i++) {
+            obj.x = 0;
+            obj2.x = 10;
+        }
+        return obj.x;
+    }
+
+    @Test
+    public void testBadLoop2() {
+        ValueNode result = getReturn("testBadLoop2Snippet").result();
+        assertEquals(1, graph.getNodes(LoadFieldNode.class).count());
+        assertTrue(result instanceof LoadFieldNode);
+    }
+
+    @SuppressWarnings("all")
+    public static int testPhiSnippet(TestObject a, int b) {
+        if (b < 0) {
+            a.x = 1;
+        } else {
+            a.x = 2;
+        }
+        return a.x;
+    }
+
+    @Test
+    public void testPhi() {
+        ValueNode result = getReturn("testPhiSnippet").result();
+        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
+        assertTrue(result instanceof PhiNode);
+        PhiNode phi = (PhiNode) result;
+        assertTrue(phi.valueAt(0).isConstant());
+        assertTrue(phi.valueAt(1).isConstant());
+        assertEquals(1, phi.valueAt(0).asConstant().asInt());
+        assertEquals(2, phi.valueAt(1).asConstant().asInt());
+    }
+
+    @SuppressWarnings("all")
+    public static void testSimpleStoreSnippet(TestObject a, int b) {
+        a.x = b;
+        a.x = b;
+    }
+
+    @Test
+    public void testSimpleStore() {
+        processMethod("testSimpleStoreSnippet");
+        assertEquals(1, graph.getNodes().filter(StoreFieldNode.class).count());
+    }
+
+    final ReturnNode getReturn(String snippet) {
+        processMethod(snippet);
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first();
+    }
+
+    private void processMethod(final String snippet) {
+        graph = parse(snippet);
+        Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
+        new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+        new PartialEscapePhase(false, true, canonicalizer).apply(graph, context);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Jul 15 14:09:44 2013 +0200
@@ -236,7 +236,15 @@
             Register receiver = asRegister(cc.getArgument(0));
             AMD64Address src = new AMD64Address(receiver, config.hubOffset);
 
-            asm.cmpq(inlineCacheKlass, src);
+            AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
+            HotSpotRuntime hr = ((HotSpotRuntime) gen.getRuntime());
+            if (hr.config.useCompressedKlassPointers) {
+                Register register = r10;
+                AMD64Move.decodeKlassPointer(asm, register, src, hr.config.narrowKlassBase, hr.config.narrowKlassShift, hr.config.logKlassAlignment);
+                asm.cmpq(inlineCacheKlass, register);
+            } else {
+                asm.cmpq(inlineCacheKlass, src);
+            }
             asm.jcc(ConditionFlag.NotEqual, unverifiedStub);
         }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Jul 15 14:09:44 2013 +0200
@@ -413,10 +413,16 @@
         AMD64AddressValue loadAddress = asAddressValue(address);
         Variable result = newVariable(kind);
         assert access == null || access instanceof HeapAccess;
-        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
-            Variable scratch = newVariable(Kind.Long);
-            append(new LoadCompressedPointer(kind, result, scratch, loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase, runtime().config.narrowOopShift,
-                            runtime().config.logMinObjAlignment));
+        if (isCompressCandidate(access)) {
+            if (runtime().config.useCompressedOops && kind == Kind.Object) {
+                append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase, runtime().config.narrowOopShift,
+                                runtime().config.logMinObjAlignment));
+            } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) {
+                append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) : null, runtime().config.narrowKlassBase, runtime().config.narrowKlassShift,
+                                runtime().config.logKlassAlignment));
+            } else {
+                append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
+            }
         } else {
             append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
         }
@@ -430,17 +436,31 @@
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
             if (canStoreConstant(c)) {
-                append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
+                if (inputVal.getKind() == Kind.Object) {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
+                } else if (inputVal.getKind() == Kind.Long) {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedKlassPointers && isCompressCandidate(access)));
+                } else {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, false));
+                }
                 return;
             }
         }
         Variable input = load(inputVal);
-        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
-            if (input.getKind() == Kind.Object) {
+        if (isCompressCandidate(access)) {
+            if (runtime().config.useCompressedOops && kind == Kind.Object) {
+                if (input.getKind() == Kind.Object) {
+                    Variable scratch = newVariable(Kind.Long);
+                    append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+                } else {
+                    // the input oop is already compressed
+                    append(new StoreOp(input.getKind(), storeAddress, input, state));
+                }
+            } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) {
                 Variable scratch = newVariable(Kind.Long);
-                append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+                append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowKlassBase, runtime().config.narrowKlassShift, runtime().config.logKlassAlignment));
             } else {
-                append(new StoreOp(input.getKind(), storeAddress, input, state));
+                append(new StoreOp(kind, storeAddress, input, state));
             }
         } else {
             append(new StoreOp(kind, storeAddress, input, state));
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Mon Jul 15 14:09:44 2013 +0200
@@ -287,6 +287,103 @@
         return "Test".equals(c1);
     }
 
+    @SuppressWarnings("unchecked")
+    public static Object[] unmodListTestByte(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        List<Byte> queue = (ArrayList<Byte>) c1;
+        Byte[] result = Collections.unmodifiableCollection(queue).toArray(new Byte[queue.size()]);
+        return result;
+    }
+
+    @Test
+    public void test13() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("unmodListTestByte");
+        List<Byte> list = new ArrayList<>();
+        Byte[] array = (Byte[]) installedBenchmarkCode.execute(list, null, null);
+        Assert.assertTrue(list.size() == array.length);
+    }
+
+    @Test
+    public void test14() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferTest");
+        StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest");
+        Assert.assertTrue(buffer.length() == 28);
+        String a = new String("TestTestTestTestTestTestTest");
+        installedBenchmarkCode.execute(buffer, a.toCharArray(), null);
+        Assert.assertTrue(buffer.length() == 56);
+        Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+    }
+
+    public static void stringBufferTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        StringBuffer source = (StringBuffer) c1;
+        char[] add = (char[]) c2;
+        for (int i = 0; i < add.length; i++) {
+            source.append(add[i]);
+        }
+    }
+
+    @Test
+    public void test15() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferTestIn");
+        installedBenchmarkCode.execute(null, null, null);
+    }
+
+    @SuppressWarnings("unused")
+    public static void stringBufferTestIn(Object c1, Object c2, Object c3) {
+        StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest");
+        Assert.assertTrue(buffer.length() == 28);
+        String a = new String("TestTestTestTestTestTestTest");
+        char[] add = a.toCharArray();
+        for (int i = 0; i < add.length; i++) {
+            buffer.append(add[i]);
+        }
+        Assert.assertTrue(buffer.length() == 56);
+        Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+    }
+
+    @Test
+    public void test16() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferArrayCopy");
+        installedBenchmarkCode.execute(null, null, null);
+    }
+
+    @SuppressWarnings("unused")
+    public static void stringBufferArrayCopy(Object c1, Object c2, Object c3) {
+        StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest");
+        Assert.assertTrue(buffer.length() == 28);
+        String a = new String("TestTestTestTestTestTestTest");
+        char[] dst = new char[buffer.length() * 2];
+        System.arraycopy(buffer.toString().toCharArray(), 0, dst, 0, buffer.length());
+        System.arraycopy(a.toCharArray(), 0, dst, buffer.length(), buffer.length());
+        Assert.assertTrue(dst.length == 56);
+        Assert.assertTrue(new String(dst).equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+    }
+
+    @Test
+    public void test17() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringFormat");
+        installedBenchmarkCode.execute(null, null, null);
+    }
+
+    @SuppressWarnings("unused")
+    public static void stringFormat(Object c1, Object c2, Object c3) {
+        String.format("Hello %d", 0);
+        String.format("Hello %d", -11);
+        String.format("Hello %d", -2147483648);
+    }
+
+    @Test
+    public void test18() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBuilder");
+        StringBuilder b = (StringBuilder) installedBenchmarkCode.execute(null, null, null);
+        Assert.assertTrue(b.capacity() == 16);
+        Assert.assertTrue(b.length() == 0);
+    }
+
+    @SuppressWarnings("unused")
+    public static Object stringBuilder(Object c1, Object c2, Object c3) {
+        return new StringBuilder();
+    }
+
     static class Container {
 
         public Object a = new Object();
@@ -352,5 +449,4 @@
 
         }
     }
-
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Jul 15 14:09:44 2013 +0200
@@ -153,6 +153,13 @@
     }
 
     /**
+     * Reads a klass pointer from a constant object.
+     */
+    public static long unsafeReadKlassPointer(Object object) {
+        return instance.getCompilerToVM().readUnsafeKlassPointer(object);
+    }
+
+    /**
      * Reads a word value from a given object.
      */
     public static long unsafeReadWord(Object object, long offset) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Jul 15 14:09:44 2013 +0200
@@ -58,6 +58,9 @@
     public long narrowOopBase;
     public int narrowOopShift;
     public int logMinObjAlignment;
+    public long narrowKlassBase;
+    public int narrowKlassShift;
+    public int logKlassAlignment;
 
     // CPU capabilities
     public int useSSE;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Jul 15 14:09:44 2013 +0200
@@ -216,6 +216,8 @@
 
     Object readUnsafeUncompressedPointer(Object o, long displacement);
 
+    long readUnsafeKlassPointer(Object o);
+
     /**
      * Invalidates the profiling information and restarts profiling upon the next invocation.
      * 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Jul 15 14:09:44 2013 +0200
@@ -173,6 +173,9 @@
     public native Object readUnsafeUncompressedPointer(Object o, long displacement);
 
     @Override
+    public native long readUnsafeKlassPointer(Object o);
+
+    @Override
     public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
         return executeCompiledMethodIntrinsic(arg1, arg2, arg3, hotspotInstalledCode);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Jul 15 14:09:44 2013 +0200
@@ -649,6 +649,10 @@
             ResolvedJavaMethod method = loadMethodNode.getMethod();
             ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, loadMethodNode.getHub(), method);
             graph.replaceFixed(loadMethodNode, metaspaceMethod);
+        } else if (n instanceof StoreHubNode) {
+            StoreHubNode storeHub = (StoreHubNode) n;
+            WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue());
+            graph.replaceFixed(storeHub, hub);
         } else if (n instanceof FixedGuardNode) {
             FixedGuardNode node = (FixedGuardNode) n;
             GuardingNode guard = tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated());
@@ -836,7 +840,13 @@
     private ReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object) {
         LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false));
+        return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, config.useCompressedKlassPointers));
+    }
+
+    private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) {
+        LocationNode location = ConstantLocationNode.create(ANY_LOCATION, wordKind, config.hubOffset, graph);
+        assert !object.isConstant() || object.asConstant().isNull();
+        return graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE, config.useCompressedKlassPointers));
     }
 
     public static long referentOffset() {
@@ -1157,7 +1167,15 @@
             case Int:
                 return Constant.forInt(base == null ? unsafe.getInt(displacement) : unsafe.getInt(base, displacement));
             case Long:
-                return Constant.forLong(base == null ? unsafe.getLong(displacement) : unsafe.getLong(base, displacement));
+                if (displacement == config().hubOffset && this.getGraalRuntime().getRuntime().config.useCompressedKlassPointers) {
+                    if (base == null) {
+                        throw new GraalInternalError("Base of object must not be null");
+                    } else {
+                        return Constant.forLong(this.getGraalRuntime().getCompilerToVM().readUnsafeKlassPointer(base));
+                    }
+                } else {
+                    return Constant.forLong(base == null ? unsafe.getLong(displacement) : unsafe.getLong(base, displacement));
+                }
             case Float:
                 return Constant.forFloat(base == null ? unsafe.getFloat(displacement) : unsafe.getFloat(base, displacement));
             case Double:
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Jul 15 14:09:44 2013 +0200
@@ -277,7 +277,7 @@
 
     public static void initializeObjectHeader(Word memory, Word markWord, Word hub) {
         memory.writeWord(markOffset(), markWord, MARK_WORD_LOCATION);
-        memory.writeWord(hubOffset(), hub, HUB_LOCATION);
+        StoreHubNode.write(memory.toObject(), hub);
     }
 
     @Fold
@@ -351,6 +351,11 @@
     }
 
     @Fold
+    public static int instanceHeaderSize() {
+        return config().useCompressedKlassPointers ? (2 * wordSize()) - 4 : 2 * wordSize();
+    }
+
+    @Fold
     public static int cardTableShift() {
         return config().cardtableShift;
     }
@@ -468,6 +473,7 @@
     }
 
     public static Word loadWordFromObject(Object object, int offset) {
+        assert offset != hubOffset() : "Use loadHubIntrinsic instead";
         return loadWordFromObjectIntrinsic(object, 0, offset, getWordKind());
     }
 
@@ -483,7 +489,10 @@
     @SuppressWarnings("unused")
     @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true)
     static Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word) {
-        return Word.box(unsafeReadWord(object, hubOffset()));
+        if (wordKind() == Kind.Int) {
+            return Word.box((int) unsafeReadKlassPointer(object));
+        }
+        return Word.box(unsafeReadKlassPointer(object));
     }
 
     @Fold
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Jul 15 14:09:44 2013 +0200
@@ -203,12 +203,12 @@
             if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) {
                 new_seqInit.inc();
                 explodeLoop();
-                for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
+                for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) {
                     memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                 }
             } else {
                 new_loopInit.inc();
-                for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
+                for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) {
                     memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                 }
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Mon Jul 15 14:09:44 2013 +0200
@@ -57,7 +57,7 @@
         Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, useG1GC());
 
         Pointer memory = Word.fromObject(result);
-        for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) {
+        for (int offset = instanceHeaderSize(); offset < instanceSize; offset += wordSize()) {
             memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION);
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Jul 15 14:09:44 2013 +0200
@@ -94,7 +94,7 @@
                 if (memory.notEqual(0)) {
                     Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
                     initializeObjectHeader(memory, prototypeMarkWord, hub);
-                    for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) {
+                    for (int offset = instanceHeaderSize(); offset < sizeInBytes; offset += wordSize()) {
                         memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                     }
                     return verifyObject(memory.toObject());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Mon Jul 15 14:09:44 2013 +0200
@@ -213,7 +213,7 @@
                     fatal("oop not in heap: %p", oop.rawValue());
                 }
 
-                Word klass = oop.readWord(hubOffset());
+                Word klass = loadHub(object);
                 if (klass.equal(Word.zero())) {
                     fatal("klass for oop %p is null", oop.rawValue());
                 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Jul 15 14:09:44 2013 +0200
@@ -120,26 +120,27 @@
 
     public static class LoadCompressedPointer extends LoadOp {
 
-        private long narrowOopBase;
-        private int narrowOopShift;
-        private int logMinObjAlignment;
-        @Temp({REG}) private AllocatableValue scratch;
+        private long base;
+        private int shift;
+        private int alignment;
 
-        public LoadCompressedPointer(Kind kind, AllocatableValue result, AllocatableValue scratch, AMD64AddressValue address, LIRFrameState state, long narrowOopBase, int narrowOopShift,
-                        int logMinObjAlignment) {
+        public LoadCompressedPointer(Kind kind, AllocatableValue result, AMD64AddressValue address, LIRFrameState state, long base, int shift, int alignment) {
             super(kind, result, address, state);
-            this.narrowOopBase = narrowOopBase;
-            this.narrowOopShift = narrowOopShift;
-            this.logMinObjAlignment = logMinObjAlignment;
-            this.scratch = scratch;
-            assert kind == Kind.Object;
+            this.base = base;
+            this.shift = shift;
+            this.alignment = alignment;
+            assert kind == Kind.Object || kind == Kind.Long;
         }
 
         @Override
         public void emitMemAccess(AMD64MacroAssembler masm) {
             Register resRegister = asRegister(result);
             masm.movl(resRegister, address.toAddress());
-            decodePointer(masm, resRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+            if (kind == Kind.Object) {
+                decodePointer(masm, resRegister, base, shift, alignment);
+            } else {
+                decodeKlassPointer(masm, resRegister, base, shift, alignment);
+            }
         }
     }
 
@@ -189,31 +190,34 @@
     public static class StoreCompressedPointer extends AMD64LIRInstruction {
 
         protected final Kind kind;
-        private long narrowOopBase;
-        private int narrowOopShift;
-        private int logMinObjAlignment;
+        private long base;
+        private int shift;
+        private int alignment;
         @Temp({REG}) private AllocatableValue scratch;
         @Alive({REG}) protected AllocatableValue input;
         @Alive({COMPOSITE}) protected AMD64AddressValue address;
         @State protected LIRFrameState state;
 
-        public StoreCompressedPointer(Kind kind, AMD64AddressValue address, AllocatableValue input, AllocatableValue scratch, LIRFrameState state, long narrowOopBase, int narrowOopShift,
-                        int logMinObjAlignment) {
-            this.narrowOopBase = narrowOopBase;
-            this.narrowOopShift = narrowOopShift;
-            this.logMinObjAlignment = logMinObjAlignment;
+        public StoreCompressedPointer(Kind kind, AMD64AddressValue address, AllocatableValue input, AllocatableValue scratch, LIRFrameState state, long base, int shift, int alignment) {
+            this.base = base;
+            this.shift = shift;
+            this.alignment = alignment;
             this.scratch = scratch;
             this.kind = kind;
             this.address = address;
             this.state = state;
             this.input = input;
-            assert kind == Kind.Object;
+            assert kind == Kind.Object || kind == Kind.Long;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
             masm.movq(asRegister(scratch), asRegister(input));
-            encodePointer(masm, asRegister(scratch), narrowOopBase, narrowOopShift, logMinObjAlignment);
+            if (kind == Kind.Object) {
+                encodePointer(masm, asRegister(scratch), base, shift, alignment);
+            } else {
+                encodeKlassPointer(masm, asRegister(scratch), base, shift, alignment);
+            }
             if (state != null) {
                 tasm.recordImplicitException(masm.codeBuffer.position(), state);
             }
@@ -290,7 +294,11 @@
                     break;
                 case Long:
                     if (NumUtil.isInt(input.asLong())) {
-                        masm.movslq(address.toAddress(), (int) input.asLong());
+                        if (compress) {
+                            masm.movl(address.toAddress(), (int) input.asLong());
+                        } else {
+                            masm.movslq(address.toAddress(), (int) input.asLong());
+                        }
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                     }
@@ -410,15 +418,15 @@
         @Alive protected AllocatableValue newValue;
         @Temp({REG}) protected AllocatableValue scratch;
 
-        private long narrowOopBase;
-        private int narrowOopShift;
-        private int logMinObjAlignment;
+        private long base;
+        private int shift;
+        private int alignment;
 
-        public CompareAndSwapCompressedOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, AllocatableValue scratch, long narrowOopBase,
-                        int narrowOopShift, int logMinObjAlignment) {
-            this.narrowOopBase = narrowOopBase;
-            this.narrowOopShift = narrowOopShift;
-            this.logMinObjAlignment = logMinObjAlignment;
+        public CompareAndSwapCompressedOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, AllocatableValue scratch, long base, int shift,
+                        int alignment) {
+            this.base = base;
+            this.shift = shift;
+            this.alignment = alignment;
             this.scratch = scratch;
             this.result = result;
             this.address = address;
@@ -429,7 +437,7 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            compareAndSwapCompressed(tasm, masm, result, address, cmpValue, newValue, scratch, narrowOopBase, narrowOopShift, logMinObjAlignment);
+            compareAndSwapCompressed(tasm, masm, result, address, cmpValue, newValue, scratch, base, shift, alignment);
         }
     }
 
@@ -643,56 +651,82 @@
     }
 
     protected static void compareAndSwapCompressed(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue,
-                    AllocatableValue newValue, AllocatableValue scratch, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+                    AllocatableValue newValue, AllocatableValue scratch, long base, int shift, int alignment) {
         assert AMD64.rax.equals(asRegister(cmpValue)) && AMD64.rax.equals(asRegister(result));
         final Register scratchRegister = asRegister(scratch);
         final Register cmpRegister = asRegister(cmpValue);
         final Register newRegister = asRegister(newValue);
-        encodePointer(masm, cmpRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+        encodePointer(masm, cmpRegister, base, shift, alignment);
         masm.movq(scratchRegister, newRegister);
-        encodePointer(masm, scratchRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+        encodePointer(masm, scratchRegister, base, shift, alignment);
         if (tasm.target.isMP) {
             masm.lock();
         }
         masm.cmpxchgl(scratchRegister, address.toAddress());
     }
 
-    private static void encodePointer(AMD64MacroAssembler masm, Register scratchRegister, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
-        // If the narrowOopBase is zero, the uncompressed address has to be shifted right
+    private static void encodePointer(AMD64MacroAssembler masm, Register scratchRegister, long base, int shift, int alignment) {
+        // If the base is zero, the uncompressed address has to be shifted right
         // in order to be compressed.
-        if (narrowOopBase == 0) {
-            if (narrowOopShift != 0) {
-                assert logMinObjAlignment == narrowOopShift : "Encode algorithm is wrong";
-                masm.shrq(scratchRegister, logMinObjAlignment);
+        if (base == 0) {
+            if (shift != 0) {
+                assert alignment == shift : "Encode algorithm is wrong";
+                masm.shrq(scratchRegister, alignment);
             }
         } else {
-            // Otherwise the narrow heap base, which resides always in register 12, is subtracted
+            // Otherwise the heap base, which resides always in register 12, is subtracted
             // followed by right shift.
             masm.testq(scratchRegister, scratchRegister);
             // If the stored reference is null, move the heap to scratch
             // register and then calculate the compressed oop value.
             masm.cmovq(ConditionFlag.Equal, scratchRegister, AMD64.r12);
             masm.subq(scratchRegister, AMD64.r12);
-            masm.shrq(scratchRegister, logMinObjAlignment);
+            masm.shrq(scratchRegister, alignment);
         }
     }
 
-    private static void decodePointer(AMD64MacroAssembler masm, Register resRegister, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
-        // If the narrowOopBase is zero, the compressed address has to be shifted left
+    private static void decodePointer(AMD64MacroAssembler masm, Register resRegister, long base, int shift, int alignment) {
+        // If the base is zero, the compressed address has to be shifted left
         // in order to be uncompressed.
-        if (narrowOopBase == 0) {
-            if (narrowOopShift != 0) {
-                assert logMinObjAlignment == narrowOopShift : "Decode algorithm is wrong";
-                masm.shlq(resRegister, logMinObjAlignment);
+        if (base == 0) {
+            if (shift != 0) {
+                assert alignment == shift : "Decode algorithm is wrong";
+                masm.shlq(resRegister, alignment);
             }
         } else {
             Label done = new Label();
-            masm.shlq(resRegister, logMinObjAlignment);
+            masm.shlq(resRegister, alignment);
             masm.jccb(ConditionFlag.Equal, done);
-            // Otherwise the narrow heap base is added to the shifted address.
+            // Otherwise the heap base is added to the shifted address.
             masm.addq(resRegister, AMD64.r12);
             masm.bind(done);
         }
     }
 
+    private static void encodeKlassPointer(AMD64MacroAssembler masm, Register scratchRegister, long base, int shift, int alignment) {
+        if (base != 0) {
+            masm.subq(scratchRegister, AMD64.r12);
+        }
+        if (shift != 0) {
+            assert alignment == shift : "Encode algorithm is wrong";
+            masm.shrq(scratchRegister, alignment);
+        }
+    }
+
+    private static void decodeKlassPointer(AMD64MacroAssembler masm, Register resRegister, long base, int shift, int alignment) {
+        if (shift != 0) {
+            assert alignment == shift : "Decode algorighm is wrong";
+            masm.shlq(resRegister, alignment);
+            if (base != 0) {
+                masm.addq(resRegister, AMD64.r12);
+            }
+        } else {
+            assert base == 0 : "Sanity";
+        }
+    }
+
+    public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, AMD64Address address, long narrowKlassBase, int narrowKlassShift, int logKlassAlignment) {
+        masm.movl(register, address);
+        decodeKlassPointer(masm, register, narrowKlassBase, narrowKlassShift, logKlassAlignment);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Mon Jul 15 14:09:44 2013 +0200
@@ -88,12 +88,11 @@
                 this.replaceAtUsages(BeginNode.prevBegin(this));
                 graph().removeFixed(this);
             } else {
-                FixedNode next = this.next();
-                if (next != null) {
-                    tool.deleteBranch(next);
-                }
-                setNext(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason)));
-                return;
+                FixedWithNextNode predecessor = (FixedWithNextNode) predecessor();
+                DeoptimizeNode deopt = graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason));
+                deopt.setDeoptimizationState(getDeoptimizationState());
+                tool.deleteBranch(this);
+                predecessor.setNext(deopt);
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Mon Jul 15 14:09:44 2013 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public final class StoreHubNode extends FixedWithNextNode implements Lowerable {
+
+    @Input private ValueNode value;
+    @Input private ValueNode object;
+
+    public ValueNode getValue() {
+        return value;
+    }
+
+    public ValueNode getObject() {
+        return object;
+    }
+
+    private StoreHubNode(ValueNode object, ValueNode value) {
+        super(StampFactory.forVoid());
+        this.value = value;
+        this.object = object;
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @NodeIntrinsic
+    public static native void write(Object object, Object value);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Jul 15 14:09:44 2013 +0200
@@ -25,7 +25,9 @@
 import static com.oracle.graal.api.code.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -66,6 +68,10 @@
         return forStoreCheck;
     }
 
+    // TODO (ds) remove once performance regression in compiler.sunflow (and other benchmarks)
+    // caused by new lowering is fixed
+    private static final boolean useNewLowering = true; // Boolean.getBoolean("graal.checkcast.useNewLowering");
+
     /**
      * Lowers a {@link CheckCastNode} to a {@link GuardingPiNode}. That is:
      * 
@@ -94,20 +100,31 @@
      */
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile));
-        Stamp stamp = StampFactory.declared(type).join(object.stamp());
-        ValueNode condition;
-        if (stamp == null) {
-            // This is a check cast that will always fail
-            condition = LogicConstantNode.contradiction(graph());
-            stamp = StampFactory.declared(type);
-        } else if (object.stamp().nonNull()) {
-            condition = typeTest;
+        if (useNewLowering) {
+            InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile));
+            Stamp stamp = StampFactory.declared(type).join(object.stamp());
+            ValueNode condition;
+            if (stamp == null) {
+                // This is a check cast that will always fail
+                condition = LogicConstantNode.contradiction(graph());
+                stamp = StampFactory.declared(type);
+            } else if (object.stamp().nonNull()) {
+                condition = typeTest;
+            } else {
+                if (profile != null && profile.getNullSeen() == TriState.FALSE) {
+                    FixedGuardNode nullGuard = graph().add(new FixedGuardNode(graph().unique(new IsNullNode(object)), UnreachedCode, DeoptimizationAction.InvalidateReprofile, true));
+                    graph().addBeforeFixed(this, nullGuard);
+                    condition = typeTest;
+                    stamp = stamp.join(StampFactory.objectNonNull());
+                } else {
+                    condition = graph().unique(new LogicDisjunctionNode(graph().unique(new IsNullNode(object)), typeTest));
+                }
+            }
+            GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp));
+            graph().replaceFixedWithFixed(this, checkedObject);
         } else {
-            condition = graph().unique(new LogicDisjunctionNode(graph().unique(new IsNullNode(object)), typeTest));
+            tool.getRuntime().lower(this, tool);
         }
-        GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp));
-        graph().replaceFixedWithFixed(this, checkedObject);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Mon Jul 15 14:09:44 2013 +0200
@@ -132,18 +132,21 @@
     }
 
     public static Stamp forConstant(Constant value) {
-        assert value.getKind() != Kind.Object;
-        if (value.getKind() == Kind.Object) {
-            throw new GraalInternalError("unexpected kind: %s", value.getKind());
-        } else {
-            if (value.getKind() == Kind.Int || value.getKind() == Kind.Long) {
-                return forInteger(value.getKind(), value.asLong(), value.asLong(), value.asLong() & IntegerStamp.defaultMask(value.getKind()));
-            } else if (value.getKind() == Kind.Float) {
-                return forFloat(value.getKind(), value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
-            } else if (value.getKind() == Kind.Double) {
-                return forFloat(value.getKind(), value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
-            }
-            return forKind(value.getKind().getStackKind());
+        Kind kind = value.getKind();
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+                return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), value.asLong() & IntegerStamp.defaultMask(kind));
+            case Float:
+                return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
+            case Double:
+                return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
+            default:
+                throw new GraalInternalError("unexpected kind: %s", kind);
         }
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Jul 15 14:09:44 2013 +0200
@@ -397,15 +397,24 @@
                 GraphUtil.killWithUnusedFloatingInputs(guard);
                 metricGuardsRemoved.increment();
             } else {
-                LogicNode replacement = evaluateCondition(condition, trueConstant, falseConstant);
-                if (replacement != null) {
-                    guard.setCondition(replacement);
-                    if (condition.usages().isEmpty()) {
-                        GraphUtil.killWithUnusedFloatingInputs(condition);
+                ValueNode anchor = state.trueConditions.get(condition);
+                if (anchor != null) {
+                    if (!guard.negated()) {
+                        guard.replaceAtUsages(anchor);
+                        metricGuardsRemoved.increment();
+                        GraphUtil.killWithUnusedFloatingInputs(guard);
                     }
-                    metricGuardsRemoved.increment();
                 } else {
-                    registerCondition(!guard.negated(), condition, guard);
+                    anchor = state.falseConditions.get(condition);
+                    if (anchor != null) {
+                        if (guard.negated()) {
+                            guard.replaceAtUsages(anchor);
+                            metricGuardsRemoved.increment();
+                            GraphUtil.killWithUnusedFloatingInputs(guard);
+                        }
+                    } else {
+                        registerCondition(!guard.negated(), condition, guard);
+                    }
                 }
             }
         }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Mon Jul 15 14:09:44 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.printer;
 
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.*;
@@ -32,7 +33,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.phases.schedule.*;
@@ -151,8 +151,8 @@
                 // Check for method scopes that must be closed since the previous dump.
                 for (int i = 0; i < previousInlineContext.size(); ++i) {
                     if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
-                        for (int j = previousInlineContext.size() - 1; j >= i; --j) {
-                            closeScope();
+                        for (int inlineDepth = previousInlineContext.size() - 1; inlineDepth >= i; --inlineDepth) {
+                            closeScope(inlineDepth);
                         }
                         break;
                     }
@@ -161,8 +161,8 @@
                 // Check for method scopes that must be opened since the previous dump.
                 for (int i = 0; i < inlineContext.size(); ++i) {
                     if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
-                        for (int j = i; j < inlineContext.size(); ++j) {
-                            openScope(inlineContext.get(j), j == 0);
+                        for (int inlineDepth = i; inlineDepth < inlineContext.size(); ++inlineDepth) {
+                            openScope(inlineContext.get(inlineDepth), inlineDepth);
                         }
                         break;
                     }
@@ -191,11 +191,11 @@
 
     private static List<String> getInlineContext() {
         List<String> result = new ArrayList<>();
-        Object last = null;
+        Object lastMethodOrGraph = null;
         for (Object o : Debug.context()) {
-            JavaMethod method = GraalDebugConfig.asJavaMethod(o);
+            JavaMethod method = asJavaMethod(o);
             if (method != null) {
-                if (last != method) {
+                if (lastMethodOrGraph == null || asJavaMethod(lastMethodOrGraph) != method) {
                     result.add(MetaUtil.format("%H::%n(%p)", method));
                 } else {
                     // This prevents multiple adjacent method context objects for the same method
@@ -211,7 +211,9 @@
                     result.add(debugDumpScope.name);
                 }
             }
-            last = o;
+            if (o instanceof JavaMethod || o instanceof Graph) {
+                lastMethodOrGraph = o;
+            }
         }
         if (result.isEmpty()) {
             result.add("Top Scope");
@@ -229,8 +231,8 @@
         return result;
     }
 
-    private void openScope(String name, boolean showThread) {
-        String prefix = showThread ? Thread.currentThread().getName() + ":" : "";
+    private void openScope(String name, int inlineDepth) {
+        String prefix = inlineDepth == 0 ? Thread.currentThread().getName() + ":" : "";
         try {
             printer.beginGroup(prefix + name, name, Debug.contextLookup(ResolvedJavaMethod.class), -1);
         } catch (IOException e) {
@@ -239,7 +241,8 @@
         }
     }
 
-    private void closeScope() {
+    private void closeScope(int inlineDepth) {
+        dumpIds[inlineDepth] = 0;
         try {
             printer.endGroup();
         } catch (IOException e) {
@@ -250,8 +253,8 @@
 
     @Override
     public void close() {
-        for (int i = 0; i < previousInlineContext.size(); i++) {
-            closeScope();
+        for (int inlineDepth = 0; inlineDepth < previousInlineContext.size(); inlineDepth++) {
+            closeScope(inlineDepth);
         }
         if (printer != null) {
             printer.close();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Mon Jul 15 14:09:44 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Mon Jul 15 14:09:44 2013 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.schedule.*;
@@ -39,21 +40,26 @@
 
 public class PartialEscapePhase extends EffectsPhase<PhaseContext> {
 
+    //@formatter:off
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEarlyReadElimination = new OptionValue<>(true);
+    //@formatter:on
+
+    private final boolean readElimination;
+
     public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer) {
+        this(iterative, OptEarlyReadElimination.getValue(), canonicalizer);
+    }
+
+    public PartialEscapePhase(boolean iterative, boolean readElimination, CanonicalizerPhase canonicalizer) {
         super(iterative ? EscapeAnalysisIterations.getValue() : 1, canonicalizer);
+        this.readElimination = readElimination;
     }
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
         if (VirtualUtil.matches(graph, EscapeAnalyzeOnly.getValue())) {
-            boolean analyzableNodes = false;
-            for (Node node : graph.getNodes()) {
-                if (node instanceof VirtualizableAllocation) {
-                    analyzableNodes = true;
-                    break;
-                }
-            }
-            if (analyzableNodes) {
+            if (readElimination || graph.getNodes().filterInterface(VirtualizableAllocation.class).isNotEmpty()) {
                 runAnalysis(graph, context);
             }
         }
@@ -61,7 +67,11 @@
 
     @Override
     protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule) {
-        return new PartialEscapeClosure.Final(schedule, context.getRuntime(), context.getAssumptions());
+        if (readElimination) {
+            return new ReadEliminationPEClosure(schedule, context.getRuntime(), context.getAssumptions());
+        } else {
+            return new PartialEscapeClosure.Final(schedule, context.getRuntime(), context.getAssumptions());
+        }
     }
 
     public static Map<Invoke, Double> getHints(StructuredGraph graph) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationPEBlockState.java	Mon Jul 15 14:09:44 2013 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.virtual.phases.ea;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.virtual.*;
+
+public class ReadEliminationPEBlockState extends PartialEscapeBlockState<ReadEliminationPEBlockState> {
+
+    final HashMap<ReadCacheEntry, ValueNode> readCache;
+
+    static class ReadCacheEntry {
+
+        public final ResolvedJavaField identity;
+        public final ValueNode object;
+
+        public ReadCacheEntry(ResolvedJavaField identity, ValueNode object) {
+            this.identity = identity;
+            this.object = object;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = 31 + ((identity == null) ? 0 : identity.hashCode());
+            return 31 * result + ((object == null) ? 0 : object.hashCode());
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            ReadCacheEntry other = (ReadCacheEntry) obj;
+            return identity == other.identity && object == other.object;
+        }
+
+        @Override
+        public String toString() {
+            return object + ":" + identity;
+        }
+    }
+
+    public ReadEliminationPEBlockState() {
+        readCache = new HashMap<>();
+    }
+
+    public ReadEliminationPEBlockState(ReadEliminationPEBlockState other) {
+        super(other);
+        readCache = new HashMap<>(other.readCache);
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + " " + readCache;
+    }
+
+    @Override
+    protected void objectMaterialized(VirtualObjectNode virtual, AllocatedObjectNode representation, List<ValueNode> values) {
+        if (virtual instanceof VirtualInstanceNode) {
+            VirtualInstanceNode instance = (VirtualInstanceNode) virtual;
+            for (int i = 0; i < instance.entryCount(); i++) {
+                readCache.put(new ReadCacheEntry(instance.field(i), representation), values.get(i));
+            }
+        }
+    }
+
+    @Override
+    public boolean equivalentTo(ReadEliminationPEBlockState other) {
+        if (!compareMapsNoSize(readCache, other.readCache)) {
+            return false;
+        }
+        return super.equivalentTo(other);
+    }
+
+    public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value) {
+        ValueNode cacheObject;
+        ObjectState obj = getObjectState(object);
+        if (obj != null) {
+            assert !obj.isVirtual();
+            cacheObject = obj.getMaterializedValue();
+        } else {
+            cacheObject = object;
+        }
+        readCache.put(new ReadCacheEntry(identity, cacheObject), value);
+    }
+
+    public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity) {
+        ValueNode cacheObject;
+        ObjectState obj = getObjectState(object);
+        if (obj != null) {
+            assert !obj.isVirtual();
+            cacheObject = obj.getMaterializedValue();
+        } else {
+            cacheObject = object;
+        }
+        ValueNode cacheValue = readCache.get(new ReadCacheEntry(identity, cacheObject));
+        obj = getObjectState(cacheValue);
+        if (obj != null) {
+            assert !obj.isVirtual();
+            cacheValue = obj.getMaterializedValue();
+        } else {
+            // assert !scalarAliases.containsKey(cacheValue);
+            cacheValue = getScalarAlias(cacheValue);
+        }
+        return cacheValue;
+    }
+
+    public void killReadCache() {
+        readCache.clear();
+    }
+
+    public void killReadCache(ResolvedJavaField identity) {
+        Iterator<Map.Entry<ReadCacheEntry, ValueNode>> iter = readCache.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<ReadCacheEntry, ValueNode> entry = iter.next();
+            if (entry.getKey().identity == identity) {
+                iter.remove();
+            }
+        }
+    }
+
+    public Map<ReadCacheEntry, ValueNode> getReadCache() {
+        return readCache;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationPEClosure.java	Mon Jul 15 14:09:44 2013 +0200
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.virtual.phases.ea;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.virtual.phases.ea.ReadEliminationPEBlockState.ReadCacheEntry;
+
+public class ReadEliminationPEClosure extends PartialEscapeClosure<ReadEliminationPEBlockState> {
+
+    public ReadEliminationPEClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
+        super(schedule, metaAccess, assumptions);
+    }
+
+    @Override
+    protected ReadEliminationPEBlockState getInitialState() {
+        return new ReadEliminationPEBlockState();
+    }
+
+    @Override
+    protected boolean processNode(Node node, ReadEliminationPEBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
+        boolean deleted = super.processNode(node, state, effects, lastFixedNode);
+        if (!deleted) {
+            if (node instanceof LoadFieldNode) {
+                LoadFieldNode load = (LoadFieldNode) node;
+                ValueNode cachedValue = state.getReadCache(load.object(), load.field());
+                if (cachedValue != null) {
+                    effects.replaceAtUsages(load, cachedValue);
+                    state.addScalarAlias(load, cachedValue);
+                } else {
+                    state.addReadCache(load.object(), load.field(), load);
+                }
+                deleted = true;
+            } else if (node instanceof StoreFieldNode) {
+                StoreFieldNode store = (StoreFieldNode) node;
+                ValueNode cachedValue = state.getReadCache(store.object(), store.field());
+
+                if (state.getScalarAlias(store.value()) == cachedValue) {
+                    effects.deleteFixedNode(store);
+                    deleted = true;
+                }
+                state.killReadCache(store.field());
+                state.addReadCache(store.object(), store.field(), store.value());
+            } else if (node instanceof MemoryCheckpoint.Single) {
+                METRIC_MEMORYCHECKOINT.increment();
+                LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
+                processIdentity(state, identity);
+            } else if (node instanceof MemoryCheckpoint.Multi) {
+                METRIC_MEMORYCHECKOINT.increment();
+                for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) {
+                    processIdentity(state, identity);
+                }
+            }
+        }
+        return deleted;
+    }
+
+    private static void processIdentity(ReadEliminationPEBlockState state, LocationIdentity identity) {
+        if (identity instanceof ResolvedJavaField) {
+            state.killReadCache((ResolvedJavaField) identity);
+        } else if (identity == ANY_LOCATION) {
+            state.killReadCache();
+        }
+    }
+
+    @Override
+    protected void processLoopExit(LoopExitNode exitNode, ReadEliminationPEBlockState initialState, ReadEliminationPEBlockState exitState, GraphEffectList effects) {
+        super.processLoopExit(exitNode, initialState, exitState, effects);
+
+        for (Map.Entry<ReadCacheEntry, ValueNode> entry : exitState.getReadCache().entrySet()) {
+            if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
+                ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null);
+                effects.addFloatingNode(proxy, "readCacheProxy");
+                entry.setValue(proxy);
+            }
+        }
+    }
+
+    @Override
+    protected ReadEliminationPEBlockState cloneState(ReadEliminationPEBlockState other) {
+        return new ReadEliminationPEBlockState(other);
+    }
+
+    @Override
+    protected MergeProcessor createMergeProcessor(Block merge) {
+        return new ReadEliminationMergeProcessor(merge);
+    }
+
+    private class ReadEliminationMergeProcessor extends MergeProcessor {
+
+        public ReadEliminationMergeProcessor(Block mergeBlock) {
+            super(mergeBlock);
+        }
+
+        @Override
+        protected void merge(List<ReadEliminationPEBlockState> states) {
+            super.merge(states);
+
+            mergeReadCache(states);
+        }
+
+        private void mergeReadCache(List<ReadEliminationPEBlockState> states) {
+            for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
+                ReadCacheEntry key = entry.getKey();
+                ValueNode value = entry.getValue();
+                boolean phi = false;
+                for (int i = 1; i < states.size(); i++) {
+                    ValueNode otherValue = states.get(i).readCache.get(key);
+                    if (otherValue == null) {
+                        value = null;
+                        phi = false;
+                        break;
+                    }
+                    if (!phi && otherValue != value) {
+                        phi = true;
+                    }
+                }
+                if (phi) {
+                    PhiNode phiNode = getCachedPhi(entry, value.kind());
+                    mergeEffects.addFloatingNode(phiNode, "mergeReadCache");
+                    for (int i = 0; i < states.size(); i++) {
+                        afterMergeEffects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity));
+                    }
+                    newState.readCache.put(key, phiNode);
+                } else if (value != null) {
+                    newState.readCache.put(key, value);
+                }
+            }
+            for (PhiNode phi : merge.phis()) {
+                if (phi.kind() == Kind.Object) {
+                    for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
+                        if (entry.getKey().object == phi.valueAt(0)) {
+                            mergeReadCachePhi(phi, entry.getKey().identity, states);
+                        }
+                    }
+
+                }
+            }
+        }
+
+        private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List<ReadEliminationPEBlockState> states) {
+            ValueNode[] values = new ValueNode[phi.valueCount()];
+            for (int i = 0; i < phi.valueCount(); i++) {
+                ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity);
+                if (value == null) {
+                    return;
+                }
+                values[i] = value;
+            }
+
+            PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].kind());
+            mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi");
+            for (int i = 0; i < values.length; i++) {
+                afterMergeEffects.addPhiInput(phiNode, values[i]);
+            }
+            newState.readCache.put(new ReadCacheEntry(identity, phi), phiNode);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Mon Jul 15 14:09:44 2013 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
+import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Node1Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeInfo.Kind;
+
+public class PolymorphicTest2 {
+
+    @Test
+    public void testMultipleTypes() {
+        /* Tests the unexpected polymorphic case. */
+        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
+        assertEquals(21, executeWith(node, false, false));
+        assertEquals(42, executeWith(node, 21, 21));
+        assertEquals("(boolean,int)", executeWith(node, false, 42));
+        assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+    }
+
+    @SuppressWarnings("unused")
+    @PolymorphicLimit(3)
+    abstract static class Node1 extends BinaryNode {
+
+        @Specialization(order = 1)
+        int add(int left, int right) {
+            return 42;
+        }
+
+        @Specialization(order = 2)
+        int add(boolean left, boolean right) {
+            return 21;
+        }
+
+        @Specialization(order = 4)
+        String add(boolean left, int right) {
+            return "(boolean,int)";
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Jul 15 14:09:44 2013 +0200
@@ -352,17 +352,26 @@
     public static void replaceChild(Node parent, Node oldChild, Node newChild) {
         NodeClass nodeClass = NodeClass.get(parent.getClass());
 
-        for (long fieldOffset : nodeClass.childOffsets) {
+        long[] fieldOffsets = nodeClass.childOffsets;
+        for (int i = 0; i < fieldOffsets.length; i++) {
+            long fieldOffset = fieldOffsets[i];
             if (unsafe.getObject(parent, fieldOffset) == oldChild) {
+                assert assertAssignable(nodeClass, parent, oldChild, newChild);
                 unsafe.putObject(parent, fieldOffset, newChild);
             }
         }
-        for (long fieldOffset : nodeClass.childrenOffsets) {
-            Node[] array = (Node[]) unsafe.getObject(parent, fieldOffset);
-            if (array != null) {
-                for (int i = 0; i < array.length; i++) {
-                    if (array[i] == oldChild) {
-                        array[i] = newChild;
+
+        long[] childrenOffsets = nodeClass.childrenOffsets;
+        for (int i = 0; i < childrenOffsets.length; i++) {
+            long fieldOffset = childrenOffsets[i];
+            Object arrayObject = unsafe.getObject(parent, fieldOffset);
+            if (arrayObject != null) {
+                assert arrayObject instanceof Node[] : "Children must be instanceof Node[] ";
+                Node[] array = (Node[]) arrayObject;
+                for (int j = 0; j < array.length; j++) {
+                    if (array[j] == oldChild) {
+                        assert newChild != null && array.getClass().getComponentType().isAssignableFrom(newChild.getClass()) : "Array type does not match";
+                        array[j] = newChild;
                         return;
                     }
                 }
@@ -370,6 +379,26 @@
         }
     }
 
+    private static boolean assertAssignable(NodeClass clazz, Node parent, Object oldValue, Object newValue) {
+        if (newValue == null) {
+            return true;
+        }
+        for (NodeField field : clazz.fields) {
+            if (field.kind != NodeFieldKind.CHILD) {
+                continue;
+            }
+            if (unsafe.getObject(parent, field.offset) == oldValue) {
+                if (!field.type.isAssignableFrom(newValue.getClass())) {
+                    assert false : "Child class " + newValue.getClass() + " is not assignable to field " + field.type.getName() + " at " + field.name + " in ";
+                    return false;
+                } else {
+                    break;
+                }
+            }
+        }
+        return true;
+    }
+
     /** Returns all declared fields in the class hierarchy. */
     private static Field[] getAllFields(Class<? extends Object> clazz) {
         Field[] declaredFields = clazz.getDeclaredFields();
@@ -660,4 +689,5 @@
             p.print("    ");
         }
     }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon Jul 15 14:09:44 2013 +0200
@@ -32,6 +32,7 @@
 import javax.lang.model.util.*;
 
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.ast.*;
@@ -1226,6 +1227,12 @@
         private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) {
             String name = executeCachedName(polymorph);
             CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name);
+
+            ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
+            boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
+            if (sourceThrowsUnexpected) {
+                cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class));
+            }
             addInternalValueParameters(cachedExecute, polymorph, true, true);
 
             if (polymorph == node.getGenericPolymorphicSpecialization()) {
@@ -2441,11 +2448,18 @@
             }
 
             if (!returnBuilder.isEmpty()) {
-                builder.startReturn();
+
+                ExecutableTypeData sourceExecutableType = node.findExecutableType(specialization.getReturnType().getTypeSystemType(), 0);
+                boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
+                boolean targetSupportsUnexpected = executable.hasUnexpectedValue(getContext());
 
                 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
                 TypeData sourceType = specialization.getReturnType().getTypeSystemType();
 
+                if (specialization.isPolymorphic() && sourceThrowsUnexpected && !targetSupportsUnexpected) {
+                    builder.startTryBlock();
+                }
+                builder.startReturn();
                 if (targetType == null || sourceType == null) {
                     builder.tree(returnBuilder.getRoot());
                 } else if (sourceType.needsCastTo(getContext(), targetType)) {
@@ -2454,6 +2468,19 @@
                     builder.tree(returnBuilder.getRoot());
                 }
                 builder.end();
+                if (specialization.isPolymorphic() && sourceThrowsUnexpected && !targetSupportsUnexpected) {
+                    builder.end();
+                    builder.startCatchBlock(getUnexpectedValueException(), "ex");
+                    builder.startReturn();
+                    CodeTree returns = CodeTreeBuilder.singleString("ex.getResult()");
+                    if (sourceType.needsCastTo(getContext(), targetType)) {
+                        builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), returns));
+                    } else {
+                        builder.tree(returns);
+                    }
+                    builder.end();
+                    builder.end();
+                }
             }
 
             if (!specialization.getExceptions().isEmpty()) {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Mon Jul 15 14:09:44 2013 +0200
@@ -118,8 +118,8 @@
             }
         };
         
-        server = new Server(callback, false);
-        binaryServer = new Server(callback, true);
+        server = new Server(getDocument(), callback, false);
+        binaryServer = new Server(getDocument(), callback, true);
     }
 
     public void clear() {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Mon Jul 15 14:09:44 2013 +0200
@@ -110,14 +110,14 @@
                     }
                 };
                 final GraphParser parser;
+                final OutlineTopComponent component = OutlineTopComponent.findInstance();
                 if (file.getName().endsWith(".xml")) {
                     parser = new Parser(channel, monitor, null);
                 } else if (file.getName().endsWith(".bgv")) {
-                    parser = new BinaryParser(channel, monitor, null);
+                    parser = new BinaryParser(channel, monitor, component.getDocument(), null);
                 } else {
                     parser = null;
                 }
-                final OutlineTopComponent component = OutlineTopComponent.findInstance();
                 RequestProcessor.getDefault().post(new Runnable() {
                     @Override
                     public void run() {
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Mon Jul 15 14:09:44 2013 +0200
@@ -69,6 +69,7 @@
     private final List<Object> constantPool;
     private final ByteBuffer buffer;
     private final ReadableByteChannel channel;
+    private final GraphDocument rootDocument;
     private final Deque<Folder> folderStack;
     private final ParseMonitor monitor;
     
@@ -240,12 +241,13 @@
         }
     }
 
-    public BinaryParser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback callback) {
+    public BinaryParser(ReadableByteChannel channel, ParseMonitor monitor, GraphDocument rootDocument, GroupCallback callback) {
         this.callback = callback;
         constantPool = new ArrayList<>();
         buffer = ByteBuffer.allocateDirect(256 * 1024);
         buffer.flip();
         this.channel = channel;
+        this.rootDocument = rootDocument;
         folderStack = new LinkedList<>();
         this.monitor = monitor;
     }
@@ -527,8 +529,7 @@
 
     @Override
     public GraphDocument parse() throws IOException {
-        GraphDocument doc = new GraphDocument();
-        folderStack.push(doc);
+        folderStack.push(rootDocument);
         if (monitor != null) {
             monitor.setState("Starting parsing");
         }
@@ -542,7 +543,7 @@
         if (monitor != null) {
             monitor.setState("Finished parsing");
         }
-        return doc;
+        return rootDocument;
     }
 
     private void parseRoot() throws IOException {
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java	Mon Jul 15 14:09:44 2013 +0200
@@ -24,6 +24,7 @@
  */
 package com.sun.hotspot.igv.connection;
 
+import com.sun.hotspot.igv.data.GraphDocument;
 import com.sun.hotspot.igv.data.serialization.BinaryParser;
 import com.sun.hotspot.igv.data.serialization.Parser;
 import com.sun.hotspot.igv.data.services.GroupCallback;
@@ -34,12 +35,14 @@
 public class Client implements Runnable {
     private final boolean binary;
     private final SocketChannel socket;
+    private final GraphDocument rootDocument;
     private final GroupCallback callback;
 
-    public Client(SocketChannel socket, GroupCallback callback, boolean  binary) {
+    public Client(SocketChannel socket, GraphDocument rootDocument, GroupCallback callback, boolean  binary) {
         this.callback = callback;
         this.socket = socket;
         this.binary = binary;
+        this.rootDocument = rootDocument;
     }
 
     @Override
@@ -49,7 +52,7 @@
             final SocketChannel channel = socket;
             channel.configureBlocking(true);
             if (binary) {
-                new BinaryParser(channel, null, callback).parse();
+                new BinaryParser(channel, null, rootDocument, callback).parse();
             } else {
                 new Parser(channel, null, callback).parse();
             }
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java	Thu Jul 11 22:14:27 2013 +0200
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java	Mon Jul 15 14:09:44 2013 +0200
@@ -24,6 +24,7 @@
  */
 package com.sun.hotspot.igv.connection;
 
+import com.sun.hotspot.igv.data.GraphDocument;
 import com.sun.hotspot.igv.data.services.GroupCallback;
 import com.sun.hotspot.igv.settings.Settings;
 import java.io.IOException;
@@ -43,12 +44,14 @@
 public class Server implements PreferenceChangeListener {
     private final boolean binary;
     private ServerSocketChannel serverSocket;
+    private final GraphDocument rootDocument;
     private final GroupCallback callback;
     private int port;
     private Runnable serverRunnable;
 
-    public Server(GroupCallback callback, boolean binary) {
+    public Server(GraphDocument rootDocument, GroupCallback callback, boolean binary) {
         this.binary = binary;
+        this.rootDocument = rootDocument;
         this.callback = callback;
         initializeNetwork();
         Settings.get().addPreferenceChangeListener(this);
@@ -87,7 +90,7 @@
                             clientSocket.close();
                             return;
                         }
-                        RequestProcessor.getDefault().post(new Client(clientSocket, callback, binary), 0, Thread.MAX_PRIORITY);
+                        RequestProcessor.getDefault().post(new Client(clientSocket, rootDocument, callback, binary), 0, Thread.MAX_PRIORITY);
                     } catch (IOException ex) {
                         serverSocket = null;
                         NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jul 11 22:14:27 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Jul 15 14:09:44 2013 +0200
@@ -867,6 +867,10 @@
   set_address("narrowOopBase", Universe::narrow_oop_base());
   set_int("narrowOopShift", Universe::narrow_oop_shift());
   set_int("logMinObjAlignment", LogMinObjAlignmentInBytes);
+  set_address("narrowKlassBase", Universe::narrow_klass_base());
+  set_int("narrowKlassShift", Universe::narrow_klass_shift());
+  set_int("logKlassAlignment", LogKlassAlignmentInBytes);
+
 
   set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()));
   set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()));
@@ -1186,6 +1190,11 @@
   return JNIHandles::make_local(*((oop*)address));
 C2V_END
 
+C2V_VMENTRY(jlong, readUnsafeKlassPointer, (JNIEnv *env, jobject, jobject o))
+  oop resolved_o = JNIHandles::resolve(o);
+  jlong klass = (jlong)(address)resolved_o->klass();
+  return klass;
+C2V_END
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@@ -1265,6 +1274,7 @@
   {CC"reprofile",                     CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
   {CC"invalidateInstalledCode",       CC"("HS_INSTALLED_CODE")V",                                       FN_PTR(invalidateInstalledCode)},
   {CC"readUnsafeUncompressedPointer", CC"("OBJECT"J)"OBJECT,                                            FN_PTR(readUnsafeUncompressedPointer)},
+  {CC"readUnsafeKlassPointer",        CC"("OBJECT")J",                                                  FN_PTR(readUnsafeKlassPointer)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/runtime/arguments.cpp	Thu Jul 11 22:14:27 2013 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Mon Jul 15 14:09:44 2013 +0200
@@ -2208,12 +2208,9 @@
 #ifdef GRAAL
   if (UseCompressedKlassPointers) {
     if (IgnoreUnrecognizedVMOptions) {
-      warning("UseCompressedKlassPointers is disabled, because it is not supported by Graal");
-      FLAG_SET_CMDLINE(bool, UseCompressedKlassPointers, false);
+      FLAG_SET_CMDLINE(bool, UseCompressedKlassPointers, true);
     } else {
-      jio_fprintf(defaultStream::error_stream(),
-                    "UseCompressedKlassPointers are not supported in Graal at the moment\n");
-      status = false;
+      status = true;
     }
   } else {
     // This prevents the flag being set to true by set_ergonomics_flags()
--- a/src/share/vm/runtime/deoptimization.cpp	Thu Jul 11 22:14:27 2013 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Mon Jul 15 14:09:44 2013 +0200
@@ -1300,8 +1300,8 @@
   nmethodLocker nl(fr.pc());
 
   // Log a message
-  Events::log(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT,
-              trap_request, fr.pc());
+  Events::log(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT " relative=" INTPTR_FORMAT,
+              trap_request, fr.pc(), fr.pc() - fr.cb()->code_begin());
 
   {
     ResourceMark rm;