changeset 9956:8ad4e90fc5d7

Merge.
author Christian Haeubl <haeubl@ssw.jku.at>
date Mon, 10 Jun 2013 08:44:25 +0200
parents de73bbbde021 (current diff) 60648c97cdd0 (diff)
children 1b33ef6544b4
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java
diffstat 66 files changed, 2365 insertions(+), 1306 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jun 10 08:44:25 2013 +0200
@@ -90,6 +90,20 @@
         }
     }
 
+    public static class Fmt2e {
+        public Fmt2e(SPARCAssembler asm, int op, int c4lo, int cc2, int rs1, int d10lo, int regOrImmediate) {
+            assert op == 0;
+            assert (cc2 & 0xFFFFFFFE) == 0;
+            assert c4lo >= 0 && rs1 < 0x10;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert (regOrImmediate & 0x1F) < 0x20;
+            assert (regOrImmediate & 0xFFFFC000) == 0;
+            assert (d10lo & 0xFFFFFC00) == 0;
+
+            asm.emitInt(op << 30 | 1 << 28 | 3 << 22 | cc2 << 21 | (d10lo >> 8) << 19 | rs1 << 14 | (d10lo & 0xff) << 5 | regOrImmediate);
+        }
+    }
+
     public static class Fmt3a {
         public Fmt3a(SPARCAssembler masm, int op, int rd, int op3, int rs1, int rs2) {
             assert  op == 2 || op == 3;
@@ -158,6 +172,18 @@
         }
     }
 
+    public static class Fmt3n {
+        public Fmt3n(SPARCAssembler masm, int op, int op3, int opf, int rs2, int rd) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert opf >= 0 && opf < 0x200;
+            assert rs2 >= 0 && rs2 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | opf << 5 | rs2);
+        }
+    }
+
     public static class Fmt3p {
         public Fmt3p(SPARCAssembler masm, int op, int op3, int opf, int rs1, int rs2, int rd) {
             assert  op == 2 || op == 3;
@@ -171,18 +197,6 @@
         }
     }
 
-    public static class Fmt3n {
-        public Fmt3n(SPARCAssembler masm, int op, int op3, int opf, int rs2, int rd) {
-            assert  op == 2 || op == 3;
-            assert op3 >= 0 && op3 < 0x40;
-            assert opf >= 0 && opf < 0x200;
-            assert rs2 >= 0 && rs2 < 0x20;
-            assert  rd >= 0 &&  rd < 0x20;
-
-            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | opf << 5 | rs2);
-        }
-    }
-
     public static class Fmt3q {
         public Fmt3q(SPARCAssembler masm, int op, int op3, int rs1, int rd) {
             assert  op == 2 || op == 3;
@@ -239,6 +253,20 @@
         }
     }
 
+    public static class Fmt5a {
+        public Fmt5a(SPARCAssembler masm, int op, int op3, int op5, int rs1, int rs2, int rs3, int rd) {
+            assert   op == 2;
+            assert  op3 >= 0 &&  op3 < 0x40;
+            assert  op5 >= 0 &&  op5 < 0x10;
+            assert  rs1 >= 0 &&  rs1 < 0x20;
+            assert  rs2 >= 0 &&  rs2 < 0x20;
+            assert  rs3 >= 0 &&  rs3 < 0x20;
+            assert  rd  >= 0 &&  rd  < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | rs3 << 9 | op5 << 5 | rs2);
+        }
+    }
+
     public static final int ImmedTrue = 0x00002000;
 
     public enum Ops {
@@ -389,6 +417,27 @@
         }
     }
 
+    public enum Op5s {
+        Fmadds(0x1),
+        Fmaddd(0x2),
+        Fmsubs(0x5),
+        Fmsubd(0x6),
+        Fnmsubs(0x9),
+        Fnmsubd(0xA),
+        Fnmadds(0xD),
+        Fnmaddd(0xE);
+
+        private final int value;
+
+        private Op5s(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
     public enum Opfs {
         Fmovs(0x01, "fmovs"),
         Fmovd(0x02, "fmovd"),
@@ -399,6 +448,62 @@
         Fabss(0x09, "fabss"),
         Fabsd(0x0A, "fabsd"),
         Fabsq(0x0B, "fabsq"),
+
+        // start VIS1
+        Edge8cc(0x0, "edge8cc"),
+        Edge8n(0x1, "edge8n"),
+        Edge8lcc(0x2, "edge8lcc"),
+        Edge8ln(0x3, "edge8ln"),
+        Edge16cc(0x4, "edge16cc"),
+        Edge16n(0x5, "edge16n"),
+        Edge16lcc(0x6, "edge16lcc"),
+        Edge16ln(0x7, "edge16ln"),
+        Edge32cc(0x8, "edge32cc"),
+        Edge32n(0x9, "edge32n"),
+        Edge32lcc(0xA, "edge32lcc"),
+        Edge32ln(0xB, "edge32ln"),
+        Array8(0x10, "array8"),
+        Array16(0x12, "array16"),
+        Array32(0x14, "array32"),
+        AlignAddress(0x18, "alignaddress"),
+        AlignAddressLittle(0x1A, "alignaddress_little"),
+        Fmul8x16(0x31, "fmul8x16"),
+        Fmul8x16au(0x33, "fmul8x16au"),
+        Fmul8x16al(0x35, "fmul8x16al"),
+        Fmul8sux16(0x36, "fmul8sux16"),
+        Fmul8ulx16(0x37, "fmul8ulx16"),
+        Fmuld8sux16(0x38, "fmuld8sux16"),
+        Fmuld8ulx16(0x39, "fmuld8ulx16"),
+        Faligndatag(0x48, "faligndata"),
+        Fnhadds(0x71, "fnhadds"),
+        Fnhaddd(0x72, "fnhaddd"),
+        // end VIS1
+
+        // start VIS2
+        Bmask(0x19, "bmask"),
+        Bshuffle(0x4c, "bshuffle"),
+        // end VIS2 only
+
+        // start VIS3
+        Addxc(0x11, "addxc"),
+        Addxccc(0x13, "addxccc"),
+        Cmask8(0x1B, "cmask8"),
+        Cmask16(0x1D, "cmask16"),
+        Cmask32(0x1F, "cmask32"),
+        Fmean16(0x40, "fmean16"),
+        Fnadds(0x51, "fnadds"),
+        Fnaddd(0x52, "fnaddd"),
+        // end VIS3
+
+        // start CAMMELLIA
+        CammelliaFl(0x13C, "cammelia_fl"),
+        CammelliaFli(0x13D, "cammellia_fli"),
+        // end CAMMELLIA
+
+        // start CRYPTO
+        Crc32c(0x147, "crc32c"),
+        // end CRYPTO
+
         Fadds(0x41, "fadds"),
         Faddd(0x42, "faddd"),
         Faddq(0x43, "faddq"),
@@ -663,6 +768,38 @@
         }
     }
 
+    public static class Addxc extends Fmt3p {
+        public Addxc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Addxc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Addxccc extends Fmt3p {
+        public Addxccc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Addxccc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Alignaddr extends Fmt3p {
+        public Alignaddr(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.AlignAddress.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Alignaddrl extends Fmt3p {
+        public Alignaddrl(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.AlignAddressLittle.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class And extends Fmt3b {
         public And(SPARCAssembler masm, Register src1, int simm13, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.And.getValue(), src1.encoding(), simm13, dst.encoding());
@@ -699,6 +836,38 @@
         }
     }
 
+    public static class Array8 extends Fmt3p {
+        public Array8(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Array8.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Array16 extends Fmt3p {
+        public Array16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Array16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Array32 extends Fmt3p {
+        public Array32(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Array32.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Bmask extends Fmt3p {
+        public Bmask(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS2 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Bmask.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Bpa extends Fmt2c {
         public Bpa(SPARCAssembler masm, int simmm19) {
             super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Always.getValue(),
@@ -891,11 +1060,456 @@
         }
     }
 
+    public static class Bshuffle extends Fmt3p {
+        public Bshuffle(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS2 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Bshuffle.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class CammelliaFl extends Fmt3p {
+        public CammelliaFl(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* CAMELLIA only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.CammelliaFl.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class CammelliaFli extends Fmt3p {
+        public CammelliaFli(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* CAMELLIA only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.CammelliaFli.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     private static int patchUnbound(SPARCAssembler masm, Label label) {
         label.addPatchAt(masm.codeBuffer.position());
         return 0;
     }
 
+    public static class Cmask8 extends Fmt3n {
+        public Cmask8(SPARCAssembler asm, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Cmask8.getValue(),
+                            src2.encoding(), 0);
+        }
+    }
+
+    public static class Cmask16 extends Fmt3n {
+        public Cmask16(SPARCAssembler asm, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Cmask16.getValue(),
+                            src2.encoding(), 0);
+        }
+    }
+
+    public static class Cmask32 extends Fmt3n {
+        public Cmask32(SPARCAssembler asm, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Cmask32.getValue(),
+                            src2.encoding(), 0);
+        }
+    }
+
+    public static class Crc32c extends Fmt3p {
+        public Crc32c(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* CRYPTO only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Crc32c.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Cwbcc extends Fmt2e {
+        public Cwbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbcc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbcs extends Fmt2e {
+        public Cwbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbcs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbe extends Fmt2e {
+        public Cwbe(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbe(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbg extends Fmt2e {
+        public Cwbg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbge extends Fmt2e {
+        public Cwbge(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbge(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbgu extends Fmt2e {
+        public Cwbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbgu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbl extends Fmt2e {
+        public Cwbl(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbl(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwble extends Fmt2e {
+        public Cwble(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwble(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbleu extends Fmt2e {
+        public Cwbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbleu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbne extends Fmt2e {
+        public Cwbne(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbne(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbneg extends Fmt2e {
+        public Cwbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbneg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbpos extends Fmt2e {
+        public Cwbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbpos(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbvc extends Fmt2e {
+        public Cwbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbvc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbvs extends Fmt2e {
+        public Cwbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbvs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbcc extends Fmt2e {
+        public Cxbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbcc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbcs extends Fmt2e {
+        public Cxbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbcs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbe extends Fmt2e {
+        public Cxbe(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbe(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbg extends Fmt2e {
+        public Cxbg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbge extends Fmt2e {
+        public Cxbge(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbge(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbgu extends Fmt2e {
+        public Cxbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbgu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbl extends Fmt2e {
+        public Cxbl(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbl(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxble extends Fmt2e {
+        public Cxble(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxble(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbleu extends Fmt2e {
+        public Cxbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbleu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbne extends Fmt2e {
+        public Cxbne(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbne(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbneg extends Fmt2e {
+        public Cxbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbneg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbpos extends Fmt2e {
+        public Cxbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbpos(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbvc extends Fmt2e {
+        public Cxbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbvc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbvs extends Fmt2e {
+        public Cxbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbvs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Edge8cc extends Fmt3p {
+        public Edge8cc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge8cc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge8n extends Fmt3p {
+        public Edge8n(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge8n.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge8lcc extends Fmt3p {
+        public Edge8lcc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge8lcc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge8ln extends Fmt3p {
+        public Edge8ln(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge8ln.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge16cc extends Fmt3p {
+        public Edge16cc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge16cc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge16n extends Fmt3p {
+        public Edge16n(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge16n.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge16lcc extends Fmt3p {
+        public Edge16lcc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge16lcc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge16ln extends Fmt3p {
+        public Edge16ln(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge16ln.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge32cc extends Fmt3p {
+        public Edge32cc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge32cc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge32n extends Fmt3p {
+        public Edge32n(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge32n.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge32lcc extends Fmt3p {
+        public Edge32lcc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge32lcc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge32ln extends Fmt3p {
+        public Edge32ln(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge32ln.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fadds extends Fmt3p {
         public Fadds(SPARCAssembler masm, Register src1, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fadds.getValue(),
@@ -917,6 +1531,13 @@
         }
     }
 
+    public static class Faligndata extends Fmt3p {
+        public Faligndata(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Faligndatag.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fdivs extends Fmt3p {
         public Fdivs(SPARCAssembler masm, Register src1, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdivs.getValue(),
@@ -931,6 +1552,86 @@
         }
     }
 
+    public static class Fmadds extends Fmt5a {
+        public Fmadds(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmadds.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmaddd extends Fmt5a {
+        public Fmaddd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmaddd.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmean16 extends Fmt3p {
+        public Fmean16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmean16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmsubs extends Fmt5a {
+        public Fmsubs(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmsubs.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmsubd extends Fmt5a {
+        public Fmsubd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmsubd.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnadds extends Fmt3p {
+        public Fnadds(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnadds.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnaddd extends Fmt3p {
+        public Fnaddd(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnaddd.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnmadds extends Fmt5a {
+        public Fnmadds(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmadds.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnmaddd extends Fmt5a {
+        public Fnmaddd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmaddd.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnmsubs extends Fmt5a {
+        public Fnmsubs(SPARCAssembler masm, Register src1, Register src2, Register src3, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmsubs.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnmsubd extends Fmt5a {
+        public Fnmsubd(SPARCAssembler masm, Register src1, Register src2, Register src3, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmsubd.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fmuls extends Fmt3p {
         public Fmuls(SPARCAssembler masm, Register src1, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fmuls.getValue(),
@@ -945,6 +1646,62 @@
         }
     }
 
+    public static class Fmul8x16 extends Fmt3p {
+        public Fmul8x16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8x16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmul8x16au extends Fmt3p {
+        public Fmul8x16au(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8x16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmul8x16al extends Fmt3p {
+        public Fmul8x16al(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8x16al.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmul8sux16 extends Fmt3p {
+        public Fmul8sux16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8sux16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmul8ulx16 extends Fmt3p {
+        public Fmul8ulx16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8ulx16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmuld8sux16 extends Fmt3p {
+        public Fmuld8sux16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmuld8sux16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmuld8ulx16 extends Fmt3p {
+        public Fmuld8ulx16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmuld8ulx16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fnegs extends Fmt3n {
         public Fnegs(SPARCAssembler masm, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnegs.getValue(),
@@ -1463,6 +2220,127 @@
         }
     }
 
+    public static class Tcc extends Fmt4a {
+        public Tcc(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.CarryClear.getValue());
+        }
+        public Tcc(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.CarryClear.getValue());
+        }
+    }
+
+    public static class Tcs extends Fmt4a {
+        public Tcs(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.CarrySet.getValue());
+        }
+        public Tcs(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.CarrySet.getValue());
+        }
+    }
+
+    public static class Te extends Fmt4a {
+        public Te(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Equal.getValue());
+        }
+        public Te(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Equal.getValue());
+        }
+    }
+
+    public static class Tg extends Fmt4a {
+        public Tg(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Greater.getValue());
+        }
+        public Tg(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Greater.getValue());
+        }
+    }
+
+    public static class Tge extends Fmt4a {
+        public Tge(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.GreaterEqual.getValue());
+        }
+        public Tge(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.GreaterEqual.getValue());
+        }
+    }
+
+    public static class Tle extends Fmt4a {
+        public Tle(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.LessEqual.getValue());
+        }
+        public Tle(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.LessEqual.getValue());
+        }
+    }
+
+    public static class Tleu extends Fmt4a {
+        public Tleu(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.LessEqualUnsigned.getValue());
+        }
+        public Tleu(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.LessEqualUnsigned.getValue());
+        }
+    }
+
+    public static class Tn extends Fmt4a {
+        public Tn(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Never.getValue());
+        }
+        public Tn(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Never.getValue());
+        }
+    }
+
+    public static class Tne extends Fmt4a {
+        public Tne(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.NotEqual.getValue());
+        }
+        public Tne(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.NotEqual.getValue());
+        }
+    }
+
+    public static class Tneg extends Fmt4a {
+        public Tneg(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Negative.getValue());
+        }
+        public Tneg(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Negative.getValue());
+        }
+    }
+
+    public static class Tpos extends Fmt4a {
+        public Tpos(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Positive.getValue());
+        }
+        public Tpos(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Positive.getValue());
+        }
+    }
+
     public static class Tsubcc extends Fmt3b {
         public Tsubcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Tsubcc.getValue(), src1.encoding(), simm13, dst.encoding());
@@ -1484,6 +2362,28 @@
         }
     }
 
+    public static class Tvc extends Fmt4a {
+        public Tvc(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.OverflowClear.getValue());
+        }
+        public Tvc(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.OverflowClear.getValue());
+        }
+    }
+
+    public static class Tvs extends Fmt4a {
+        public Tvs(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.OverflowSet.getValue());
+        }
+        public Tvs(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.OverflowSet.getValue());
+        }
+    }
+
     @Deprecated
     public static class Udiv extends Fmt3b {
         @Deprecated
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Mon Jun 10 08:44:25 2013 +0200
@@ -212,6 +212,19 @@
     }
 
     @SuppressWarnings("unused")
+    public static class Mov {
+
+        public Mov(SPARCAssembler asm, Register src1, Register dst) {
+            assert src1.encoding() != dst.encoding();
+            new Or(asm, SPARC.g0, src1, dst);
+        }
+
+        public Mov(SPARCAssembler asm, int simm13, Register dst) {
+            new Or(asm, SPARC.g0, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
     public static class Not {
 
         public Not(SPARCAssembler asm, Register src1, Register dst) {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jun 10 08:44:25 2013 +0200
@@ -119,6 +119,13 @@
 
     @Override
     public void emitMove(AllocatableValue dst, Value src) {
+        // XXX SPARCAddress loads
+        /*
+         * if (src instanceof SPARCAddressValue) { public LoadOp(Kind kind, AllocatableValue result,
+         * SPARCAddressValue address, LIRFrameState state) {
+         * 
+         * return new LoadOp(result.getKind(), result, (SPARCAddressValue) src); }
+         */
         if (isRegister(src) || isStackSlot(dst)) {
             append(new MoveFromRegOp(dst, src));
         } else {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Jun 10 08:44:25 2013 +0200
@@ -309,7 +309,7 @@
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new PartialEscapeAnalysisPhase(false, false, new CanonicalizerPhase(true)).apply(graph, context);
+        new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
         new CullFrameStatesPhase().apply(graph);
     }
 
@@ -333,7 +333,7 @@
                 }
                 new DeadCodeEliminationPhase().apply(graph);
                 canonicalizer.apply(graph, context);
-                new PartialEscapeAnalysisPhase(false, false, canonicalizer).apply(graph, context);
+                new PartialEscapePhase(false, canonicalizer).apply(graph, context);
 
                 new CullFrameStatesPhase().apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Jun 10 08:44:25 2013 +0200
@@ -222,7 +222,7 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
-                new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true)).apply(graph, context);
+                new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context);
                 Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
                 ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
                 if (expectedConstantResult != null) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Jun 10 08:44:25 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
-import static com.oracle.graal.phases.GraalOptions.*;
 import static org.junit.Assert.*;
 
 import java.util.concurrent.*;
@@ -81,19 +80,6 @@
         assertEquals(graph.getLocal(0), result);
     }
 
-    @SuppressWarnings("all")
-    public static int testSimpleReadSnippet(TestObject a, int b) throws Exception {
-        a.callable = new TestInt(b, 9);
-        return a.callable.call();
-    }
-
-    @Test
-    public void testSimpleRead() {
-        ValueNode result = getReturn("testSimpleReadSnippet").result();
-        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
-        assertEquals(graph.getLocal(1), result);
-    }
-
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
         assertEquals(1, graph.getNodes(ReturnNode.class).count());
@@ -102,8 +88,7 @@
 
     private void processMethod(final String snippet) {
         graph = parse(snippet);
-        OptEarlyReadElimination.setValue(true);
         HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
-        new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false, new CanonicalizerPhase(true)).apply(graph, context);
+        new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, new CanonicalizerPhase(true)).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Jun 10 08:44:03 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-/*
- * 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.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);
-        new PartialEscapeAnalysisPhase(false, true, new CanonicalizerPhase(true)).apply(graph, context);
-    }
-}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Jun 10 08:44:25 2013 +0200
@@ -166,7 +166,7 @@
                 new DeadCodeEliminationPhase().apply(graph);
                 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
                 canonicalizer.apply(graph, context);
-                new PartialEscapeAnalysisPhase(false, false, canonicalizer).apply(graph, context);
+                new PartialEscapePhase(false, canonicalizer).apply(graph, context);
 
                 new CullFrameStatesPhase().apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Jun 10 08:44:25 2013 +0200
@@ -150,7 +150,7 @@
 
         if (Inline.getValue() && !plan.isPhaseDisabled(InliningPhase.class)) {
             if (IterativeInlining.getValue()) {
-                new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, OptEarlyReadElimination.getValue(), canonicalizer).apply(graph, highTierContext);
+                new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, canonicalizer).apply(graph, highTierContext);
             } else {
                 new InliningPhase(runtime, null, replacements, assumptions, cache, plan, optimisticOpts).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Jun 10 08:44:25 2013 +0200
@@ -68,12 +68,6 @@
     protected Block currentBlock;
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
-    private FrameState lastState;
-
-    /**
-     * Mapping from blocks to the last encountered frame state at the end of the block.
-     */
-    private final BlockMap<FrameState> blockLastState;
 
     /**
      * Checks whether the supplied constant can be used without loading it into a register for store
@@ -100,7 +94,6 @@
         this.nodeOperands = graph.createNodeMap();
         this.lir = lir;
         this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands);
-        this.blockLastState = new BlockMap<>(lir.cfg);
     }
 
     @SuppressWarnings("hiding")
@@ -291,41 +284,8 @@
         if (block == lir.cfg.getStartBlock()) {
             assert block.getPredecessorCount() == 0;
             emitPrologue();
-
         } else {
             assert block.getPredecessorCount() > 0;
-            FrameState fs = null;
-
-            for (Block pred : block.getPredecessors()) {
-                if (fs == null) {
-                    fs = blockLastState.get(pred);
-                } else {
-                    if (blockLastState.get(pred) == null) {
-                        // Only a back edge can have a null state for its enclosing block.
-                        assert pred.getEndNode() instanceof LoopEndNode;
-
-                        if (block.getBeginNode().stateAfter() == null) {
-                            // We'll assert later that the begin and end of a framestate-less loop
-                            // share the frame state that flowed into the loop
-                            blockLastState.put(pred, fs);
-                        }
-                    } else if (fs != blockLastState.get(pred)) {
-                        fs = null;
-                        break;
-                    }
-                }
-            }
-            if (TraceLIRGeneratorLevel.getValue() >= 2) {
-                if (fs == null) {
-                    TTY.println("STATE RESET");
-                } else {
-                    TTY.println("STATE CHANGE (singlePred)");
-                    if (TraceLIRGeneratorLevel.getValue() >= 3) {
-                        TTY.println(fs.toString(Node.Verbosity.Debugger));
-                    }
-                }
-            }
-            lastState = fs;
         }
 
         List<ScheduledNode> nodes = lir.nodesFor(block);
@@ -334,10 +294,6 @@
             if (TraceLIRGeneratorLevel.getValue() >= 3) {
                 TTY.println("LIRGen for " + instr);
             }
-            FrameState stateAfter = null;
-            if (instr instanceof StateSplit && !(instr instanceof InfopointNode)) {
-                stateAfter = ((StateSplit) instr).stateAfter();
-            }
             if (instr instanceof ValueNode) {
                 ValueNode valueNode = (ValueNode) instr;
                 if (operand(valueNode) == null) {
@@ -355,16 +311,6 @@
                     // before by other instructions.
                 }
             }
-            if (stateAfter != null) {
-                lastState = stateAfter;
-                assert checkStateReady(lastState);
-                if (TraceLIRGeneratorLevel.getValue() >= 2) {
-                    TTY.println("STATE CHANGE");
-                    if (TraceLIRGeneratorLevel.getValue() >= 3) {
-                        TTY.println(stateAfter.toString(Node.Verbosity.Debugger));
-                    }
-                }
-            }
         }
         if (block.getSuccessorCount() >= 1 && !endsWithJump(block)) {
             NodeClassIterable successors = block.getEndNode().successors();
@@ -377,11 +323,6 @@
             TTY.println("END Generating LIR for block B" + block.getId());
         }
 
-        // Check that the begin and end of a framestate-less loop
-        // share the frame state that flowed into the loop
-        assert blockLastState.get(block) == null || blockLastState.get(block) == lastState;
-
-        blockLastState.put(block, lastState);
         currentBlock = null;
 
         if (PrintIRWithLIR.getValue()) {
@@ -391,19 +332,6 @@
 
     protected abstract boolean peephole(ValueNode valueNode);
 
-    private boolean checkStateReady(FrameState state) {
-        FrameState fs = state;
-        while (fs != null) {
-            for (ValueNode v : fs.values()) {
-                if (v != null && !(v instanceof VirtualObjectNode)) {
-                    assert operand(v) != null : "Value " + v + " in " + fs + " is not ready!";
-                }
-            }
-            fs = fs.outerFrameState();
-        }
-        return true;
-    }
-
     private boolean endsWithJump(Block block) {
         List<LIRInstruction> instructions = lir.lir(block);
         if (instructions.size() == 0) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Jun 10 08:44:25 2013 +0200
@@ -45,7 +45,7 @@
         }
 
         if (PartialEscapeAnalysis.getValue()) {
-            addPhase(new PartialEscapeAnalysisPhase(true, OptEarlyReadElimination.getValue(), canonicalizer));
+            addPhase(new PartialEscapePhase(true, canonicalizer));
         }
 
         if (OptConvertDeoptsToGuards.getValue()) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Mon Jun 10 08:44:25 2013 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.sparc.*;
 
 /**
  * SPARC specific implementation of {@link HotSpotGraalRuntime}.
@@ -44,10 +45,15 @@
         return graalRuntime();
     }
 
+    protected static Architecture createArchitecture() {
+        return new SPARC();
+    }
+
     @Override
     protected TargetDescription createTarget() {
-        // SPARC: Create target description.
-        throw new InternalError("NYI");
+        final int stackFrameAlignment = 16;
+        final int implicitNullCheckLimit = 4096;
+        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, true);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Jun 10 08:44:25 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -87,9 +88,11 @@
         runtime.compilerToVm = toVM;
     }
 
+    private static final String DEFAULT_GRAAL_RUNTIME = "basic";
+
     // @formatter:off
     @Option(help = "The runtime configuration to use")
-    private static final OptionValue<String> GraalRuntime = new OptionValue<>("basic");
+    private static final OptionValue<String> GraalRuntime = new OptionValue<>(DEFAULT_GRAAL_RUNTIME);
     // @formatter:on
 
     protected static HotSpotGraalRuntimeFactory findFactory(String architecture) {
@@ -98,6 +101,11 @@
                 return factory;
             }
         }
+        if (!DEFAULT_GRAAL_RUNTIME.equals(GraalRuntime.getValue())) {
+            // Fail fast if a non-default value for GraalRuntime was specified
+            // and the corresponding factory is not available
+            throw new GraalInternalError("Specified runtime \"%s\" not available for the %s architecture", GraalRuntime.getValue(), architecture);
+        }
         return null;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Jun 10 08:44:25 2013 +0200
@@ -23,16 +23,28 @@
 
 package com.oracle.graal.hotspot;
 
+import static java.nio.file.Files.*;
+
+import java.io.*;
+import java.nio.charset.*;
+import java.nio.file.*;
 import java.util.*;
 
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.options.*;
 
+/**
+ * Called from {@code graalCompiler.cpp} to parse any Graal specific options. Such options are
+ * (currently) distinguished by a {@code "-G:"} prefix.
+ */
 public class HotSpotOptions {
 
     private static final Map<String, OptionDescriptor> options = new HashMap<>();
 
-    static {
+    /**
+     * Initializes {@link #options} from {@link Options} services.
+     */
+    private static void initializeOptions() {
         ServiceLoader<Options> sl = ServiceLoader.loadInstalled(Options.class);
         for (Options opts : sl) {
             for (OptionDescriptor desc : opts) {
@@ -45,6 +57,38 @@
         }
     }
 
+    /**
+     * Loads default option value overrides from a {@code graal.options} file if it exists. Each
+     * line in this file starts with {@code "#"} and is ignored or must have the format of a Graal
+     * command line option without the leading {@code "-G:"} prefix. These option value are set
+     * prior to processing of any Graal options present on the command line.
+     */
+    private static void loadOptionOverrides() throws InternalError {
+        String javaHome = System.getProperty("java.home");
+        Path graalDotOptions = Paths.get(javaHome, "lib", "graal.options");
+        if (!exists(graalDotOptions)) {
+            graalDotOptions = Paths.get(javaHome, "jre", "lib", "graal.options");
+        }
+        if (exists(graalDotOptions)) {
+            try {
+                for (String line : Files.readAllLines(graalDotOptions, Charset.defaultCharset())) {
+                    if (!line.startsWith("#")) {
+                        if (!setOption(line)) {
+                            throw new InternalError("Invalid option \"" + line + "\" specified in " + graalDotOptions);
+                        }
+                    }
+                }
+            } catch (IOException e) {
+                throw (InternalError) new InternalError().initCause(e);
+            }
+        }
+    }
+
+    static {
+        initializeOptions();
+        loadOptionOverrides();
+    }
+
     // Called from VM code
     public static boolean setOption(String option) {
         if (option.length() == 0) {
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Mon Jun 10 08:44:25 2013 +0200
@@ -373,6 +373,12 @@
             }
         } else {
             switch (opcode) {
+            // case A:  new Add(Int, dst, src1, src2);
+            // case S:  new Sub(Int, dst, src1, src2);
+            // case U:  new Shl(UnsignedInt, dst, src1, src2);
+            // case L:  new Shl(UnsignedLong, dst, src1, src2);
+            // case F:  new Add(Float, dst, src1, src2);
+            // case D:  new Mul(Double, dst, src1, src2);
             case IADD:  masm.add_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case ISUB:  masm.sub_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case IMUL:  masm.mul_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Mon Jun 10 08:44:25 2013 +0200
@@ -22,9 +22,16 @@
  */
 package com.oracle.graal.lir.sparc;
 
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Andn;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Or;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Popc;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Srl;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Srlx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Sub;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.isSimm13;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -54,6 +61,7 @@
     @SuppressWarnings("unused")
     public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
         Register dst = ValueUtil.asIntReg(result);
+        Register tmp = null;  // ??
         if (ValueUtil.isRegister(input)) {
             Register src = ValueUtil.asRegister(input);
             switch (opcode) {
@@ -65,9 +73,64 @@
                 case LPOPCNT:
                     new Popc(masm, src, dst);
                     break;
-                case BSF:  // masm.bsfq(dst, src);
-                case IBSR:  // masm.bsrl(dst, src);
-                case LBSR:  // masm.bsrq(dst, src);
+                case BSF:
+                    // countTrailingZerosI - bsfl
+                    // countTrailingZerosL - masm.bsfq(dst, src);
+                    Kind tkind = input.getKind();
+                    if (tkind == Kind.Int) {
+                        new Sub(masm, src, 1, dst);
+                        new Andn(masm, dst, src, dst);
+                        new Srl(masm, dst, SPARC.g0, dst);
+                        new Popc(masm, dst, dst);
+                    } else if (tkind == Kind.Long) {
+                        new Sub(masm, src, 1, dst);
+                        new Andn(masm, dst, src, dst);
+                        new Popc(masm, dst, dst);
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("missing: " + tkind);
+                    }
+                    break;
+                case IBSR:
+                    // countLeadingZerosI_bsr masm.bsrq(dst, src);
+                    // masm.bsrl(dst, src);
+                    Kind ikind = input.getKind();
+                    assert ikind == Kind.Int;
+                    new Srl(masm, src, 1, tmp);
+                    new Srl(masm, src, 0, dst);
+                    new Or(masm, src, tmp, dst);
+                    new Srl(masm, dst, 2, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 4, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 8, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 16, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Popc(masm, dst, dst);
+                    new Mov(masm, ikind.getBitCount(), tmp);
+                    new Sub(masm, tmp, dst, dst);
+                    break;
+                case LBSR:
+                    // countLeadingZerosL_bsr masm.bsrq(dst, src);
+                    // masm.bsrq(dst, src);
+                    Kind lkind = input.getKind();
+                    assert lkind == Kind.Int;
+                    new Srlx(masm, src, 1, tmp);
+                    new Or(masm, src, tmp, dst);
+                    new Srlx(masm, dst, 2, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srlx(masm, dst, 4, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srlx(masm, dst, 8, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srlx(masm, dst, 16, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srlx(masm, dst, 32, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Popc(masm, dst, dst);
+                    new Mov(masm, lkind.getBitCount(), tmp);
+                    new Sub(masm, tmp, dst, dst);
+                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
 
@@ -87,20 +150,41 @@
             SPARCAddress src = (SPARCAddress) tasm.asAddress(input);
             switch (opcode) {
                 case IPOPCNT:
-                    // masm.popcntl(dst, src);
+                    new Ldsw(masm, src, tmp);
+                    // clear upper word for 64 bit POPC
+                    new Srl(masm, tmp, SPARC.g0, dst);
+                    new Popc(masm, tmp, dst);
                     break;
                 case LPOPCNT:
-                    // masm.popcntq(dst, src);
+                    new Ldx(masm, src, tmp);
+                    new Popc(masm, tmp, dst);
                     break;
                 case BSF:
-                    // masm.bsfq(dst, src);
+                    assert input.getKind() == Kind.Int;
+                    new Ldsw(masm, src, tmp);
+                    new Srl(masm, tmp, 1, tmp);
+                    new Srl(masm, tmp, 0, dst);
+                    new Or(masm, tmp, tmp, dst);
+                    new Srl(masm, dst, 2, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 4, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 8, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 16, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Popc(masm, dst, dst);
+                    new Mov(masm, Kind.Int.getBitCount(), tmp);
+                    new Sub(masm, tmp, dst, dst);
                     break;
                 case IBSR:
                     // masm.bsrl(dst, src);
-                    break;
+                    // countLeadingZerosI_bsr masm.bsrq(dst, src);
+                    // masm.bsrl(dst, src);
                 case LBSR:
                     // masm.bsrq(dst, src);
-                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
             }
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Mon Jun 10 08:44:25 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "*")
-public final class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
+public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
 
     public IntegerMulNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Mon Jun 10 08:44:25 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "-")
-public final class IntegerSubNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
+public class IntegerSubNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
 
     public IntegerSubNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Mon Jun 10 08:44:25 2013 +0200
@@ -105,10 +105,15 @@
     @Override
     public void setDeoptimizationState(FrameState f) {
         updateUsages(deoptState, f);
-        if (deoptState != null) {
-            throw new IllegalStateException(toString(Verbosity.Debugger));
+        assert deoptState == null && canDeoptimize() : "shouldn't assign deoptState to " + this;
+        deoptState = f;
+    }
+
+    @Override
+    public void setStateAfter(FrameState x) {
+        if (hasSideEffect() || canDeoptimize()) {
+            super.setStateAfter(x);
         }
-        deoptState = f;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Jun 10 08:44:25 2013 +0200
@@ -79,13 +79,6 @@
             if (fieldIndex != -1) {
                 tool.replaceWith(state.getEntry(fieldIndex));
             }
-        } else {
-            ValueNode cachedValue = tool.getReadCache(object(), field());
-            if (cachedValue != null) {
-                tool.replaceWithValue(cachedValue);
-            } else {
-                tool.addReadCache(object(), field(), this);
-            }
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Mon Jun 10 08:44:25 2013 +0200
@@ -77,12 +77,6 @@
                 tool.setVirtualEntry(state, fieldIndex, value());
                 tool.delete();
             }
-        } else {
-            if (value() == tool.getReadCache(object(), field())) {
-                tool.delete();
-            }
-            tool.killReadCache(field());
-            tool.addReadCache(object(), field(), value());
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java	Mon Jun 10 08:44:25 2013 +0200
@@ -43,8 +43,6 @@
 
         public abstract VirtualObjectNode getVirtualObject();
 
-        public abstract void setEntry(int index, ValueNode value);
-
         public abstract ValueNode getEntry(int index);
 
         public abstract void addLock(int depth);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Mon Jun 10 08:44:25 2013 +0200
@@ -153,10 +153,4 @@
      */
     void replaceWith(ValueNode value);
 
-    void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value);
-
-    ValueNode getReadCache(ValueNode object, ResolvedJavaField identity);
-
-    void killReadCache(ResolvedJavaField identity);
-
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Jun 10 08:44:25 2013 +0200
@@ -37,6 +37,11 @@
         this.fields = type.getInstanceFields(true);
     }
 
+    public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
+        this.type = type;
+        this.fields = fields;
+    }
+
     @Override
     public ResolvedJavaType type() {
         return type;
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Mon Jun 10 08:44:25 2013 +0200
@@ -159,7 +159,7 @@
                 String help = option.help;
                 String location = pkg + "." + option.declaringClass + "." + option.field.getSimpleName();
                 String comma = i == info.options.size() - 1 ? "" : ",";
-                out.printf("            new %s(\"%s\", %s.class, \"%s\", \"%s\", %s)%s%n", OptionDescriptor.class.getSimpleName(), name, type, help, location, optionValue, comma);
+                out.printf("            new %s(\"%s\", %s.class, \"%s\", \"%s\", %s)%s\n", OptionDescriptor.class.getSimpleName(), name, type, help, location, optionValue, comma);
                 i++;
             }
             out.println("        );");
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Jun 10 08:44:25 2013 +0200
@@ -257,8 +257,6 @@
     @Option(help = "")
     public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true);
     @Option(help = "")
-    public static final OptionValue<Boolean> OptEarlyReadElimination = new OptionValue<>(true);
-    @Option(help = "")
     public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true);
     @Option(help = "")
     public static final OptionValue<Boolean> OptCanonicalizeReads = new OptionValue<>(true);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Mon Jun 10 08:44:25 2013 +0200
@@ -63,7 +63,7 @@
     }
 
     /**
-     * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}.
+     * Tests monitor operations on {@link PartialEscapePhase virtual objects}.
      */
     @Test
     public void test3() {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Jun 10 08:44:25 2013 +0200
@@ -22,17 +22,20 @@
  */
 package com.oracle.graal.replacements.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
 
-public class MacroNode extends AbstractStateSplit implements Lowerable {
+public class MacroNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint {
 
     @Input protected final NodeInputList<ValueNode> arguments;
 
@@ -106,4 +109,9 @@
             }
         }
     }
+
+    @Override
+    public LocationIdentity[] getLocationIdentities() {
+        return new LocationIdentity[]{ANY_LOCATION};
+    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Mon Jun 10 08:44:03 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/*
- * Copyright (c) 2011, 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.virtual.phases.ea;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
-import com.oracle.graal.nodes.virtual.*;
-
-public class BlockState {
-
-    protected final IdentityHashMap<VirtualObjectNode, ObjectState> objectStates = new IdentityHashMap<>();
-    protected final IdentityHashMap<ValueNode, VirtualObjectNode> objectAliases;
-    protected final IdentityHashMap<ValueNode, ValueNode> scalarAliases;
-    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 BlockState() {
-        objectAliases = new IdentityHashMap<>();
-        scalarAliases = new IdentityHashMap<>();
-        readCache = new HashMap<>();
-    }
-
-    public BlockState(BlockState other) {
-        for (Map.Entry<VirtualObjectNode, ObjectState> entry : other.objectStates.entrySet()) {
-            objectStates.put(entry.getKey(), entry.getValue().cloneState());
-        }
-        objectAliases = new IdentityHashMap<>(other.objectAliases);
-        scalarAliases = new IdentityHashMap<>(other.scalarAliases);
-        readCache = new HashMap<>(other.readCache);
-    }
-
-    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 {
-            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 ObjectState getObjectState(VirtualObjectNode object) {
-        assert objectStates.containsKey(object);
-        return objectStates.get(object);
-    }
-
-    public ObjectState getObjectStateOptional(VirtualObjectNode object) {
-        return objectStates.get(object);
-    }
-
-    public ObjectState getObjectState(ValueNode value) {
-        VirtualObjectNode object = objectAliases.get(value);
-        return object == null ? null : getObjectState(object);
-    }
-
-    public BlockState cloneState() {
-        return new BlockState(this);
-    }
-
-    public BlockState cloneEmptyState() {
-        return new BlockState();
-    }
-
-    public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, GraphEffectList materializeEffects) {
-        PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment();
-        List<AllocatedObjectNode> objects = new ArrayList<>(2);
-        List<ValueNode> values = new ArrayList<>(8);
-        List<int[]> locks = new ArrayList<>(2);
-        List<ValueNode> otherAllocations = new ArrayList<>(2);
-        materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state);
-
-        materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations);
-    }
-
-    private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List<AllocatedObjectNode> objects, List<int[]> locks, List<ValueNode> values, List<ValueNode> otherAllocations,
-                    EscapeState state) {
-        VirtualUtil.trace("materializing %s", virtual);
-        ObjectState obj = getObjectState(virtual);
-
-        ValueNode[] entries = obj.getEntries();
-        ValueNode representation = virtual.getMaterializedRepresentation(fixed, entries, obj.getLocks());
-        obj.escape(representation, state);
-        if (representation instanceof AllocatedObjectNode) {
-            objects.add((AllocatedObjectNode) representation);
-            locks.add(obj.getLocks());
-            int pos = values.size();
-            while (values.size() < pos + entries.length) {
-                values.add(null);
-            }
-            for (int i = 0; i < entries.length; i++) {
-                ObjectState entryObj = getObjectState(entries[i]);
-                if (entryObj != null) {
-                    if (entryObj.isVirtual()) {
-                        materializeWithCommit(fixed, entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state);
-                    }
-                    values.set(pos + i, entryObj.getMaterializedValue());
-                } else {
-                    values.set(pos + i, entries[i]);
-                }
-            }
-            if (virtual instanceof VirtualInstanceNode) {
-                VirtualInstanceNode instance = (VirtualInstanceNode) virtual;
-                for (int i = 0; i < entries.length; i++) {
-                    readCache.put(new ReadCacheEntry(instance.field(i), representation), values.get(pos + i));
-                }
-            }
-        } else {
-            otherAllocations.add(representation);
-            assert obj.getLocks().length == 0;
-        }
-    }
-
-    void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) {
-        objectAliases.put(node, virtual);
-        if (node.isAlive()) {
-            for (Node usage : node.usages()) {
-                markVirtualUsages(usage, usages);
-            }
-        }
-    }
-
-    private void markVirtualUsages(Node node, NodeBitMap usages) {
-        if (!usages.isNew(node)) {
-            usages.mark(node);
-        }
-        if (node instanceof VirtualState) {
-            for (Node usage : node.usages()) {
-                markVirtualUsages(usage, usages);
-            }
-        }
-    }
-
-    public void addObject(VirtualObjectNode virtual, ObjectState state) {
-        objectStates.put(virtual, state);
-    }
-
-    public void addScalarAlias(ValueNode alias, ValueNode value) {
-        scalarAliases.put(alias, value);
-    }
-
-    public ValueNode getScalarAlias(ValueNode alias) {
-        ValueNode result = scalarAliases.get(alias);
-        return result == null ? alias : result;
-    }
-
-    public Iterable<ObjectState> getStates() {
-        return objectStates.values();
-    }
-
-    public Collection<VirtualObjectNode> getVirtualObjects() {
-        return objectAliases.values();
-    }
-
-    @Override
-    public String toString() {
-        return objectStates + " " + readCache;
-    }
-
-    public void meetAliases(List<? extends BlockState> states) {
-        objectAliases.putAll(states.get(0).objectAliases);
-        scalarAliases.putAll(states.get(0).scalarAliases);
-        for (int i = 1; i < states.size(); i++) {
-            BlockState state = states.get(i);
-            meetMaps(objectAliases, state.objectAliases);
-            meetMaps(scalarAliases, state.scalarAliases);
-        }
-    }
-
-    public Map<ReadCacheEntry, ValueNode> getReadCache() {
-        return readCache;
-    }
-
-    public boolean equivalentTo(BlockState other) {
-        if (this == other) {
-            return true;
-        }
-        boolean objectAliasesEqual = compareMaps(objectAliases, other.objectAliases);
-        boolean objectStatesEqual = compareMaps(objectStates, other.objectStates);
-        boolean readCacheEqual = compareMapsNoSize(readCache, other.readCache);
-        boolean scalarAliasesEqual = scalarAliases.equals(other.scalarAliases);
-        return objectAliasesEqual && objectStatesEqual && readCacheEqual && scalarAliasesEqual;
-    }
-
-    protected static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
-        if (left.size() != right.size()) {
-            return false;
-        }
-        return compareMapsNoSize(left, right);
-    }
-
-    protected static <K, V> boolean compareMapsNoSize(Map<K, V> left, Map<K, V> right) {
-        if (left == right) {
-            return true;
-        }
-        for (Map.Entry<K, V> entry : right.entrySet()) {
-            K key = entry.getKey();
-            V value = entry.getValue();
-            assert value != null;
-            V otherValue = left.get(key);
-            if (otherValue != value && !value.equals(otherValue)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    protected static <U, V> void meetMaps(Map<U, V> target, Map<U, V> source) {
-        Iterator<Map.Entry<U, V>> iter = target.entrySet().iterator();
-        while (iter.hasNext()) {
-            Map.Entry<U, V> entry = iter.next();
-            if (source.containsKey(entry.getKey())) {
-                assert source.get(entry.getKey()) == entry.getValue();
-            } else {
-                iter.remove();
-            }
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsBlockState.java	Mon Jun 10 08:44:25 2013 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2011, 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.virtual.phases.ea;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+
+public abstract class EffectsBlockState<T extends EffectsBlockState<T>> {
+
+    protected final IdentityHashMap<ValueNode, ValueNode> scalarAliases;
+
+    protected EffectsBlockState() {
+        scalarAliases = new IdentityHashMap<>();
+    }
+
+    protected EffectsBlockState(EffectsBlockState<T> other) {
+        scalarAliases = new IdentityHashMap<>(other.scalarAliases);
+    }
+
+    public void addScalarAlias(ValueNode alias, ValueNode value) {
+        scalarAliases.put(alias, value);
+    }
+
+    public ValueNode getScalarAlias(ValueNode alias) {
+        ValueNode result = scalarAliases.get(alias);
+        return result == null ? alias : result;
+    }
+
+    @Override
+    public String toString() {
+        return "Scalar Aliases: " + scalarAliases.toString();
+    }
+
+    public void meetAliases(List<T> states) {
+        scalarAliases.putAll(states.get(0).scalarAliases);
+        for (int i = 1; i < states.size(); i++) {
+            EffectsBlockState<T> state = states.get(i);
+            meetMaps(scalarAliases, state.scalarAliases);
+        }
+    }
+
+    public boolean equivalentTo(T other) {
+        if (this == other) {
+            return true;
+        }
+        return scalarAliases.equals(other.scalarAliases);
+    }
+
+    protected static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
+        if (left.size() != right.size()) {
+            return false;
+        }
+        return compareMapsNoSize(left, right);
+    }
+
+    protected static <K, V> boolean compareMapsNoSize(Map<K, V> left, Map<K, V> right) {
+        if (left == right) {
+            return true;
+        }
+        for (Map.Entry<K, V> entry : right.entrySet()) {
+            K key = entry.getKey();
+            V value = entry.getValue();
+            assert value != null;
+            V otherValue = left.get(key);
+            if (otherValue != value && !value.equals(otherValue)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    protected static <U, V> void meetMaps(Map<U, V> target, Map<U, V> source) {
+        Iterator<Map.Entry<U, V>> iter = target.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<U, V> entry = iter.next();
+            if (source.containsKey(entry.getKey())) {
+                assert source.get(entry.getKey()) == entry.getValue();
+            } else {
+                iter.remove();
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Mon Jun 10 08:44:25 2013 +0200
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2011, 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.virtual.phases.ea;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
+import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
+
+public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
+
+    private final SchedulePhase schedule;
+
+    protected final BlockMap<GraphEffectList> blockEffects;
+    private final IdentityHashMap<Loop, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
+
+    private boolean changed;
+
+    public EffectsClosure(SchedulePhase schedule) {
+        this.schedule = schedule;
+        this.blockEffects = new BlockMap<>(schedule.getCFG());
+        for (Block block : schedule.getCFG().getBlocks()) {
+            blockEffects.put(block, new GraphEffectList());
+        }
+    }
+
+    @Override
+    public boolean hasChanged() {
+        return changed;
+    }
+
+    @Override
+    public void applyEffects() {
+        final StructuredGraph graph = schedule.getCFG().graph;
+        final ArrayList<Node> obsoleteNodes = new ArrayList<>(0);
+        BlockIteratorClosure<Void> closure = new BlockIteratorClosure<Void>() {
+
+            @Override
+            protected Void getInitialState() {
+                return null;
+            }
+
+            private void apply(GraphEffectList effects, Object context) {
+                if (!effects.isEmpty()) {
+                    Debug.log(" ==== effects for %s", context);
+                    for (Effect effect : effects) {
+                        effect.apply(graph, obsoleteNodes);
+                        if (effect.isVisible()) {
+                            Debug.log("    %s", effect);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            protected Void processBlock(Block block, Void currentState) {
+                apply(blockEffects.get(block), block);
+                Debug.dump(graph, "after processing block %s", block);
+                return currentState;
+            }
+
+            @Override
+            protected Void merge(Block merge, List<Void> states) {
+                return null;
+            }
+
+            @Override
+            protected Void cloneState(Void oldState) {
+                return oldState;
+            }
+
+            @Override
+            protected List<Void> processLoop(Loop loop, Void initialState) {
+                LoopInfo<Void> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
+                apply(loopMergeEffects.get(loop), loop);
+                return info.exitStates;
+            }
+        };
+        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
+        assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
+    }
+
+    @Override
+    protected BlockT processBlock(Block block, BlockT state) {
+        VirtualUtil.trace("\nBlock: %s (", block);
+
+        GraphEffectList effects = blockEffects.get(block);
+        FixedWithNextNode lastFixedNode = null;
+        for (Node node : schedule.getBlockToNodesMap().get(block)) {
+            changed |= processNode(node, state, effects, lastFixedNode);
+            if (node instanceof FixedWithNextNode) {
+                lastFixedNode = (FixedWithNextNode) node;
+            }
+        }
+        VirtualUtil.trace(")\n    end state: %s\n", state);
+        return state;
+    }
+
+    protected abstract boolean processNode(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode);
+
+    @Override
+    protected BlockT merge(Block merge, List<BlockT> states) {
+        assert blockEffects.get(merge).isEmpty();
+        MergeProcessor processor = createMergeProcessor(merge);
+        processor.merge(states);
+        blockEffects.get(merge).addAll(processor.mergeEffects);
+        blockEffects.get(merge).addAll(processor.afterMergeEffects);
+        return processor.newState;
+    }
+
+    @Override
+    protected final List<BlockT> processLoop(Loop loop, BlockT initialState) {
+        BlockT loopEntryState = initialState;
+        BlockT lastMergedState = initialState;
+        MergeProcessor mergeProcessor = createMergeProcessor(loop.header);
+        for (int iteration = 0; iteration < 10; iteration++) {
+            LoopInfo<BlockT> info = ReentrantBlockIterator.processLoop(this, loop, cloneState(lastMergedState));
+
+            List<BlockT> states = new ArrayList<>();
+            states.add(initialState);
+            states.addAll(info.endStates);
+            mergeProcessor.merge(states);
+
+            Debug.log("================== %s", loop.header);
+            Debug.log("%s", mergeProcessor.newState);
+            Debug.log("===== vs.");
+            Debug.log("%s", lastMergedState);
+
+            if (mergeProcessor.newState.equivalentTo(lastMergedState)) {
+                blockEffects.get(loop.header).insertAll(mergeProcessor.mergeEffects, 0);
+                loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects);
+
+                assert info.exitStates.size() == loop.exits.size();
+                for (int i = 0; i < loop.exits.size(); i++) {
+                    BlockT exitState = info.exitStates.get(i);
+                    assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header;
+                    processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), loopEntryState, exitState, blockEffects.get(loop.exits.get(i)));
+                }
+
+                return info.exitStates;
+            } else {
+                lastMergedState = mergeProcessor.newState;
+                for (Block block : loop.blocks) {
+                    blockEffects.get(block).clear();
+                }
+            }
+        }
+        throw new GraalInternalError("too many iterations at %s", loop);
+    }
+
+    protected abstract void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects);
+
+    protected abstract MergeProcessor createMergeProcessor(Block merge);
+
+    protected class MergeProcessor {
+
+        protected final Block mergeBlock;
+        protected final MergeNode merge;
+
+        protected final GraphEffectList mergeEffects;
+        protected final GraphEffectList afterMergeEffects;
+        protected BlockT newState;
+
+        public MergeProcessor(Block mergeBlock) {
+            this.mergeBlock = mergeBlock;
+            this.merge = (MergeNode) mergeBlock.getBeginNode();
+            this.mergeEffects = new GraphEffectList();
+            this.afterMergeEffects = new GraphEffectList();
+        }
+
+        protected void merge(List<BlockT> states) {
+            newState = getInitialState();
+            newState.meetAliases(states);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Mon Jun 10 08:44:25 2013 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011, 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.virtual.phases.ea;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
+
+public abstract class EffectsPhase<PhaseContextT extends PhaseContext> extends BasePhase<PhaseContextT> {
+
+    public abstract static class Closure<T> extends ReentrantBlockIterator.BlockIteratorClosure<T> {
+
+        public abstract boolean hasChanged();
+
+        public abstract void applyEffects();
+    }
+
+    private final int maxIterations;
+    private CanonicalizerPhase canonicalizer;
+
+    public EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) {
+        this.maxIterations = maxIterations;
+        this.canonicalizer = canonicalizer;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph, PhaseContextT context) {
+        runAnalysis(graph, context);
+    }
+
+    public boolean runAnalysis(final StructuredGraph graph, final PhaseContextT context) {
+        boolean changed = false;
+        for (int iteration = 0; iteration < maxIterations; iteration++) {
+            boolean currentChanged = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
+
+                @Override
+                public Boolean call() {
+                    SchedulePhase schedule = new SchedulePhase();
+                    schedule.apply(graph, false);
+                    Closure<?> closure = createEffectsClosure(context, schedule);
+                    ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
+
+                    if (!closure.hasChanged()) {
+                        return false;
+                    }
+
+                    // apply the effects collected during this iteration
+                    closure.applyEffects();
+
+                    Debug.dump(graph, "after " + getName() + " iteration");
+
+                    new DeadCodeEliminationPhase().apply(graph);
+
+                    if (OptCanonicalizer.getValue()) {
+                        canonicalizer.apply(graph, context);
+                    }
+
+                    return true;
+                }
+            });
+            if (!currentChanged) {
+                break;
+            }
+            changed |= currentChanged;
+        }
+        return changed;
+    }
+
+    protected abstract Closure<?> createEffectsClosure(PhaseContextT context, SchedulePhase schedule);
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Mon Jun 10 08:44:25 2013 +0200
@@ -41,15 +41,13 @@
     private final Replacements replacements;
     private final GraphCache cache;
     private final OptimisticOptimizations optimisticOpts;
-    private final boolean readElimination;
     private final CanonicalizerPhase canonicalizer;
 
-    public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination, CanonicalizerPhase canonicalizer) {
+    public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, CanonicalizerPhase canonicalizer) {
         this.replacements = replacements;
         this.cache = cache;
         this.plan = plan;
         this.optimisticOpts = optimisticOpts;
-        this.readElimination = readElimination;
         this.canonicalizer = canonicalizer;
     }
 
@@ -73,11 +71,11 @@
                 @Override
                 public Boolean call() {
                     boolean progress = false;
-                    PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination, canonicalizer);
+                    PartialEscapePhase ea = new PartialEscapePhase(false, canonicalizer);
                     boolean eaResult = ea.runAnalysis(graph, context);
                     progress |= eaResult;
 
-                    Map<Invoke, Double> hints = PEAInliningHints.getValue() ? PartialEscapeAnalysisPhase.getHints(graph) : null;
+                    Map<Invoke, Double> hints = PEAInliningHints.getValue() ? PartialEscapePhase.getHints(graph) : null;
 
                     InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, replacements, context.getAssumptions(), cache, plan, optimisticOpts);
                     inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java	Mon Jun 10 08:44:25 2013 +0200
@@ -34,7 +34,7 @@
  * the fields or array elements (called "entries") and the lock count if the object is still
  * virtual. If the object was materialized, it contains the current materialized value.
  */
-class ObjectState extends Virtualizable.State {
+public class ObjectState extends Virtualizable.State {
 
     private static final int[] EMPTY_INT_ARRAY = new int[0];
 
@@ -131,7 +131,6 @@
         return entries[index];
     }
 
-    @Override
     public void setEntry(int index, ValueNode value) {
         assert isVirtual();
         entries[index] = value;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Mon Jun 10 08:44:03 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2011, 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.virtual.phases.ea;
-
-import static com.oracle.graal.phases.GraalOptions.*;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.graph.*;
-import com.oracle.graal.phases.schedule.*;
-import com.oracle.graal.phases.tiers.*;
-
-public class PartialEscapeAnalysisPhase extends BasePhase<PhaseContext> {
-
-    public abstract static class Closure<T> extends ReentrantBlockIterator.BlockIteratorClosure<T> {
-
-        public abstract boolean hasChanged();
-
-        public abstract void applyEffects();
-    }
-
-    private final boolean iterative;
-    private final boolean readElimination;
-    private final CanonicalizerPhase canonicalizer;
-
-    public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination, CanonicalizerPhase canonicalizer) {
-        this.iterative = iterative;
-        this.readElimination = readElimination;
-        this.canonicalizer = canonicalizer;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph, PhaseContext context) {
-        runAnalysis(graph, context);
-    }
-
-    public boolean runAnalysis(final StructuredGraph graph, final PhaseContext context) {
-        if (!VirtualUtil.matches(graph, EscapeAnalyzeOnly.getValue())) {
-            return false;
-        }
-
-        if (!readElimination) {
-            boolean analyzableNodes = false;
-            for (Node node : graph.getNodes()) {
-                if (node instanceof VirtualizableAllocation) {
-                    analyzableNodes = true;
-                    break;
-                }
-            }
-            if (!analyzableNodes) {
-                return false;
-            }
-        }
-
-        boolean continueIteration = true;
-        boolean changed = false;
-        for (int iteration = 0; iteration < EscapeAnalysisIterations.getValue() && continueIteration; iteration++) {
-            boolean currentChanged = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
-
-                @Override
-                public Boolean call() {
-
-                    SchedulePhase schedule = new SchedulePhase();
-                    schedule.apply(graph, false);
-                    Closure<?> closure = createAnalysisClosure(context, schedule);
-                    ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
-
-                    if (!closure.hasChanged()) {
-                        return false;
-                    }
-
-                    // apply the effects collected during the escape analysis iteration
-                    closure.applyEffects();
-
-                    Debug.dump(graph, "after PartialEscapeAnalysis iteration");
-
-                    new DeadCodeEliminationPhase().apply(graph);
-
-                    if (OptCanonicalizer.getValue()) {
-                        canonicalizer.apply(graph, context);
-                    }
-
-                    return true;
-                }
-            });
-            continueIteration = currentChanged && iterative;
-            changed |= currentChanged;
-        }
-
-        return changed;
-    }
-
-    protected Closure<?> createAnalysisClosure(PhaseContext context, SchedulePhase schedule) {
-        return new PartialEscapeClosure<>(schedule, context.getRuntime(), context.getAssumptions());
-    }
-
-    public static Map<Invoke, Double> getHints(StructuredGraph graph) {
-        NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply();
-        Map<Invoke, Double> hints = null;
-        for (CommitAllocationNode commit : graph.getNodes(CommitAllocationNode.class)) {
-            double sum = 0;
-            double invokeSum = 0;
-            for (Node commitUsage : commit.usages()) {
-                for (Node usage : commitUsage.usages()) {
-                    if (usage instanceof FixedNode) {
-                        sum += probabilities.get((FixedNode) usage);
-                    } else {
-                        if (usage instanceof MethodCallTargetNode) {
-                            invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode());
-                        }
-                        for (Node secondLevelUage : usage.usages()) {
-                            if (secondLevelUage instanceof FixedNode) {
-                                sum += probabilities.get(((FixedNode) secondLevelUage));
-                            }
-                        }
-                    }
-                }
-            }
-            // TODO(lstadler) get rid of this magic number
-            if (sum > 100 && invokeSum > 0) {
-                for (Node commitUsage : commit.usages()) {
-                    for (Node usage : commitUsage.usages()) {
-                        if (usage instanceof MethodCallTargetNode) {
-                            if (hints == null) {
-                                hints = new HashMap<>();
-                            }
-                            Invoke invoke = ((MethodCallTargetNode) usage).invoke();
-                            hints.put(invoke, sum / invokeSum);
-                        }
-                    }
-                }
-            }
-        }
-        return hints;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Mon Jun 10 08:44:25 2013 +0200
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2011, 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.virtual.phases.ea;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
+import com.oracle.graal.nodes.virtual.*;
+
+public abstract class PartialEscapeBlockState<T extends PartialEscapeBlockState<T>> extends EffectsBlockState<T> {
+
+    protected final IdentityHashMap<VirtualObjectNode, ObjectState> objectStates = new IdentityHashMap<>();
+    protected final IdentityHashMap<ValueNode, VirtualObjectNode> objectAliases;
+
+    /**
+     * Final subclass of PartialEscapeBlockState, for performance and to make everything behave
+     * nicely with generics.
+     */
+    public static final class Final extends PartialEscapeBlockState<Final> {
+
+        public Final() {
+        }
+
+        public Final(Final other) {
+            super(other);
+        }
+    }
+
+    protected PartialEscapeBlockState() {
+        objectAliases = new IdentityHashMap<>();
+    }
+
+    protected PartialEscapeBlockState(PartialEscapeBlockState<T> other) {
+        super(other);
+        for (Map.Entry<VirtualObjectNode, ObjectState> entry : other.objectStates.entrySet()) {
+            objectStates.put(entry.getKey(), entry.getValue().cloneState());
+        }
+        objectAliases = new IdentityHashMap<>(other.objectAliases);
+    }
+
+    public ObjectState getObjectState(VirtualObjectNode object) {
+        assert objectStates.containsKey(object);
+        return objectStates.get(object);
+    }
+
+    public ObjectState getObjectStateOptional(VirtualObjectNode object) {
+        return objectStates.get(object);
+    }
+
+    public ObjectState getObjectState(ValueNode value) {
+        VirtualObjectNode object = objectAliases.get(value);
+        return object == null ? null : getObjectState(object);
+    }
+
+    public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, GraphEffectList materializeEffects) {
+        PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment();
+        List<AllocatedObjectNode> objects = new ArrayList<>(2);
+        List<ValueNode> values = new ArrayList<>(8);
+        List<int[]> locks = new ArrayList<>(2);
+        List<ValueNode> otherAllocations = new ArrayList<>(2);
+        materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state);
+
+        materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations);
+    }
+
+    private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List<AllocatedObjectNode> objects, List<int[]> locks, List<ValueNode> values, List<ValueNode> otherAllocations,
+                    EscapeState state) {
+        ObjectState obj = getObjectState(virtual);
+
+        ValueNode[] entries = obj.getEntries();
+        ValueNode representation = virtual.getMaterializedRepresentation(fixed, entries, obj.getLocks());
+        obj.escape(representation, state);
+        if (representation instanceof AllocatedObjectNode) {
+            objects.add((AllocatedObjectNode) representation);
+            locks.add(obj.getLocks());
+            int pos = values.size();
+            while (values.size() < pos + entries.length) {
+                values.add(null);
+            }
+            for (int i = 0; i < entries.length; i++) {
+                ObjectState entryObj = getObjectState(entries[i]);
+                if (entryObj != null) {
+                    if (entryObj.isVirtual()) {
+                        materializeWithCommit(fixed, entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state);
+                    }
+                    values.set(pos + i, entryObj.getMaterializedValue());
+                } else {
+                    values.set(pos + i, entries[i]);
+                }
+            }
+            objectMaterialized(virtual, (AllocatedObjectNode) representation, values.subList(pos, pos + entries.length));
+        } else {
+            VirtualUtil.trace("materialized %s as %s", virtual, representation);
+            otherAllocations.add(representation);
+            assert obj.getLocks().length == 0;
+        }
+    }
+
+    protected void objectMaterialized(VirtualObjectNode virtual, AllocatedObjectNode representation, List<ValueNode> values) {
+        VirtualUtil.trace("materialized %s as %s with values %s", virtual, representation, values);
+    }
+
+    void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) {
+        objectAliases.put(node, virtual);
+        if (node.isAlive()) {
+            for (Node usage : node.usages()) {
+                markVirtualUsages(usage, usages);
+            }
+        }
+    }
+
+    private void markVirtualUsages(Node node, NodeBitMap usages) {
+        if (!usages.isNew(node)) {
+            usages.mark(node);
+        }
+        if (node instanceof VirtualState) {
+            for (Node usage : node.usages()) {
+                markVirtualUsages(usage, usages);
+            }
+        }
+    }
+
+    public void addObject(VirtualObjectNode virtual, ObjectState state) {
+        objectStates.put(virtual, state);
+    }
+
+    public Iterable<ObjectState> getStates() {
+        return objectStates.values();
+    }
+
+    public Collection<VirtualObjectNode> getVirtualObjects() {
+        return objectAliases.values();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + ", Object Aliases: " + objectAliases + ", Object States: " + objectStates;
+    }
+
+    @Override
+    public void meetAliases(List<T> states) {
+        super.meetAliases(states);
+        objectAliases.putAll(states.get(0).objectAliases);
+        for (int i = 1; i < states.size(); i++) {
+            meetMaps(objectAliases, states.get(i).objectAliases);
+        }
+    }
+
+    @Override
+    public boolean equivalentTo(T other) {
+        if (!compareMaps(objectAliases, other.objectAliases) || !compareMaps(objectStates, other.objectStates)) {
+            return false;
+        }
+        return super.equivalentTo(other);
+    }
+
+    protected static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
+        if (left.size() != right.size()) {
+            return false;
+        }
+        return compareMapsNoSize(left, right);
+    }
+
+    protected static <K, V> boolean compareMapsNoSize(Map<K, V> left, Map<K, V> right) {
+        if (left == right) {
+            return true;
+        }
+        for (Map.Entry<K, V> entry : right.entrySet()) {
+            K key = entry.getKey();
+            V value = entry.getValue();
+            assert value != null;
+            V otherValue = left.get(key);
+            if (otherValue != value && !value.equals(otherValue)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    protected static <U, V> void meetMaps(Map<U, V> target, Map<U, V> source) {
+        Iterator<Map.Entry<U, V>> iter = target.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<U, V> entry = iter.next();
+            if (source.containsKey(entry.getKey())) {
+                assert source.get(entry.getKey()) == entry.getValue();
+            } else {
+                iter.remove();
+            }
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Jun 10 08:44:25 2013 +0200
@@ -22,9 +22,6 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.api.meta.LocationIdentity.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -35,20 +32,14 @@
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.graph.*;
-import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
-import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.nodes.*;
-import com.oracle.graal.virtual.phases.ea.BlockState.ReadCacheEntry;
-import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
 
-public class PartialEscapeClosure<BlockT extends BlockState> extends PartialEscapeAnalysisPhase.Closure<BlockT> {
+public abstract class PartialEscapeClosure<BlockT extends PartialEscapeBlockState<BlockT>> extends EffectsClosure<BlockT> {
 
     public static final DebugMetric METRIC_MATERIALIZATIONS = Debug.metric("Materializations");
     public static final DebugMetric METRIC_MATERIALIZATIONS_PHI = Debug.metric("MaterializationsPhi");
@@ -61,143 +52,63 @@
     public static final DebugMetric METRIC_MEMORYCHECKOINT = Debug.metric("MemoryCheckpoint");
 
     private final NodeBitMap usages;
-    private final SchedulePhase schedule;
-
-    private final BlockMap<GraphEffectList> blockEffects;
-    private final IdentityHashMap<Loop, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
-
     private final VirtualizerToolImpl tool;
-
     private final Map<Invoke, Double> hints = new IdentityHashMap<>();
 
-    private boolean changed;
+    /**
+     * Final subclass of PartialEscapeClosure, for performance and to make everything behave nicely
+     * with generics.
+     */
+    public static final class Final extends PartialEscapeClosure<PartialEscapeBlockState.Final> {
 
-    public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
-        this.usages = schedule.getCFG().graph.createNodeBitMap();
-        this.schedule = schedule;
-        this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions);
-        this.blockEffects = new BlockMap<>(schedule.getCFG());
-        for (Block block : schedule.getCFG().getBlocks()) {
-            blockEffects.put(block, new GraphEffectList());
+        public Final(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
+            super(schedule, metaAccess, assumptions);
+        }
+
+        @Override
+        protected PartialEscapeBlockState.Final getInitialState() {
+            return new PartialEscapeBlockState.Final();
+        }
+
+        @Override
+        protected PartialEscapeBlockState.Final cloneState(PartialEscapeBlockState.Final oldState) {
+            return new PartialEscapeBlockState.Final(oldState);
         }
     }
 
-    @SuppressWarnings("unchecked")
-    @Override
-    protected BlockT getInitialState() {
-        return (BlockT) new BlockState();
-    }
-
-    @Override
-    public boolean hasChanged() {
-        return changed;
-    }
-
-    @Override
-    public void applyEffects() {
-        final StructuredGraph graph = schedule.getCFG().graph;
-        final ArrayList<Node> obsoleteNodes = new ArrayList<>(0);
-        BlockIteratorClosure<Void> closure = new BlockIteratorClosure<Void>() {
-
-            @Override
-            protected Void getInitialState() {
-                return null;
-            }
-
-            private void apply(GraphEffectList effects, Object context) {
-                if (!effects.isEmpty()) {
-                    Debug.log(" ==== effects for %s", context);
-                    for (Effect effect : effects) {
-                        effect.apply(graph, obsoleteNodes);
-                        if (effect.isVisible()) {
-                            Debug.log("    %s", effect);
-                        }
-                    }
-                }
-            }
-
-            @Override
-            protected Void processBlock(Block block, Void currentState) {
-                apply(blockEffects.get(block), block);
-                return currentState;
-            }
-
-            @Override
-            protected Void merge(Block merge, List<Void> states) {
-                return null;
-            }
-
-            @Override
-            protected Void cloneState(Void oldState) {
-                return oldState;
-            }
-
-            @Override
-            protected List<Void> processLoop(Loop loop, Void initialState) {
-                LoopInfo<Void> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
-                apply(loopMergeEffects.get(loop), loop);
-                return info.exitStates;
-            }
-        };
-        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
-        assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
+    public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
+        super(schedule);
+        this.usages = schedule.getCFG().graph.createNodeBitMap();
+        this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions);
     }
 
     public Map<Invoke, Double> getHints() {
         return hints;
     }
 
+    /**
+     * @return true if the node was deleted, false otherwise
+     */
     @Override
-    protected BlockT processBlock(Block block, BlockT state) {
-        GraphEffectList effects = blockEffects.get(block);
-        tool.setEffects(effects);
-
-        VirtualUtil.trace("\nBlock: %s (", block);
-        List<ScheduledNode> nodeList = schedule.getBlockToNodesMap().get(block);
-
-        FixedWithNextNode lastFixedNode = null;
-        for (Node node : nodeList) {
-            boolean deleted;
-            boolean isMarked = usages.isMarked(node);
-            if (isMarked || node instanceof VirtualizableRoot) {
-                VirtualUtil.trace("[[%s]] ", node);
-                FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next();
-                deleted = processNode((ValueNode) node, nextFixedNode, state, effects, isMarked);
-            } else {
-                VirtualUtil.trace("%s ", node);
-                deleted = false;
-            }
-            if (OptEarlyReadElimination.getValue()) {
-                if (!deleted && node instanceof MemoryCheckpoint) {
-                    METRIC_MEMORYCHECKOINT.increment();
-                    MemoryCheckpoint checkpoint = (MemoryCheckpoint) node;
-                    for (LocationIdentity identity : checkpoint.getLocationIdentities()) {
-                        if (identity instanceof ResolvedJavaField) {
-                            state.killReadCache((ResolvedJavaField) identity);
-                        } else if (identity == ANY_LOCATION) {
-                            state.killReadCache();
-                        }
-                    }
-                }
-            }
-            if (node instanceof FixedWithNextNode) {
-                lastFixedNode = (FixedWithNextNode) node;
-            }
+    protected boolean processNode(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
+        boolean isMarked = usages.isMarked(node);
+        if (isMarked || node instanceof VirtualizableRoot) {
+            VirtualUtil.trace("[[%s]] ", node);
+            FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next();
+            return processNode((ValueNode) node, nextFixedNode, state, effects, isMarked);
+        } else {
+            VirtualUtil.trace("%s ", node);
+            return false;
         }
-        VirtualUtil.trace(")\n    end state: %s\n", state);
-        return state;
     }
 
     private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockT state, final GraphEffectList effects, boolean isMarked) {
-        tool.reset(state, node, insertBefore);
+        tool.reset(state, node, insertBefore, effects);
         if (node instanceof Virtualizable) {
             ((Virtualizable) node).virtualize(tool);
         }
         if (tool.isDeleted()) {
-            if (!(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode)) {
-                changed = true;
-            }
-            return true;
+            return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode);
         }
         if (isMarked) {
             if (node instanceof StateSplit) {
@@ -289,7 +200,7 @@
         return false;
     }
 
-    private static void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
+    private static void ensureMaterialized(PartialEscapeBlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
         assert obj != null;
         if (obj.getState() == EscapeState.Virtual) {
             metric.increment();
@@ -300,70 +211,13 @@
         assert !obj.isVirtual();
     }
 
-    private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) {
+    private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, PartialEscapeBlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) {
         ensureMaterialized(state, obj, materializeBefore, effects, metric);
         effects.replaceFirstInput(usage, value, obj.getMaterializedValue());
     }
 
     @Override
-    protected BlockT merge(Block merge, List<BlockT> states) {
-        assert blockEffects.get(merge).isEmpty();
-        MergeProcessor<BlockT> processor = new MergeProcessor<>(merge, usages, blockEffects);
-        processor.merge(states);
-        blockEffects.get(merge).addAll(processor.mergeEffects);
-        blockEffects.get(merge).addAll(processor.afterMergeEffects);
-        return processor.newState;
-
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected BlockT cloneState(BlockState oldState) {
-        return (BlockT) oldState.cloneState();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected List<BlockT> processLoop(Loop loop, BlockT initialState) {
-        BlockState loopEntryState = initialState;
-        BlockState lastMergedState = initialState;
-        MergeProcessor<BlockT> mergeProcessor = new MergeProcessor<>(loop.header, usages, blockEffects);
-        for (int iteration = 0; iteration < 10; iteration++) {
-            LoopInfo<BlockT> info = ReentrantBlockIterator.processLoop(this, loop, (BlockT) lastMergedState.cloneState());
-
-            List<BlockT> states = new ArrayList<>();
-            states.add(initialState);
-            states.addAll(info.endStates);
-            mergeProcessor.merge(states);
-
-            Debug.log("================== %s", loop.header);
-            Debug.log("%s", mergeProcessor.newState);
-            Debug.log("===== vs.");
-            Debug.log("%s", lastMergedState);
-
-            if (mergeProcessor.newState.equivalentTo(lastMergedState)) {
-                blockEffects.get(loop.header).insertAll(mergeProcessor.mergeEffects, 0);
-                loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects);
-
-                assert info.exitStates.size() == loop.exits.size();
-                for (int i = 0; i < loop.exits.size(); i++) {
-                    BlockState exitState = info.exitStates.get(i);
-                    assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header;
-                    processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), loopEntryState, exitState, blockEffects.get(loop.exits.get(i)));
-                }
-
-                return info.exitStates;
-            } else {
-                lastMergedState = mergeProcessor.newState;
-                for (Block block : loop.blocks) {
-                    blockEffects.get(block).clear();
-                }
-            }
-        }
-        throw new GraalInternalError("too many iterations at %s", loop);
-    }
-
-    private static void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState, GraphEffectList effects) {
+    protected void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects) {
         HashMap<VirtualObjectNode, ProxyNode> proxies = new HashMap<>();
 
         for (ProxyNode proxy : exitNode.proxies()) {
@@ -404,41 +258,25 @@
                 }
             }
         }
-
-        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);
-            }
-        }
     }
 
-    private static class MergeProcessor<BlockT extends BlockState> {
+    @Override
+    protected MergeProcessor createMergeProcessor(Block merge) {
+        return new MergeProcessor(merge);
+    }
 
-        private final Block mergeBlock;
-        private final MergeNode merge;
-        private final NodeBitMap usages;
-        private final BlockMap<GraphEffectList> blockEffects;
-        private final GraphEffectList mergeEffects;
-        private final GraphEffectList afterMergeEffects;
+    protected class MergeProcessor extends EffectsClosure<BlockT>.MergeProcessor {
 
         private final HashMap<Object, PhiNode> materializedPhis = new HashMap<>();
         private final IdentityHashMap<VirtualObjectNode, PhiNode[]> valuePhis = new IdentityHashMap<>();
         private final IdentityHashMap<PhiNode, PhiNode[]> valueObjectMergePhis = new IdentityHashMap<>();
         private final IdentityHashMap<PhiNode, VirtualObjectNode> valueObjectVirtuals = new IdentityHashMap<>();
-        private BlockT newState;
 
-        public MergeProcessor(Block mergeBlock, NodeBitMap usages, BlockMap<GraphEffectList> blockEffects) {
-            this.usages = usages;
-            this.mergeBlock = mergeBlock;
-            this.blockEffects = blockEffects;
-            this.merge = (MergeNode) mergeBlock.getBeginNode();
-            this.mergeEffects = new GraphEffectList();
-            this.afterMergeEffects = new GraphEffectList();
+        public MergeProcessor(Block mergeBlock) {
+            super(mergeBlock);
         }
 
-        private <T> PhiNode getCachedPhi(T virtual, Kind kind) {
+        protected <T> PhiNode getCachedPhi(T virtual, Kind kind) {
             PhiNode result = materializedPhis.get(virtual);
             if (result == null) {
                 result = new PhiNode(kind, merge);
@@ -474,10 +312,9 @@
             return result;
         }
 
-        @SuppressWarnings("unchecked")
-        private void merge(List<BlockT> states) {
-            newState = (BlockT) states.get(0).cloneEmptyState();
-            newState.meetAliases(states);
+        @Override
+        protected void merge(List<BlockT> states) {
+            super.merge(states);
 
             /*
              * Iterative processing: Merging the materialized/virtual state of virtual objects can
@@ -519,7 +356,7 @@
                             PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object);
                             mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi");
                             for (int i = 0; i < states.size(); i++) {
-                                BlockState state = states.get(i);
+                                PartialEscapeBlockState state = states.get(i);
                                 ObjectState obj = objStates[i];
                                 materialized |= obj.isVirtual();
                                 Block predecessor = mergeBlock.getPredecessors().get(i);
@@ -578,8 +415,6 @@
                     }
                 }
             } while (materialized);
-
-            mergeReadCache(states);
         }
 
         private boolean processPhi(PhiNode phi, List<BlockT> states) {
@@ -665,62 +500,5 @@
             }
             return materialized;
         }
-
-        private void mergeReadCache(List<BlockT> 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<BlockT> 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.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Mon Jun 10 08:44:25 2013 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2011, 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.virtual.phases.ea;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class PartialEscapePhase extends EffectsPhase<PhaseContext> {
+
+    public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer) {
+        super(iterative ? EscapeAnalysisIterations.getValue() : 1, canonicalizer);
+    }
+
+    @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) {
+                runAnalysis(graph, context);
+            }
+        }
+    }
+
+    @Override
+    protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule) {
+        return new PartialEscapeClosure.Final(schedule, context.getRuntime(), context.getAssumptions());
+    }
+
+    public static Map<Invoke, Double> getHints(StructuredGraph graph) {
+        NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply();
+        Map<Invoke, Double> hints = null;
+        for (CommitAllocationNode commit : graph.getNodes(CommitAllocationNode.class)) {
+            double sum = 0;
+            double invokeSum = 0;
+            for (Node commitUsage : commit.usages()) {
+                for (Node usage : commitUsage.usages()) {
+                    if (usage instanceof FixedNode) {
+                        sum += probabilities.get((FixedNode) usage);
+                    } else {
+                        if (usage instanceof MethodCallTargetNode) {
+                            invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode());
+                        }
+                        for (Node secondLevelUage : usage.usages()) {
+                            if (secondLevelUage instanceof FixedNode) {
+                                sum += probabilities.get(((FixedNode) secondLevelUage));
+                            }
+                        }
+                    }
+                }
+            }
+            // TODO(lstadler) get rid of this magic number
+            if (sum > 100 && invokeSum > 0) {
+                for (Node commitUsage : commit.usages()) {
+                    for (Node usage : commitUsage.usages()) {
+                        if (usage instanceof MethodCallTargetNode) {
+                            if (hints == null) {
+                                hints = new HashMap<>();
+                            }
+                            Invoke invoke = ((MethodCallTargetNode) usage).invoke();
+                            hints.put(invoke, sum / invokeSum);
+                        }
+                    }
+                }
+            }
+        }
+        return hints;
+    }
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Mon Jun 10 08:44:25 2013 +0200
@@ -111,7 +111,7 @@
         }
     }
 
-    static boolean matches(StructuredGraph graph, String filter) {
+    public static boolean matches(StructuredGraph graph, String filter) {
         if (filter != null) {
             if (filter.startsWith("~")) {
                 ResolvedJavaMethod method = graph.method();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Jun 10 08:44:25 2013 +0200
@@ -39,7 +39,6 @@
     private final NodeBitMap usages;
     private final MetaAccessProvider metaAccess;
     private final Assumptions assumptions;
-    private GraphEffectList effects;
 
     VirtualizerToolImpl(NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) {
         this.usages = usages;
@@ -48,9 +47,10 @@
     }
 
     private boolean deleted;
-    private BlockState state;
+    private PartialEscapeBlockState state;
     private ValueNode current;
     private FixedNode position;
+    private GraphEffectList effects;
 
     @Override
     public MetaAccessProvider getMetaAccessProvider() {
@@ -62,15 +62,12 @@
         return assumptions;
     }
 
-    public void setEffects(GraphEffectList effects) {
-        this.effects = effects;
-    }
-
-    public void reset(BlockState newState, ValueNode newCurrent, FixedNode newPosition) {
+    public void reset(PartialEscapeBlockState newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) {
         deleted = false;
         state = newState;
         current = newCurrent;
         position = newPosition;
+        effects = newEffects;
     }
 
     public boolean isDeleted() {
@@ -87,16 +84,24 @@
         ObjectState obj = (ObjectState) objectState;
         assert obj != null && obj.isVirtual() : "not virtual: " + obj;
         ObjectState valueState = state.getObjectState(value);
+        ValueNode newValue = value;
         if (valueState == null) {
-            obj.setEntry(index, getReplacedValue(value));
+            newValue = getReplacedValue(value);
+            assert obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind() || (isObjectEntry(obj.getEntry(index)) && isObjectEntry(newValue));
         } else {
-            ValueNode newValue = value;
             if (valueState.getState() != EscapeState.Virtual) {
                 newValue = valueState.getMaterializedValue();
+                assert newValue.kind() == Kind.Object;
+            } else {
+                newValue = valueState.getVirtualObject();
             }
-            assert obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind();
-            obj.setEntry(index, newValue);
+            assert obj.getEntry(index) == null || isObjectEntry(obj.getEntry(index));
         }
+        obj.setEntry(index, newValue);
+    }
+
+    private static boolean isObjectEntry(ValueNode value) {
+        return value.kind() == Kind.Object || value instanceof VirtualObjectNode;
     }
 
     @Override
@@ -128,7 +133,6 @@
 
     @Override
     public void delete() {
-        assert current instanceof FixedWithNextNode;
         effects.deleteFixedNode((FixedWithNextNode) current);
         deleted = true;
     }
@@ -181,26 +185,4 @@
             }
         }
     }
-
-    @Override
-    public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value) {
-        if (OptEarlyReadElimination.getValue()) {
-            state.addReadCache(object, identity, value);
-        }
-    }
-
-    @Override
-    public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity) {
-        if (OptEarlyReadElimination.getValue()) {
-            return state.getReadCache(object, identity);
-        }
-        return null;
-    }
-
-    @Override
-    public void killReadCache(ResolvedJavaField identity) {
-        if (OptEarlyReadElimination.getValue()) {
-            state.killReadCache(identity);
-        }
-    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Mon Jun 10 08:44:25 2013 +0200
@@ -170,4 +170,13 @@
      * @return the new materialized frame
      */
     MaterializedFrame materialize();
+
+    /**
+     * To check whether the given {@link FrameSlot} has been initialized or not. An initialized slot
+     * has previously been read or modified.
+     * 
+     * @param slot the slot
+     * @return true if the slot is uninitialized.
+     */
+    boolean isInitialized(FrameSlot slot);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Jun 10 08:44:25 2013 +0200
@@ -112,6 +112,13 @@
         return clonedFrameDescriptor;
     }
 
+    public FrameDescriptor shallowCopy() {
+        FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.typeConversion);
+        clonedFrameDescriptor.slots.addAll(slots);
+        clonedFrameDescriptor.identifierToSlotMap.putAll(identifierToSlotMap);
+        return clonedFrameDescriptor;
+    }
+
     void updateVersion() {
         version.invalidate();
         version = createVersion();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java	Mon Jun 10 08:44:25 2013 +0200
@@ -29,7 +29,7 @@
     private final int index;
     private FrameSlotKind kind;
 
-    protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) {
+    public FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) {
         this.descriptor = descriptor;
         this.identifier = identifier;
         this.index = index;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Mon Jun 10 08:44:25 2013 +0200
@@ -133,4 +133,9 @@
     public FrameDescriptor getFrameDescriptor() {
         throw new UnsupportedOperationException("native frame");
     }
+
+    @Override
+    public boolean isInitialized(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Mon Jun 10 08:44:25 2013 +0200
@@ -122,4 +122,9 @@
     public FrameDescriptor getFrameDescriptor() {
         return wrapped.getFrameDescriptor();
     }
+
+    @Override
+    public boolean isInitialized(FrameSlot slot) {
+        return wrapped.isInitialized(slot);
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Mon Jun 10 08:44:03 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Mon Jun 10 08:44:25 2013 +0200
@@ -201,4 +201,9 @@
             tags = Arrays.copyOf(tags, newSize);
         }
     }
+
+    @Override
+    public boolean isInitialized(FrameSlot slot) {
+        return (this.tags[slot.getIndex()] != FrameSlotKind.Illegal.ordinal());
+    }
 }
--- a/make/Makefile	Mon Jun 10 08:44:03 2013 +0200
+++ b/make/Makefile	Mon Jun 10 08:44:25 2013 +0200
@@ -516,6 +516,10 @@
 $(EXPORT_JRE_LIB_DIR)/%.jar: $(SHARED_DIR)/%.jar
 	$(install-file)
 
+# Shared options files
+$(EXPORT_JRE_LIB_DIR)/%.options: $(SHARED_DIR)/%.options
+	$(install-file)
+	
 # Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h)
 $(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/%
 	$(install-file)
--- a/make/build-graal.xml	Mon Jun 10 08:44:03 2013 +0200
+++ b/make/build-graal.xml	Mon Jun 10 08:44:25 2013 +0200
@@ -28,7 +28,7 @@
   <property name="classes.dir" value="${shared.dir}/graal"/>
   <property name="jar.dir" value="${shared.dir}"/>
   <property name="jar.file" value="${jar.dir}/graal.jar"/>
-  <target depends="jar" name="main"/>
+  <target depends="options,jar" name="main"/>
   <target depends="cleanclasses" name="compile">
     <mkdir dir="${classes.dir}"/>
     <javac debug="on" destdir="${classes.dir}" includeantruntime="false">
@@ -101,6 +101,14 @@
   <target name="cleanclasses">
     <delete dir="${classes.dir}"/>
   </target>
+  <target if="graal.options.exists" name="options">
+    <copy todir="${jar.dir}">
+      <filelist dir="${gamma.dir}" files="graal.options"/>
+    </copy>
+  </target>
+  <target name="check-graal-options-exists">
+    <available file="${gamma.dir}/graal.options" property="graal.options.exists"/>
+  </target>
   <target depends="cleanclasses" name="clean">
     <delete file="${jar.file}"/>
   </target>
--- a/make/solaris/makefiles/buildtree.make	Mon Jun 10 08:44:03 2013 +0200
+++ b/make/solaris/makefiles/buildtree.make	Mon Jun 10 08:44:25 2013 +0200
@@ -229,7 +229,9 @@
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
+	echo "$(call gamma-path,altsrc,gpu/ptx) \\"; \
+	echo "$(call gamma-path,commonsrc,gpu/ptx)"; \
 	echo; \
 	echo "Src_Dirs_I = \\"; \
 	echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \
@@ -244,8 +246,9 @@
 	echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(ARCH)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
-	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
+	echo "$(call gamma-path,altsrc,gpu) \\"; \
+	echo "$(call gamma-path,commonsrc,gpu)"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
 	    echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \
 	[ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \
--- a/make/solaris/makefiles/vm.make	Mon Jun 10 08:44:03 2013 +0200
+++ b/make/solaris/makefiles/vm.make	Mon Jun 10 08:44:25 2013 +0200
@@ -194,7 +194,9 @@
 COMPILER2_PATHS +=  $(GENERATED)/adfiles
 
 GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/graal)
+GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/ptx)
 GRAAL_PATHS += $(HS_COMMON_SRC)/share/vm/graal
+GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/ptx
 
 # Include dirs per type.
 Src_Dirs/CORE      := $(CORE_PATHS)
--- a/mx/commands.py	Mon Jun 10 08:44:03 2013 +0200
+++ b/mx/commands.py	Mon Jun 10 08:44:25 2013 +0200
@@ -232,6 +232,8 @@
     machine = platform.uname()[4]
     if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']:
         return 'amd64'
+    if machine in ['sun4v']:
+        return 'sparc'
     if machine == 'i386' and mx.get_os() == 'darwin':
         try:
             # Support for Snow Leopard and earlier version of MacOSX
@@ -343,6 +345,7 @@
 
 def _installGraalJarInJdks(graalDist):
     graalJar = graalDist.path
+    graalOptions = join(_graal_home, 'graal.options')
     jdks = join(_graal_home, 'jdk' + str(mx.java().version))
     if exists(jdks):
         for e in os.listdir(jdks):
@@ -353,6 +356,9 @@
                 shutil.copyfile(graalJar, tmp)
                 os.close(fd)
                 shutil.move(tmp, join(jreLibDir, 'graal.jar'))
+                
+                if exists(graalOptions):
+                    shutil.copy(graalOptions, join(jreLibDir, 'graal.options'))
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}):
@@ -458,7 +464,7 @@
     out.element('property', {'name' : 'jar.dir', 'value' : '${shared.dir}'})
     out.element('property', {'name' : 'jar.file', 'value' : '${jar.dir}/graal.jar'})
     
-    out.element('target', {'name' : 'main', 'depends' : 'jar'})
+    out.element('target', {'name' : 'main', 'depends' : 'options,jar'})
 
     serviceMap = {};
     def addService(service, provider):
@@ -513,6 +519,16 @@
     out.element('delete', {'dir' : '${classes.dir}'})
     out.close('target')
 
+    out.open('target', {'name' : 'options', 'if' : 'graal.options.exists'})
+    out.open('copy', {'todir' : '${jar.dir}'})
+    out.element('filelist', {'dir' : '${gamma.dir}', 'files' : 'graal.options'})
+    out.close('copy')
+    out.close('target')
+
+    out.open('target', {'name' : 'check-graal-options-exists'})
+    out.element('available', {'property' : 'graal.options.exists', 'file' : '${gamma.dir}/graal.options'})
+    out.close('target')
+    
     out.open('target', {'name' : 'clean', 'depends' : 'cleanclasses'})
     out.element('delete', {'file' : '${jar.file}'})
     out.close('target')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/sparc/vm/codeInstaller_sparc.hpp	Mon Jun 10 08:44:25 2013 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+#ifndef CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
+#define CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
+
+inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+  fatal("CodeInstaller::pd_next_offset - sparc unimp");
+  return 0;
+}
+
+inline void CodeInstaller::pd_site_DataPatch(oop constant, oop kind, bool inlined,
+                                             address instruction, int alignment, char typeChar) {
+  fatal("CodeInstaller::pd_site_DataPatch - sparc unimp");
+}
+
+inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+  fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
+}
+
+inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+  fatal("CodeInstaller::pd_relocate_ForeignCall - sparc unimp");
+}
+
+inline void CodeInstaller::pd_relocate_JavaMethod(oop method, jint pc_offset) {
+  fatal("CodeInstaller::pd_relocate_JavaMethod - sparc unimp");
+}
+
+inline int32_t* CodeInstaller::pd_locate_operand(address instruction) {
+  fatal("CodeInstaller::pd_locate_operand - sparc unimp");
+  return (int32_t*)0;
+}
+
+#endif // CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
--- a/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Mon Jun 10 08:44:25 2013 +0200
@@ -31,6 +31,32 @@
 // Sets the default values for platform dependent flags used by the Graal compiler.
 // (see graalGlobals.hpp)
 
-define_pd_global(intx, GraalSafepointPollOffset,     0    );
+#if !defined(COMPILER1) && !defined(COMPILER2)
+define_pd_global(bool, BackgroundCompilation,        true );
+define_pd_global(bool, UseTLAB,                      true );
+define_pd_global(bool, ResizeTLAB,                   true );
+define_pd_global(bool, InlineIntrinsics,             true );
+define_pd_global(bool, PreferInterpreterNativeStubs, false);
+define_pd_global(bool, TieredCompilation,            false);
+define_pd_global(intx, BackEdgeThreshold,            100000);
+
+define_pd_global(intx, OnStackReplacePercentage,     933  );
+define_pd_global(intx, FreqInlineSize,               325  );
+define_pd_global(intx, NewSizeThreadIncrease,        4*K  );
+define_pd_global(uintx,MetaspaceSize,                12*M );
+define_pd_global(bool, NeverActAsServerClassMachine, false);
+define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
+define_pd_global(bool, CICompileOSR,                 true );
+define_pd_global(bool, ProfileTraps,                 true );
+define_pd_global(bool, UseOnStackReplacement,        true );
+define_pd_global(intx, CompileThreshold,             10000);
+define_pd_global(intx, InitialCodeCacheSize,         16*M );
+define_pd_global(intx, ReservedCodeCacheSize,        64*M );
+define_pd_global(bool, ProfileInterpreter,           true );
+define_pd_global(intx, CodeCacheExpansionSize,       64*K );
+define_pd_global(uintx,CodeCacheMinBlockLength,      4);
+define_pd_global(intx, TypeProfileWidth,             8);
+define_pd_global(intx, MethodProfileWidth,           4);
+#endif
 
 #endif // CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP
--- a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp	Mon Jun 10 08:44:25 2013 +0200
@@ -27,11 +27,16 @@
 
  friend class AbstractInterpreterGenerator;
 
+  address generate_deopt_entry_for(TosState state, int step);
+
  private:
 
   address generate_normal_entry(bool synchronized);
   address generate_native_entry(bool synchronized);
-  address generate_abstract_entry(void);
+#ifdef GRAAL
+  address generate_execute_compiled_method_entry();
+#endif
+ address generate_abstract_entry(void);
   address generate_math_entry(AbstractInterpreter::MethodKind kind);
   address generate_empty_entry(void);
   address generate_accessor_entry(void);
--- a/src/cpu/sparc/vm/nativeInst_sparc.cpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/cpu/sparc/vm/nativeInst_sparc.cpp	Mon Jun 10 08:44:25 2013 +0200
@@ -24,6 +24,8 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "code/codeCache.hpp"
 #include "memory/resourceArea.hpp"
 #include "nativeInst_sparc.hpp"
 #include "oops/oop.inline.hpp"
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Jun 10 08:44:25 2013 +0200
@@ -1826,6 +1826,20 @@
   verify_oop_args(masm, method, sig_bt, regs);
   vmIntrinsics::ID iid = method->intrinsic_id();
 
+
+#ifdef GRAAL
+  if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // We are called from compiled code here. The three object arguments
+    // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The
+    // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail
+    // call to its verified entry point.
+    __ set(nmethod::verified_entry_point_offset(), O0);
+    __ JMP(O0, 0);
+    __ delayed()->nop();
+    return;
+  }
+#endif
+
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
   Register receiver_reg   = noreg;
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Mon Jun 10 08:44:25 2013 +0200
@@ -213,7 +213,7 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
+address InterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
   address entry = __ pc();
   __ get_constant_pool_cache(LcpoolCache); // load LcpoolCache
   { Label L;
@@ -813,6 +813,19 @@
   return generate_accessor_entry();
 }
 
+#ifdef GRAAL
+
+// Interpreter stub for calling a compiled method with 3 object arguments
+address InterpreterGenerator::generate_execute_compiled_method_entry() {
+  address entry_point = __ pc();
+
+  __ stop("graal-sparc unimp");
+
+  return entry_point;
+}
+
+#endif
+
 //
 // Interpreter stub for calling a native method. (asm interpreter)
 // This sets up a somewhat different looking stack for calling the native method
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/codeInstaller_x86.hpp	Mon Jun 10 08:44:25 2013 +0200
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+#ifndef CPU_SPARC_VM_CODEINSTALLER_X86_HPP
+#define CPU_SPARC_VM_CODEINSTALLER_X86_HPP
+
+#include "compiler/disassembler.hpp"
+#include "runtime/javaCalls.hpp"
+#include "graal/graalEnv.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCodeInstaller.hpp"
+#include "graal/graalJavaAccess.hpp"
+#include "graal/graalCompilerToVM.hpp"
+#include "graal/graalRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+
+inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+  if (inst->is_call() || inst->is_jump()) {
+    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
+    return (pc_offset + NativeCall::instruction_size);
+  } else if (inst->is_mov_literal64()) {
+    // mov+call instruction pair
+    jint offset = pc_offset + NativeMovConstReg::instruction_size;
+    u_char* call = (u_char*) (_instructions->start() + offset);
+    assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
+    offset += 3; /* prefix byte + opcode byte + modrm byte */
+    return (offset);
+  } else if (inst->is_call_reg()) {
+    // the inlined vtable stub contains a "call register" instruction
+    assert(method != NULL, "only valid for virtual calls");
+    return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
+  } else {
+    fatal("unsupported type of instruction for call site");
+    return 0;
+  }
+}
+
+inline void CodeInstaller::pd_site_DataPatch(oop constant, oop kind, bool inlined,
+                                             address instruction, int alignment, char typeChar) {
+  switch (typeChar) {
+    case 'z':
+    case 'b':
+    case 's':
+    case 'c':
+    case 'i':
+      fatal("int-sized values not expected in DataPatch");
+      break;
+    case 'f':
+    case 'j':
+    case 'd': {
+      if (inlined) {
+        address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
+        *((jlong*) operand) = Constant::primitive(constant);
+      } else {
+        address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand);
+        address next_instruction = Assembler::locate_next_instruction(instruction);
+        int size = _constants->size();
+        if (alignment > 0) {
+          guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
+          size = align_size_up(size, alignment);
+        }
+        // we don't care if this is a long/double/etc., the primitive field contains the right bits
+        address dest = _constants->start() + size;
+        _constants->set_end(dest + BytesPerLong);
+        *(jlong*) dest = Constant::primitive(constant);
+
+        long disp = dest - next_instruction;
+        assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+        *((jint*) operand) = (jint) disp;
+
+        _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+        TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size);
+      }
+      break;
+    }
+    case 'a': {
+      address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
+      Handle obj = Constant::object(constant);
+
+      jobject value = JNIHandles::make_local(obj());
+      *((jobject*) operand) = value;
+      _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+      TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand);
+      break;
+    }
+    default:
+      fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar));
+      break;
+  }
+}
+
+inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+  if (cb->is_nmethod()) {
+    nmethod* nm = (nmethod*) cb;
+    nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
+  } else {
+    nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
+  }
+  _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+}
+
+inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+  if (inst->is_call()) {
+    // NOTE: for call without a mov, the offset must fit a 32-bit immediate
+    //       see also CompilerToVM.getMaxCallTargetOffset()
+    NativeCall* call = nativeCall_at((address) (inst));
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else if (inst->is_mov_literal64()) {
+    NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst));
+    mov->set_data((intptr_t) foreign_call_destination);
+    _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
+  } else {
+    NativeJump* jump = nativeJump_at((address) (inst));
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+  }
+  TRACE_graal_3("relocating (foreign call)  at %p", inst);
+}
+
+inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method);
+  }
+#endif
+  switch (_next_call_type) {
+    case MARK_INLINE_INVOKE:
+      break;
+    case MARK_INVOKEVIRTUAL:
+    case MARK_INVOKEINTERFACE: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             virtual_call_Relocation::spec(_invoke_mark_pc),
+                                             Assembler::call32_operand);
+      break;
+    }
+    case MARK_INVOKESTATIC: {
+      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             relocInfo::static_call_type, Assembler::call32_operand);
+      break;
+    }
+    case MARK_INVOKESPECIAL: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                              relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+      break;
+    }
+    default:
+      fatal("invalid _next_call_type value");
+      break;
+  }
+}
+
+inline int32_t* CodeInstaller::pd_locate_operand(address instruction) {
+  return (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+}
+
+#endif // CPU_SPARC_VM_CODEINSTALLER_X86_HPP
+
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Jun 10 08:44:25 2013 +0200
@@ -314,6 +314,7 @@
   template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")             \
   template(com_oracle_graal_hotspot_debug_LocalImpl,                 "com/oracle/graal/hotspot/debug/LocalImpl")                      \
   AMD64_ONLY(template(com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime,"com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime"))\
+  SPARC_ONLY(template(com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime,"com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime"))\
   /* graal.api.meta */                                                                                                                \
   template(com_oracle_graal_api_meta_Constant,                       "com/oracle/graal/api/meta/Constant")                            \
   template(com_oracle_graal_api_meta_ConstantPool,                   "com/oracle/graal/api/meta/ConstantPool")                        \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Jun 10 08:44:25 2013 +0200
@@ -35,18 +35,23 @@
 #include "code/vmreg.hpp"
 
 #ifdef TARGET_ARCH_x86
+# include "codeInstaller_x86.hpp"
 # include "vmreg_x86.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_sparc
+# include "codeInstaller_sparc.hpp"
 # include "vmreg_sparc.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_zero
+# include "codeInstaller_zero.hpp"
 # include "vmreg_zero.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_arm
+# include "codeInstaller_arm.hpp"
 # include "vmreg_arm.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_ppc
+# include "codeInstaller_ppc.hpp"
 # include "vmreg_ppc.inline.hpp"
 #endif
 
@@ -199,8 +204,16 @@
       }
       return value;
 #else
+#ifdef TARGET_ARCH_sparc
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_FloatRegister(number)->as_VMReg()));
+      if (type == T_DOUBLE) {
+        second = value;
+      }
+      return value;
+#else
       ShouldNotReachHere("Platform currently does not support floating point values.");
 #endif
+#endif
     }
   } else if (value->is_a(StackSlot::klass())) {
     if (type == T_DOUBLE) {
@@ -704,36 +717,15 @@
   assert((hotspot_method ? 1 : 0) + (foreign_call ? 1 : 0) == 1, "Call site needs exactly one type");
 
   NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
-  jint next_pc_offset = 0x0;
-  if (inst->is_call() || inst->is_jump()) {
-    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
-    next_pc_offset = pc_offset + NativeCall::instruction_size;
-  } else if (inst->is_mov_literal64()) {
-    // mov+call instruction pair
-    next_pc_offset = pc_offset + NativeMovConstReg::instruction_size;
-    u_char* call = (u_char*) (_instructions->start() + next_pc_offset);
-    assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
-    next_pc_offset += 3; /* prefix byte + opcode byte + modrm byte */
-  } else if (inst->is_call_reg()) {
-    // the inlined vtable stub contains a "call register" instruction
-    assert(hotspot_method != NULL, "only valid for virtual calls");
-    next_pc_offset = pc_offset + ((NativeCallReg *) inst)->next_instruction_offset();
-  } else {
-    fatal("unsupported type of instruction for call site");
-  }
-
+  jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method);
+  
   if (target->is_a(SystemDictionary::HotSpotInstalledCode_klass())) {
     assert(inst->is_jump(), "jump expected");
 
     CodeBlob* cb = (CodeBlob*) (address) HotSpotInstalledCode::codeBlob(target);
     assert(cb != NULL, "npe");
-    if (cb->is_nmethod()) {
-      nmethod* nm = (nmethod*) cb;
-      nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
-    } else {
-      nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
-    }
-    _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+    
+    CodeInstaller::pd_relocate_CodeBlob(cb, inst);
 
     return;
   }
@@ -750,65 +742,14 @@
 
   if (foreign_call != NULL) {
     jlong foreign_call_destination = HotSpotForeignCallLinkage::address(foreign_call);
-    if (inst->is_call()) {
-      // NOTE: for call without a mov, the offset must fit a 32-bit immediate
-      //       see also CompilerToVM.getMaxCallTargetOffset()
-      NativeCall* call = nativeCall_at((address) (inst));
-      call->set_destination((address) foreign_call_destination);
-      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
-    } else if (inst->is_mov_literal64()) {
-      NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst));
-      mov->set_data((intptr_t) foreign_call_destination);
-      _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
-    } else {
-      NativeJump* jump = nativeJump_at((address) (inst));
-      jump->set_jump_destination((address) foreign_call_destination);
-      _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
-    }
-    TRACE_graal_3("relocating (foreign call)  at %p", inst);
+
+    CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination);
   } else { // method != NULL
     assert(hotspot_method != NULL, "unexpected JavaMethod");
-#ifdef ASSERT
-    Method* method = NULL;
-    // we need to check, this might also be an unresolved method
-    if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
-      method = getMethodFromHotSpotMethod(hotspot_method);
-    }
-#endif
     assert(debug_info != NULL, "debug info expected");
 
     TRACE_graal_3("method call");
-    switch (_next_call_type) {
-      case MARK_INLINE_INVOKE:
-        break;
-      case MARK_INVOKEVIRTUAL:
-      case MARK_INVOKEINTERFACE: {
-        assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
-
-        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-        call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
-        _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand);
-        break;
-      }
-      case MARK_INVOKESTATIC: {
-        assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
-
-        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-        call->set_destination(SharedRuntime::get_resolve_static_call_stub());
-        _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand);
-        break;
-      }
-      case MARK_INVOKESPECIAL: {
-        assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
-        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-        call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
-        _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand);
-        break;
-      }
-      default:
-        fatal("invalid _next_call_type value");
-        break;
-    }
+    CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset);
   }
   _next_call_type = MARK_INVOKE_INVALID;
   if (debug_info != NULL) {
@@ -823,59 +764,15 @@
   oop kind = Constant::kind(constant);
 
   address instruction = _instructions->start() + pc_offset;
-
   char typeChar = Kind::typeChar(kind);
   switch (typeChar) {
-    case 'z':
-    case 'b':
-    case 's':
-    case 'c':
-    case 'i':
-      fatal("int-sized values not expected in DataPatch");
-      break;
     case 'f':
     case 'j':
-    case 'd': {
+    case 'd':
       record_metadata_in_constant(constant, _oop_recorder);
-      if (inlined) {
-        address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
-        *((jlong*) operand) = Constant::primitive(constant);
-      } else {
-        address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand);
-        address next_instruction = Assembler::locate_next_instruction(instruction);
-        int size = _constants->size();
-        if (alignment > 0) {
-          guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
-          size = align_size_up(size, alignment);
-        }
-        // we don't care if this is a long/double/etc., the primitive field contains the right bits
-        address dest = _constants->start() + size;
-        _constants->set_end(dest + BytesPerLong);
-        *(jlong*) dest = Constant::primitive(constant);
-
-        long disp = dest - next_instruction;
-        assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
-        *((jint*) operand) = (jint) disp;
-
-        _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
-        TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size);
-      }
-      break;
-    }
-    case 'a': {
-      address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
-      Handle obj = Constant::object(constant);
-
-      jobject value = JNIHandles::make_local(obj());
-      *((jobject*) operand) = value;
-      _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
-      TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand);
-      break;
-    }
-    default:
-      fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar));
       break;
   }
+  CodeInstaller::pd_site_DataPatch(constant, kind, inlined, instruction, alignment, typeChar);
 }
 
 void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) {
@@ -920,7 +817,8 @@
         break;
       case MARK_POLL_NEAR: {
         NativeInstruction* ni = nativeInstruction_at(instruction);
-        int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+        int32_t* disp = (int32_t*) pd_locate_operand(instruction);
+        // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
         int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
         intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
         *disp = (int32_t)new_disp;
@@ -930,7 +828,8 @@
         break;
       case MARK_POLL_RETURN_NEAR: {
         NativeInstruction* ni = nativeInstruction_at(instruction);
-        int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+        int32_t* disp = (int32_t*) pd_locate_operand(instruction);
+        // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
         int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
         intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
         *disp = (int32_t)new_disp;
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Mon Jun 10 08:44:25 2013 +0200
@@ -75,6 +75,13 @@
   Dependencies*             _dependencies;
   ExceptionHandlerTable     _exception_handler_table;
 
+  jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method);
+  void pd_site_DataPatch(oop constant, oop kind, bool inlined, address instruction, int alignment, char typeChar);
+  void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst);
+  void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination);
+  void pd_relocate_JavaMethod(oop method, jint pc_offset);
+  int32_t* pd_locate_operand(address instruction);
+
 public:
 
   CodeInstaller(Handle& comp_result, GraalEnv::CodeInstallResult& result, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations);
@@ -106,4 +113,20 @@
 
 };
 
+#ifdef TARGET_ARCH_x86
+# include "codeInstaller_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "codeInstaller_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# error
+#endif
+#ifdef TARGET_ARCH_arm
+# error
+#endif
+#ifdef TARGET_ARCH_ppc
+# error
+#endif
+
 #endif // SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
--- a/src/share/vm/graal/graalCompiler.cpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Mon Jun 10 08:44:25 2013 +0200
@@ -51,7 +51,7 @@
 
   uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
   uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
-  guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)");
+  AMD64_ONLY(guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)"));
   NOT_LP64(error("check TLAB allocation code for address space conflicts"));
 
   _deopted_leaf_graph_count = 0;
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Jun 10 08:44:25 2013 +0200
@@ -658,8 +658,10 @@
   set_boolean("useAESIntrinsics", UseAESIntrinsics);
   set_boolean("useTLAB", UseTLAB);
   set_boolean("useG1GC", UseG1GC);
+#ifdef TARGET_ARCH_x86
   set_int("useSSE", UseSSE);
   set_int("useAVX", UseAVX);
+#endif
   set_int("codeEntryAlignment", CodeEntryAlignment);
   set_int("stackShadowPages", StackShadowPages);
   set_int("hubOffset", oopDesc::klass_offset_in_bytes());
@@ -695,9 +697,11 @@
   set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER);
   set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset()));
   set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
+#ifdef TARGET_ARCH_x86
   set_boolean("isPollingPageFar", Assembler::is_polling_page_far());
+  set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes);
+#endif
   set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset()));
-  set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes);
   set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset()));
   set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset()));
   set_int("klassOffset", java_lang_Class::klass_offset_in_bytes());
@@ -744,7 +748,9 @@
   set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset()));
   set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset()));
   set_int("threadLastJavaSpOffset", in_bytes(JavaThread::last_Java_sp_offset()));
+#ifdef TARGET_ARCH_x86
   set_int("threadLastJavaFpOffset", in_bytes(JavaThread::last_Java_fp_offset()));
+#endif
   set_int("threadLastJavaPcOffset", in_bytes(JavaThread::last_Java_pc_offset()));
   set_int("threadObjectResultOffset", in_bytes(JavaThread::vm_result_offset()));
   set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset()));
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Mon Jun 10 08:44:25 2013 +0200
@@ -51,6 +51,9 @@
 #ifdef AMD64
     Symbol* name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime();
 #endif
+#ifdef SPARC
+    Symbol* name = vmSymbols::com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime();
+#endif
     KlassHandle klass = loadClass(name);
 
     JavaValue result(T_OBJECT);
--- a/src/share/vm/runtime/fieldDescriptor.cpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/share/vm/runtime/fieldDescriptor.cpp	Mon Jun 10 08:44:25 2013 +0200
@@ -27,9 +27,6 @@
 #include "classfile/vmSymbols.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
-#include "oops/annotations.hpp"
-#include "oops/instanceKlass.hpp"
-#include "oops/fieldStreams.hpp"
 #include "runtime/fieldDescriptor.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/signature.hpp"
--- a/src/share/vm/runtime/fieldDescriptor.hpp	Mon Jun 10 08:44:03 2013 +0200
+++ b/src/share/vm/runtime/fieldDescriptor.hpp	Mon Jun 10 08:44:25 2013 +0200
@@ -25,7 +25,10 @@
 #ifndef SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP
 #define SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP
 
+#include "oops/annotations.hpp"
 #include "oops/constantPool.hpp"
+#include "oops/fieldStreams.hpp"
+#include "oops/instanceKlass.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/fieldType.hpp"
 #include "utilities/accessFlags.hpp"