changeset 9714:521c4f7aac66

Merge.
author Christian Haeubl <haeubl@ssw.jku.at>
date Wed, 15 May 2013 09:03:43 +0200
parents 4420f32a6d5c (current diff) 5797e0028796 (diff)
children badabdca0c53
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/WriteBarrierPostStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/WriteBarrierPreStub.java
diffstat 29 files changed, 1222 insertions(+), 626 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Wed May 15 09:03:43 2013 +0200
@@ -48,12 +48,6 @@
         JavaCallee(false),
 
         /**
-         * A request for the outgoing argument locations at a call site to the runtime (which may be
-         * Java or native code).
-         */
-        RuntimeCall(true),
-
-        /**
          * A request for the outgoing argument locations at a call site to external native code that
          * complies with the platform ABI.
          */
@@ -152,6 +146,16 @@
     }
 
     /**
+     * Gets the locations required for the arguments.
+     */
+    public AllocatableValue[] getArguments() {
+        if (argumentLocations.length == 0) {
+            return argumentLocations;
+        }
+        return argumentLocations.clone();
+    }
+
+    /**
      * Gets the locations used (and killed) by the call apart from the
      * {@linkplain #getArgument(int) arguments}.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/AbstractSPARCAssembler.java	Wed May 15 09:03:43 2013 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2009, 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.asm.sparc;
+
+import com.oracle.graal.api.code.AbstractAddress;
+import com.oracle.graal.api.code.Register;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.asm.AbstractAssembler;
+import com.oracle.graal.asm.Label;
+
+public abstract class AbstractSPARCAssembler extends AbstractAssembler {
+
+    public AbstractSPARCAssembler(TargetDescription target) {
+        super(target);
+    }
+
+    @Override
+    public void align(int modulus) {
+        // SPARC: Implement alignment.
+    }
+
+    @Override
+    public void jmp(Label l) {
+        // SPARC: Implement jump.
+    }
+
+    @Override
+    protected void patchJumpTarget(int branch, int jumpTarget) {
+        // SPARC: Implement patching of jump target.
+    }
+
+    @Override
+    public AbstractAddress makeAddress(Register base, int displacement) {
+        // SPARC: Implement address calculation.
+        return null;
+    }
+
+    @Override
+    public AbstractAddress getPlaceholder() {
+        // SPARC: Implement address patching.
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Wed May 15 09:03:43 2013 +0200
@@ -23,13 +23,96 @@
 package com.oracle.graal.asm.sparc;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.asm.*;
 import com.oracle.graal.sparc.*;
 
 /**
  * This class implements an assembler that can encode most SPARC instructions.
  */
-public class SPARCAssembler extends AbstractAssembler {
+public class SPARCAssembler extends AbstractSPARCAssembler {
+
+    public static final int ImmedTrue = 0x00002000;
+
+    public enum Ops {
+        CallOp(0x40000000),
+        BranchOp(0x00000000),
+        ArithOp(0x80000000),
+        LdstOp(0xC0000000);
+
+        private final int value;
+
+        private Ops(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+    public enum Op3s {
+        Add((0x00 << 19) & 0x01F80000, "add"),
+        And((0x01 << 19) & 0x01F80000, "and"),
+        Or((0x02 << 19) & 0x01F80000, "or"),
+        Xor((0x03 << 19) & 0x01F80000, "xor"),
+        Sub((0x04 << 19) & 0x01F80000, "sub"),
+        Andn((0x05 << 19) & 0x01F80000, "andn"),
+        Orn((0x06 << 19) & 0x01F80000, "orn"),
+        Xnor((0x07 << 19) & 0x01F80000, "xnor"),
+        Addc((0x08 << 19) & 0x01F80000, "addc"),
+        Mulx((0x09 << 19) & 0x01F80000, "mulx"),
+        Umul((0x0A << 19) & 0x01F80000, "umul"),
+        Smul((0x0B << 19) & 0x01F80000, "smul"),
+        Subc((0x0C << 19) & 0x01F80000, "subc"),
+        Udivx((0x0D << 19) & 0x01F80000, "udivx"),
+        Udiv((0x0E << 19) & 0x01F80000, "udiv"),
+        Sdiv((0x0F << 19) & 0x01F80000, "sdiv"),
+
+        Addcc((0x10 << 19) & 0x01F80000, "addcc"),
+        Andcc((0x11 << 19) & 0x01F80000, "andcc"),
+        Orcc((0x12 << 19) & 0x01F80000, "orcc"),
+        Xorcc((0x13 << 19) & 0x01F80000, "xorcc"),
+        Subcc((0x14 << 19) & 0x01F80000, "subcc"),
+        Andncc((0x15 << 19) & 0x01F80000, "andncc"),
+        Orncc((0x16 << 19) & 0x01F80000, "orncc"),
+        Xnorcc((0x17 << 19) & 0x01F80000, "xnorcc"),
+        Addccc((0x18 << 19) & 0x01F80000, "addccc"),
+        Mulxcc((0x19 << 19) & 0x01F80000, "mulxcc"),
+        Umulcc((0x1A << 19) & 0x01F80000, "umulcc"),
+        Smulcc((0x1B << 19) & 0x01F80000, "smulcc"),
+        Subccc((0x1C << 19) & 0x01F80000, "subccc"),
+        Udivcc((0x1E << 19) & 0x01F80000, "udivcc"),
+        Sdivcc((0x1F << 19) & 0x01F80000, "sdivcc"),
+
+        Taddcc((0x20 << 19) & 0x01F80000, "taddcc"),
+        Tsubcc((0x21 << 19) & 0x01F80000, "tsubcc"),
+        Taddcctv((0x22 << 19) & 0x01F80000, "taddcctv"),
+        Tsubcctv((0x23 << 19) & 0x01F80000, "tsubcctv"),
+        Mulscc((0x23 << 19) & 0x01F80000, "mulscc"),
+        Sll((0x25 << 19) & 0x01F80000, "sll"),
+        Sllx((0x25 << 19) & 0x01F80000, "sllx"),
+        Srl((0x26 << 19) & 0x01F80000, "srl"),
+        Srlx((0x26 << 19) & 0x01F80000, "srlx"),
+        Sra((0x27 << 19) & 0x01F80000, "srax"),
+        Srax((0x27 << 19) & 0x01F80000, "srax"),
+        Rdreg((0x27 << 19) & 0x01F80000, "rdreg"),
+        Membar((0x27 << 19) & 0x01F80000, "membar");
+
+        private final int value;
+        private final String operator;
+
+        private Op3s(int value, String op) {
+            this.value = value;
+            this.operator = op;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
+    }
 
     @SuppressWarnings("unused")
     public SPARCAssembler(TargetDescription target) {
@@ -38,30 +121,391 @@
         SPARC sparc;
     }
 
-    @Override
-    public void align(int modulus) {
-        // SPARC: Implement alignment.
+    public static final int rs1(int val) {
+        return val;
+    }
+
+    public static final int rs2(int val) {
+        return val;
+    }
+
+    public static final int rd(int val) {
+        return val;
+    }
+
+    public static final int sx1 = 0x00001000;
+
+    public static final int simm(int x, int nbits) {
+        // assert_signed_range(x, nbits);
+        return x & ((1 << nbits) - 1);
+    }
+
+    public final void add(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Add.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void add(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Add.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void addcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Addcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void addcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Addcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void addc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Addc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void addc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Addc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void addccc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Addccc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void addccc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Addccc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void and(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.And.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void and(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.And.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void andcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Andcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void andcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Andcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void andn(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Andn.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void andn(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Andn.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void andncc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Andncc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void andncc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Andncc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void mulscc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Mulscc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void mulscc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Mulscc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
     }
 
-    @Override
-    public void jmp(Label l) {
-        // SPARC: Implement jump.
+    public final void mulx(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Mulx.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void mulx(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Mulx.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void or(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Or.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void or(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Or.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void orcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Orcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void orcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Orcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void orn(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Orn.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void orn(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Orn.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void orncc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Orncc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void orncc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Orncc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void rdy(Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()));
+    }
+
+    // A.44 Read State Register
+
+    public final void rdccr(Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x00008000);
+    }
+
+    public final void rdasi(Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x0000C000);
+    }
+
+    public final void rdtick(Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x00010000);
+    }
+
+    public final void rdpc(Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x00014000);
+    }
+
+    public final void rdfprs(Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Rdreg.getValue() | rd(dst.encoding()) | 0x00018000);
+    }
+
+    @Deprecated
+    public final void sdiv(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sdiv.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    @Deprecated
+    public final void sdiv(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sdiv.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    @Deprecated
+    public final void sdivcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sdivcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    @Deprecated
+    public final void sdivcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sdivcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void sll(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sll.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void sll(Register src1, int imm5a, Register dst) {
+        assert imm5a < 0x40;
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sll.getValue() | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    }
+
+    public final void sllx(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sllx.getValue() | sx1 | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
     }
 
-    @Override
-    protected void patchJumpTarget(int branch, int jumpTarget) {
-        // SPARC: Implement patching of jump target.
+    public final void sllx(Register src1, int imm5a, Register dst) {
+        assert imm5a < 0x40;
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sllx.getValue() | sx1 | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    }
+
+    public final void smul(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Smul.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void smul(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Smul.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void smulcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Smulcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void smulcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Smulcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void sra(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sra.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void sra(Register src1, int imm5a, Register dst) {
+        assert imm5a < 0x40;
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sra.getValue() | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    }
+
+    public final void srax(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Srax.getValue() | sx1 | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void srax(Register src1, int imm5a, Register dst) {
+        assert imm5a < 0x40;
+        emitInt(Ops.ArithOp.getValue() | Op3s.Srax.getValue() | sx1 | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    }
+
+    public final void srl(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Srl.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void srl(Register src1, int imm5a, Register dst) {
+        assert imm5a < 0x40;
+        emitInt(Ops.ArithOp.getValue() | Op3s.Srl.getValue() | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    }
+
+    public final void srlx(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Srlx.getValue() | sx1 | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void srlx(Register src1, int imm5a, Register dst) {
+        assert imm5a < 0x40;
+        emitInt(Ops.ArithOp.getValue() | Op3s.Srlx.getValue() | sx1 | rs1(src1.encoding()) | ImmedTrue | imm5a | rd(dst.encoding()));
+    }
+
+    public final void sub(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sub.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void sub(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Sub.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void subcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Subcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void subcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Subcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void subc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Subc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void subc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Subc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void subccc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Subccc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void subccc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Subccc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void taddcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Taddcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void taddcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Taddcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
     }
 
-    @Override
-    public AbstractAddress makeAddress(Register base, int displacement) {
-        // SPARC: Implement address calculation.
-        return null;
+    public final void taddcctv(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Taddcctv.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void taddcctv(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Taddcctv.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void tsubcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Tsubcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void tsubcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Tsubcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void tsubcctv(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Tsubcctv.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void tsubcctv(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Tsubcctv.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    @Deprecated
+    public final void udiv(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Udiv.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    @Deprecated
+    public final void udiv(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Udiv.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    @Deprecated
+    public final void udivcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Udivcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    @Deprecated
+    public final void udivcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Udivcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void udivx(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Udivx.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
     }
 
-    @Override
-    public AbstractAddress getPlaceholder() {
-        // SPARC: Implement address patching.
-        return null;
+    public final void udivx(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Udivx.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void umul(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Umul.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void umul(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Umul.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void umulcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Umulcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void umulcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Umulcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void xor(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Xor.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void xor(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Xor.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
     }
+
+    public final void xorcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Xorcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void xorcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Xorcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void xnor(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Xnor.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void xnor(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Xnor.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
+    public final void xnorcc(Register src1, Register src2, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Xnorcc.getValue() | rs1(src1.encoding()) | rs2(src2.encoding()) | rd(dst.encoding()));
+    }
+
+    public final void xnorcc(Register src1, int simm13, Register dst) {
+        emitInt(Ops.ArithOp.getValue() | Op3s.Xnorcc.getValue() | rs1(src1.encoding()) | ImmedTrue | simm(simm13, 13) | rd(dst.encoding()));
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed May 15 09:03:43 2013 +0200
@@ -211,12 +211,12 @@
     @Override
     public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention callCc, DeoptimizingNode info, Value... args) {
         Stub stub = getStub();
-        boolean isCRuntimeCall = ((HotSpotRuntimeCallTarget) callTarget).isCRuntimeCall();
-        assert !isCRuntimeCall || stub != null : "direct call to C runtime can only be made from compiled stubs, not from " + graph;
+        boolean destroysRegisters = ((HotSpotRuntimeCallTarget) callTarget).destroysRegisters();
+        assert !destroysRegisters || stub != null : "foreign call that destroys registers can only be made from compiled stub, not from " + graph;
 
         AMD64SaveRegistersOp save = null;
         StackSlot[] savedRegisterLocations = null;
-        if (isCRuntimeCall) {
+        if (destroysRegisters) {
             if (stub.preservesRegisters()) {
                 Register[] savedRegisters = frameMap.registerConfig.getAllocatableRegisters();
                 savedRegisterLocations = new StackSlot[savedRegisters.length];
@@ -233,7 +233,7 @@
 
         Variable result = super.emitCall(callTarget, callCc, info, args);
 
-        if (isCRuntimeCall) {
+        if (destroysRegisters) {
             append(new AMD64HotSpotCRuntimeCallEpilogueOp());
             if (stub.preservesRegisters()) {
                 assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed May 15 09:03:43 2013 +0200
@@ -106,7 +106,7 @@
         return allocatable;
     }
 
-    public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config, boolean globalStubConfig) {
+    public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config, boolean isNative) {
         this.architecture = architecture;
 
         if (config.windowsOs) {
@@ -117,7 +117,7 @@
             nativeGeneralParameterRegisters = new Register[] {rdi, rsi, rdx, rcx, r8, r9};
         }
 
-        if (globalStubConfig) {
+        if (isNative) {
             Register[] regs = {
                 rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
                 r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
@@ -147,6 +147,7 @@
         if (type == Type.NativeCall) {
             return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
         }
+        // On x64, parameter locations are the same whether viewed from the caller or callee perspective   
         return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Wed May 15 09:03:43 2013 +0200
@@ -23,7 +23,10 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotRuntimeCallTarget.*;
+import static com.oracle.graal.hotspot.HotSpotRuntimeCallTarget.RegisterEffect.*;
 import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.DecryptBlockStubCall.*;
 import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.EncryptBlockStubCall.*;
 import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*;
@@ -43,61 +46,29 @@
     public AMD64HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
         super(config, graalRuntime);
 
-        Kind word = graalRuntime.getTarget().wordKind;
-
-        // @formatter:off
-
-        // The calling convention for the exception handler stub is (only?) defined in
-        // TemplateInterpreterGenerator::generate_throw_exception()
-        // in templateInterpreter_x86_64.cpp around line 1923 
-        addStubCall(EXCEPTION_HANDLER,
-                /*            ret */ ret(Kind.Void),
-               /* arg0: exception */ rax.asValue(Kind.Object),
-             /* arg1: exceptionPc */ rdx.asValue(word));
-
-        addJump(EXCEPTION_HANDLER_IN_CALLER,
-                /* arg0: exception */ rax.asValue(Kind.Object),
-               /* arg1: exceptionPc */ rdx.asValue(word));
-
-        addRuntimeCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub,
-                /*        temps */ null,
-                /*          ret */ ret(Kind.Void),
-                /* arg0:     in */ nativeCallingConvention(word,
-                /* arg1:    out */                         word,
-                /* arg2:    key */                         word));
-
-        addRuntimeCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub,
-                /*        temps */ null,
-                /*          ret */ ret(Kind.Void),
-                /* arg0:     in */ nativeCallingConvention(word,
-                /* arg1:    out */                         word,
-                /* arg2:    key */                         word));
-
-        addRuntimeCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub,
-                /*        temps */ null,
-                /*          ret */ ret(Kind.Void),
-                /* arg0:     in */ nativeCallingConvention(word,
-                /* arg1:    out */                         word,
-                /* arg2:    key */                         word,
-                /* arg3:      r */                         word,
-              /* arg4: inLength */                         Kind.Int));
-
-        addRuntimeCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub,
-                /*        temps */ null,
-                /*          ret */ ret(Kind.Void),
-                /* arg0:     in */ nativeCallingConvention(word,
-                /* arg1:    out */                         word,
-                /* arg2:    key */                         word,
-                /* arg3:      r */                         word,
-              /* arg4: inLength */                         Kind.Int));
-        // @formatter:on
-
     }
 
     private AMD64ConvertSnippets.Templates convertSnippets;
 
     @Override
     public void registerReplacements(Replacements replacements) {
+        Kind word = graalRuntime.getTarget().wordKind;
+
+        // The calling convention for the exception handler stub is (only?) defined in
+        // TemplateInterpreterGenerator::generate_throw_exception()
+        // in templateInterpreter_x86_64.cpp around line 1923
+        RegisterValue exception = rax.asValue(Kind.Object);
+        RegisterValue exceptionPc = rdx.asValue(word);
+        CallingConvention exceptionCc = new CallingConvention(0, Value.ILLEGAL, exception, exceptionPc);
+        register(new HotSpotRuntimeCallTarget(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, exceptionCc, graalRuntime.getCompilerToVM()));
+        register(new HotSpotRuntimeCallTarget(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, exceptionCc, graalRuntime.getCompilerToVM()));
+
+        // The crypto stubs do callee saving
+        registerLeafCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS);
+        registerLeafCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS);
+        registerLeafCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS);
+        registerLeafCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS);
+
         convertSnippets = new AMD64ConvertSnippets.Templates(this, replacements, graalRuntime.getTarget());
         super.registerReplacements(replacements);
     }
@@ -122,7 +93,7 @@
     }
 
     @Override
-    protected RegisterConfig createRegisterConfig(boolean globalStubConfig) {
-        return new AMD64HotSpotRegisterConfig(graalRuntime.getTarget().arch, config, globalStubConfig);
+    protected RegisterConfig createRegisterConfig(boolean isNative) {
+        return new AMD64HotSpotRegisterConfig(graalRuntime.getTarget().arch, config, isNative);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java	Wed May 15 09:03:43 2013 +0200
@@ -46,7 +46,7 @@
     }
 
     @Override
-    protected RegisterConfig createRegisterConfig(boolean globalStubConfig) {
+    protected RegisterConfig createRegisterConfig(boolean isNative) {
         // SPARC: Create register configuration.
         return null;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Wed May 15 09:03:43 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
@@ -61,7 +59,7 @@
             Call call = (Call) infopoint;
             assert call.target instanceof HotSpotRuntimeCallTarget : this + " cannot have non runtime call: " + call.target;
             HotSpotRuntimeCallTarget callTarget = (HotSpotRuntimeCallTarget) call.target;
-            assert callTarget.getAddress() == graalRuntime().getConfig().uncommonTrapStub || callTarget.isCRuntimeCall() : this + "must only call C runtime or deoptimization stub, not " + call.target;
+            assert !callTarget.isCompiledStub() : this + " cannot call compiled stub " + callTarget;
         }
         return true;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Wed May 15 09:03:43 2013 +0200
@@ -22,13 +22,19 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.HotSpotRuntimeCallTarget.RegisterEffect.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.word.*;
 
 /**
  * The details required to link a HotSpot runtime or stub call.
@@ -36,17 +42,26 @@
 public class HotSpotRuntimeCallTarget implements RuntimeCallTarget, InvokeTarget {
 
     /**
+     * Constants for specifying whether a call destroys or preserves registers. A call will always
+     * destroy {@link HotSpotRuntimeCallTarget#getCallingConvention() its}
+     * {@linkplain CallingConvention#getTemporaries() temporary} registers.
+     */
+    public enum RegisterEffect {
+        DESTROYS_REGISTERS, PRESERVES_REGISTERS
+    }
+
+    /**
      * Sentinel marker for a computed jump address.
      */
     public static final long JUMP_ADDRESS = 0xDEADDEADBEEFBEEFL;
 
     /**
-     * The descriptor of the stub. This is for informational purposes only.
+     * The descriptor of the call.
      */
-    public final Descriptor descriptor;
+    private final Descriptor descriptor;
 
     /**
-     * The entry point address of the stub.
+     * The entry point address of this call's target.
      */
     private long address;
 
@@ -56,17 +71,55 @@
     private Stub stub;
 
     /**
-     * Where the stub gets its arguments and where it places its result.
+     * The calling convention for this call.
      */
     private CallingConvention cc;
 
     private final CompilerToVM vm;
 
-    private final boolean isCRuntimeCall;
+    private final RegisterEffect effect;
+
+    /**
+     * Creates a {@link HotSpotRuntimeCallTarget}.
+     * 
+     * @param descriptor the descriptor of the call
+     * @param address the address of the code to call
+     * @param effect specifies if the call destroys or preserves all registers (apart from
+     *            temporaries which are always destroyed)
+     * @param ccType calling convention type
+     * @param ccProvider calling convention provider
+     * @param vm the Java to HotSpot C/C++ runtime interface
+     */
+    public static HotSpotRuntimeCallTarget create(Descriptor descriptor, long address, RegisterEffect effect, Type ccType, RegisterConfig ccProvider, HotSpotRuntime runtime, CompilerToVM vm) {
+        CallingConvention targetCc = createCallingConvention(descriptor, ccType, ccProvider, runtime);
+        return new HotSpotRuntimeCallTarget(descriptor, address, effect, targetCc, vm);
+    }
 
-    public HotSpotRuntimeCallTarget(Descriptor descriptor, long address, boolean isCRuntimeCall, CallingConvention cc, CompilerToVM vm) {
+    /**
+     * Gets a calling convention for a given descriptor and call type.
+     */
+    public static CallingConvention createCallingConvention(Descriptor descriptor, Type ccType, RegisterConfig ccProvider, HotSpotRuntime runtime) {
+        Class<?>[] argumentTypes = descriptor.getArgumentTypes();
+        JavaType[] parameterTypes = new JavaType[argumentTypes.length];
+        for (int i = 0; i < parameterTypes.length; ++i) {
+            parameterTypes[i] = asJavaType(argumentTypes[i], runtime);
+        }
+        TargetDescription target = graalRuntime().getTarget();
+        JavaType returnType = asJavaType(descriptor.getResultType(), runtime);
+        return ccProvider.getCallingConvention(ccType, returnType, parameterTypes, target, false);
+    }
+
+    private static JavaType asJavaType(Class type, HotSpotRuntime runtime) {
+        if (WordBase.class.isAssignableFrom(type)) {
+            return runtime.lookupJavaType(wordKind().toJavaClass());
+        } else {
+            return runtime.lookupJavaType(type);
+        }
+    }
+
+    public HotSpotRuntimeCallTarget(Descriptor descriptor, long address, RegisterEffect effect, CallingConvention cc, CompilerToVM vm) {
         this.address = address;
-        this.isCRuntimeCall = isCRuntimeCall;
+        this.effect = effect;
         this.descriptor = descriptor;
         this.cc = cc;
         this.vm = vm;
@@ -89,21 +142,23 @@
         return descriptor;
     }
 
-    public void setStub(Stub stub) {
+    public void setCompiledStub(Stub stub) {
         assert address == 0L : "cannot set stub for linkage that already has an address: " + this;
         this.stub = stub;
     }
 
+    /**
+     * Determines if this is a call to a compiled {@linkplain Stub stub}.
+     */
+    public boolean isCompiledStub() {
+        return address == 0L || stub != null;
+    }
+
     public void finalizeAddress(Backend backend) {
         if (address == 0) {
             assert stub != null : "linkage without an address must be a stub - forgot to register a Stub associated with " + descriptor + "?";
             InstalledCode code = stub.getCode(backend);
 
-            AllocatableValue[] argumentLocations = new AllocatableValue[cc.getArgumentCount()];
-            for (int i = 0; i < argumentLocations.length; i++) {
-                argumentLocations[i] = cc.getArgument(i);
-            }
-
             Set<Register> destroyedRegisters = stub.getDestroyedRegisters();
             AllocatableValue[] temporaryLocations = new AllocatableValue[destroyedRegisters.size()];
             int i = 0;
@@ -111,7 +166,7 @@
                 temporaryLocations[i++] = reg.asValue();
             }
             // Update calling convention with temporaries
-            cc = new CallingConvention(temporaryLocations, cc.getStackSize(), cc.getReturn(), argumentLocations);
+            cc = new CallingConvention(temporaryLocations, cc.getStackSize(), cc.getReturn(), cc.getArguments());
             address = code.getStart();
         }
     }
@@ -123,23 +178,6 @@
 
     @Override
     public boolean destroysRegisters() {
-        if (isCRuntimeCall) {
-            // Even though most native ABIs define some callee saved registers,
-            // for simplicity we force the register allocator to save all live
-            // registers across a C runtime call as such calls are only made from
-            // compiled stubs which a) are slow path and b) will typically only
-            // have very few live registers across a C runtime call
-            return true;
-        }
-        // This is a call to a compiled (or assembler) stub which saves
-        // all registers (apart from its temporaries)
-        return false;
-    }
-
-    /**
-     * Determines if this is a link to a C/C++ function in the HotSpot runtime.
-     */
-    public boolean isCRuntimeCall() {
-        return isCRuntimeCall;
+        return effect == DESTROYS_REGISTERS;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed May 15 09:03:43 2013 +0200
@@ -366,18 +366,10 @@
     public int bciProfileWidth;
     public int typeProfileWidth;
 
-    // runtime stubs
     public long inlineCacheMissStub;
     public long handleDeoptStub;
+    public long uncommonTrapStub;
 
-    public long uncommonTrapStub;
-    public long unwindExceptionStub;
-    public long javaTimeMillisStub;
-    public long javaTimeNanosStub;
-    public long arithmeticSinStub;
-    public long arithmeticCosStub;
-    public long arithmeticTanStub;
-    public int deoptReasonNone;
     public long aescryptEncryptBlockStub;
     public long aescryptDecryptBlockStub;
     public long cipherBlockChainingEncryptAESCryptStub;
@@ -403,7 +395,13 @@
     public long vmErrorAddress;
     public long writeBarrierPreAddress;
     public long writeBarrierPostAddress;
+    public long javaTimeMillisAddress;
+    public long javaTimeNanosAddress;
+    public long arithmeticSinAddress;
+    public long arithmeticCosAddress;
+    public long arithmeticTanAddress;
 
+    public int deoptReasonNone;
     public int deoptReasonNullCheck;
     public int deoptReasonRangeCheck;
     public int deoptReasonClassCheck;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed May 15 09:03:43 2013 +0200
@@ -340,6 +340,9 @@
 
     @Override
     public boolean canBeInlined() {
+        if (dontInline) {
+            return false;
+        }
         return graalRuntime().getCompilerToVM().isMethodCompilable(metaspaceMethod);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed May 15 09:03:43 2013 +0200
@@ -26,10 +26,10 @@
 import static com.oracle.graal.api.code.DeoptimizationAction.*;
 import static com.oracle.graal.api.code.MemoryBarriers.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
-import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.wordKind;
+import static com.oracle.graal.hotspot.HotSpotRuntimeCallTarget.RegisterEffect.*;
 import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
@@ -40,7 +40,7 @@
 import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*;
 import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*;
 import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*;
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.IDENTITY_HASHCODE;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
 import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*;
 import static com.oracle.graal.hotspot.stubs.LogObjectStub.*;
@@ -54,8 +54,6 @@
 import static com.oracle.graal.hotspot.stubs.ThreadIsInterruptedStub.*;
 import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*;
 import static com.oracle.graal.hotspot.stubs.VMErrorStub.*;
-import static com.oracle.graal.hotspot.stubs.WriteBarrierPostStub.*;
-import static com.oracle.graal.hotspot.stubs.WriteBarrierPreStub.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
 import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
 import static com.oracle.graal.replacements.Log.*;
@@ -76,6 +74,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.HotSpotRuntimeCallTarget.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
 import com.oracle.graal.hotspot.nodes.*;
@@ -105,8 +104,8 @@
 
     public final HotSpotVMConfig config;
 
-    protected final RegisterConfig regConfig;
-    protected final RegisterConfig globalStubRegConfig;
+    protected final RegisterConfig javaABI;
+    protected final RegisterConfig nativeABI;
     protected final HotSpotGraalRuntime graalRuntime;
 
     private CheckCastSnippets.Templates checkcastSnippets;
@@ -179,312 +178,90 @@
         }
     }
 
-    protected AllocatableValue ret(Kind kind) {
-        if (kind == Kind.Void) {
-            return ILLEGAL;
-        }
-        return globalStubRegConfig.getReturnRegister(kind).asValue(kind);
-    }
-
-    protected AllocatableValue[] javaCallingConvention(Kind... arguments) {
-        return callingConvention(arguments, RuntimeCall);
-    }
-
-    protected AllocatableValue[] nativeCallingConvention(Kind... arguments) {
-        return callingConvention(arguments, NativeCall);
-    }
-
-    private AllocatableValue[] callingConvention(Kind[] arguments, CallingConvention.Type type) {
-        AllocatableValue[] result = new AllocatableValue[arguments.length];
-
-        TargetDescription target = graalRuntime.getTarget();
-        int currentStackOffset = 0;
-        for (int i = 0; i < arguments.length; i++) {
-            Kind kind = arguments[i];
-            Register[] ccRegs = globalStubRegConfig.getCallingConventionRegisters(type, kind);
-            if (i < ccRegs.length) {
-                result[i] = ccRegs[i].asValue(kind);
-            } else {
-                result[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, false);
-                currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize);
-            }
-        }
-        return result;
+    public HotSpotRuntime(HotSpotVMConfig c, HotSpotGraalRuntime graalRuntime) {
+        this.config = c;
+        this.graalRuntime = graalRuntime;
+        javaABI = createRegisterConfig(false);
+        nativeABI = createRegisterConfig(true);
     }
 
-    public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
-        this.config = config;
-        this.graalRuntime = graalRuntime;
-        regConfig = createRegisterConfig(false);
-        globalStubRegConfig = createRegisterConfig(true);
-        Kind word = graalRuntime.getTarget().wordKind;
-
-        // @formatter:off
-
-        addStubCall(VERIFY_OOP,
-                        /*             ret */ ret(Kind.Object),
-                        /* arg0:    object */ javaCallingConvention(Kind.Object));
-
-        addStubCall(OSR_MIGRATION_END,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    buffer */ javaCallingConvention(word));
-
-        addCRuntimeCall(OSR_MIGRATION_END_C, config.osrMigrationEndAddress,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    buffer */ nativeCallingConvention(word));
-
-        addRuntimeCall(UNCOMMON_TRAP, config.uncommonTrapStub,
-                        /*           temps */ null,
-                        /*             ret */ ret(Kind.Void));
-
-        addCRuntimeCall(EXCEPTION_HANDLER_FOR_PC, config.exceptionHandlerForPcAddress,
-                        /*             ret */ ret(word),
-                        /* arg0:    thread */ nativeCallingConvention(word));
-
-        addStubCall(UNWIND_EXCEPTION_TO_CALLER,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0: exception */ javaCallingConvention(Kind.Object,
-                    /* arg1: returnAddress */                       word));
-
-        addCRuntimeCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, config.exceptionHandlerForReturnAddressAddress,
-                        /*             ret */ ret(word),
-                        /* arg0:    thread */ nativeCallingConvention(word,
-                    /* arg1: returnAddress */                         word));
-
-        addStubCall(NEW_ARRAY,
-                        /*             ret */ ret(Kind.Object),
-                        /* arg0:       hub */ javaCallingConvention(word,
-                        /* arg1:    length */ Kind.Int));
-
-        addCRuntimeCall(NEW_ARRAY_C, config.newArrayAddress,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    thread */ nativeCallingConvention(word,
-                        /* arg1:       hub */                         word,
-                        /* arg2:    length */                         Kind.Int));
-
-        addStubCall(NEW_INSTANCE,
-                        /*             ret */ ret(Kind.Object),
-                        /* arg0:       hub */ javaCallingConvention(word));
-
-        addCRuntimeCall(NEW_INSTANCE_C, config.newInstanceAddress,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    thread */ nativeCallingConvention(word,
-                        /* arg1:       hub */                         word));
-
-        addStubCall(NEW_MULTI_ARRAY,
-                        /*             ret */ ret(Kind.Object),
-                        /* arg0:       hub */ javaCallingConvention(word,
-                        /* arg1:      rank */                       Kind.Int,
-                        /* arg2:      dims */                       word));
-
-        addCRuntimeCall(NEW_MULTI_ARRAY_C, config.newMultiArrayAddress,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    thread */ nativeCallingConvention(word,
-                        /* arg1:       hub */                         word,
-                        /* arg2:      rank */                         Kind.Int,
-                        /* arg3:      dims */                         word));
-
-        addRuntimeCall(JAVA_TIME_MILLIS, config.javaTimeMillisStub,
-                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
-                        /*             ret */ ret(Kind.Long));
-
-        addRuntimeCall(JAVA_TIME_NANOS, config.javaTimeNanosStub,
-                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
-                        /*             ret */ ret(Kind.Long));
-
-        addRuntimeCall(ARITHMETIC_SIN, config.arithmeticSinStub,
-                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
-                        /*             ret */ ret(Kind.Double),
-                        /* arg0:     index */ javaCallingConvention(Kind.Double));
-
-        addRuntimeCall(ARITHMETIC_COS, config.arithmeticCosStub,
-                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
-                        /*             ret */ ret(Kind.Double),
-                        /* arg0:     index */ javaCallingConvention(Kind.Double));
-
-        addRuntimeCall(ARITHMETIC_TAN, config.arithmeticTanStub,
-                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
-                        /*             ret */ ret(Kind.Double),
-                        /* arg0:     index */ javaCallingConvention(Kind.Double));
-
-        addStubCall(LOG_PRIMITIVE,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:  typeChar */ javaCallingConvention(Kind.Int,
-                        /* arg1:     value */                       Kind.Long,
-                        /* arg2:   newline */                       Kind.Boolean));
-
-        addCRuntimeCall(LOG_PRIMITIVE_C, config.logPrimitiveAddress,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    thread */ nativeCallingConvention(word,
-                        /* arg1:  typeChar */                         Kind.Char,
-                        /* arg2:     value */                         Kind.Long,
-                        /* arg3:   newline */                         Kind.Boolean));
-
-        addStubCall(LOG_PRINTF,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    format */ javaCallingConvention(Kind.Object,
-                        /* arg1:     value */                       Kind.Long,
-                        /* arg2:     value */                       Kind.Long,
-                        /* arg3:     value */                       Kind.Long));
-
-        addCRuntimeCall(LOG_PRINTF_C, config.logObjectAddress,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    thread */ nativeCallingConvention(word,
-                        /* arg1:    format */                         Kind.Object,
-                        /* arg2:        v1 */                         Kind.Long,
-                        /* arg3:        v2 */                         Kind.Long,
-                        /* arg4:        v3 */                         Kind.Long));
-
-        addCRuntimeCall(VM_MESSAGE_C, config.vmMessageAddress,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:   vmError */ nativeCallingConvention(Kind.Boolean,
-                        /* arg1:    format */                         word,
-                        /* arg2:     value */                         Kind.Long,
-                        /* arg3:     value */                         Kind.Long,
-                        /* arg4:     value */                         Kind.Long));
-
-        addStubCall(LOG_OBJECT,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    object */ javaCallingConvention(Kind.Object,
-                        /* arg1:     flags */                       Kind.Int));
-
-        addCRuntimeCall(LOG_OBJECT_C, config.logObjectAddress,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0:    thread */ nativeCallingConvention(word,
-                        /* arg1:    object */                         Kind.Object,
-                        /* arg2:     flags */                         Kind.Int));
-
-        addStubCall(THREAD_IS_INTERRUPTED,
-                        /*             ret */ ret(Kind.Boolean),
-                        /* arg0:    thread */ javaCallingConvention(Kind.Object,
-                 /* arg1: clearInterrupted */                       Kind.Boolean));
-
-        addCRuntimeCall(THREAD_IS_INTERRUPTED_C, config.threadIsInterruptedAddress,
-                        /*             ret */ ret(Kind.Boolean),
-                        /* arg0:    thread */ nativeCallingConvention(word,
-                   /* arg1: receiverThread */                         Kind.Object,
-              /* arg1: clearInterrupted */                            Kind.Boolean));
-
-        addRuntimeCall(DEOPT_HANDLER, config.handleDeoptStub,
-                        /*           temps */ null,
-                        /*             ret */ ret(Kind.Void));
-
-        addRuntimeCall(IC_MISS_HANDLER, config.inlineCacheMissStub,
-                        /*           temps */ null,
-                        /*             ret */ ret(Kind.Void));
-
-        addStubCall(VM_ERROR,
-                        /*          ret */ ret(Kind.Void),
-                        /* arg0:  where */ javaCallingConvention(Kind.Object,
-                        /* arg1: format */                       Kind.Object,
-                        /* arg2:  value */                       Kind.Long));
-
-        addCRuntimeCall(VM_ERROR_C, config.vmErrorAddress,
-                        /*          ret */ ret(Kind.Void),
-                        /* arg0: thread */ nativeCallingConvention(word,
-                        /* arg0:  where */                         Kind.Object,
-                        /* arg1: format */                         Kind.Object,
-                        /* arg2:  value */                         Kind.Long));
-
-        addStubCall(WRITE_BARRIER_PRE,
-                        /*          ret */ ret(Kind.Void),
-                        /* arg0: object */ javaCallingConvention(Kind.Object));
-
-        addCRuntimeCall(WRITE_BARRIER_PRE_C, config.writeBarrierPreAddress,
-                        /*          ret */ ret(Kind.Void),
-                        /* arg0: thread */ nativeCallingConvention(word,
-                        /* arg1: object */                         Kind.Object));
-
-        addStubCall(WRITE_BARRIER_POST,
-                        /*          ret */ ret(Kind.Void),
-                        /* arg0: object */ javaCallingConvention(Kind.Object,
-                        /* arg1:   card */                       word));
-
-        addCRuntimeCall(WRITE_BARRIER_POST_C, config.writeBarrierPostAddress,
-                        /*          ret */ ret(Kind.Void),
-                        /* arg0: thread */ nativeCallingConvention(word,
-                        /* arg1: object */                         Kind.Object,
-                        /* arg2:   card */                         word));
-        // @formatter:on
+    protected HotSpotRuntimeCallTarget register(HotSpotRuntimeCallTarget call) {
+        HotSpotRuntimeCallTarget oldValue = runtimeCalls.put(call.getDescriptor(), call);
+        assert oldValue == null;
+        return call;
     }
 
     /**
-     * Registers the details for linking a call to a compiled {@link Stub}.
-     * 
-     * @param descriptor name and signature of the call
-     * @param ret where the call returns its result
-     * @param args where arguments are passed to the call
+     * Registers the details for linking a call to a {@link Stub}.
      */
-    protected RuntimeCallTarget addStubCall(Descriptor descriptor, AllocatableValue ret, AllocatableValue... args) {
-        return addRuntimeCall(descriptor, 0L, null, ret, args);
-    }
-
-    /**
-     * Registers the details for a jump to a target that has a signature (i.e. expects arguments in
-     * specified locations).
-     * 
-     * @param descriptor name and signature of the jump target
-     * @param args where arguments are passed to the call
-     */
-    protected RuntimeCallTarget addJump(Descriptor descriptor, AllocatableValue... args) {
-        return addRuntimeCall(descriptor, HotSpotRuntimeCallTarget.JUMP_ADDRESS, null, ret(Kind.Void), args);
+    protected RuntimeCallTarget registerStubCall(Descriptor descriptor) {
+        return register(HotSpotRuntimeCallTarget.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, javaABI, this, graalRuntime.getCompilerToVM()));
     }
 
     /**
      * Registers the details for a call to a runtime C/C++ function.
-     * 
-     * @param descriptor name and signature of the call
-     * @param args where arguments are passed to the call
      */
-    protected RuntimeCallTarget addCRuntimeCall(Descriptor descriptor, long address, AllocatableValue ret, AllocatableValue... args) {
-        assert descriptor.getResultType().isPrimitive() || Word.class.isAssignableFrom(descriptor.getResultType()) : "C runtime call cannot have Object return type - objects must be returned via thread local storage: " +
-                        descriptor;
-        return addRuntimeCall(descriptor, address, true, null, ret, args);
+    protected RuntimeCallTarget registerCRuntimeCall(Descriptor descriptor, long address) {
+        Class<?> resultType = descriptor.getResultType();
+        assert resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "C runtime call must return object thread local storage: " + descriptor;
+        return register(HotSpotRuntimeCallTarget.create(descriptor, address, DESTROYS_REGISTERS, NativeCall, nativeABI, this, graalRuntime.getCompilerToVM()));
     }
 
-    protected RuntimeCallTarget addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, AllocatableValue ret, AllocatableValue... args) {
-        return addRuntimeCall(descriptor, address, false, tempRegs, ret, args);
+    /**
+     * Registers the details for a call to a stub that never returns.
+     */
+    protected RuntimeCallTarget registerNoReturnStub(Descriptor descriptor, long address, CallingConvention.Type ccType) {
+        return register(HotSpotRuntimeCallTarget.create(descriptor, address, PRESERVES_REGISTERS, ccType, javaABI, this, graalRuntime.getCompilerToVM()));
     }
 
     /**
-     * Registers the details for linking a runtime call.
-     * 
-     * @param descriptor name and signature of the call
-     * @param address target address of the call
-     * @param tempRegs temporary registers used (and killed) by the call (null if none)
-     * @param ret where the call returns its result
-     * @param args where arguments are passed to the call
+     * Registers the details for a call to a leaf function. A leaf function does not lock, GC or
+     * throw exceptions. That is, the thread's execution state during the call is never inspected by
+     * another thread.
      */
-    protected RuntimeCallTarget addRuntimeCall(Descriptor descriptor, long address, boolean isCRuntimeCall, Register[] tempRegs, AllocatableValue ret, AllocatableValue... args) {
-        AllocatableValue[] temps = tempRegs == null || tempRegs.length == 0 ? AllocatableValue.NONE : new AllocatableValue[tempRegs.length];
-        for (int i = 0; i < temps.length; i++) {
-            temps[i] = tempRegs[i].asValue();
-        }
-        assert checkAssignable(descriptor.getResultType(), ret) : descriptor + " incompatible with result location " + ret;
-        Class[] argTypes = descriptor.getArgumentTypes();
-        assert argTypes.length == args.length : descriptor + " incompatible with number of argument locations: " + args.length;
-        for (int i = 0; i < argTypes.length; i++) {
-            assert checkAssignable(argTypes[i], args[i]) : descriptor + " incompatible with argument location " + i + ": " + args[i];
-        }
-        HotSpotRuntimeCallTarget runtimeCall = new HotSpotRuntimeCallTarget(descriptor, address, isCRuntimeCall, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM());
-        runtimeCalls.put(descriptor, runtimeCall);
-        return runtimeCall;
+    protected RuntimeCallTarget registerLeafCall(Descriptor descriptor, long address, CallingConvention.Type ccType, RegisterEffect effect) {
+        return register(HotSpotRuntimeCallTarget.create(descriptor, address, effect, ccType, javaABI, this, graalRuntime.getCompilerToVM()));
     }
 
-    private boolean checkAssignable(Class spec, Value value) {
-        Kind kind = value.getKind();
-        if (kind == Kind.Illegal) {
-            kind = Kind.Void;
-        }
-        if (WordBase.class.isAssignableFrom(spec)) {
-            return kind == graalRuntime.getTarget().wordKind;
-        }
-        return kind == Kind.fromJavaClass(spec);
-    }
-
-    protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig);
+    protected abstract RegisterConfig createRegisterConfig(boolean isNative);
 
     public void registerReplacements(Replacements replacements) {
+        registerStubCall(VERIFY_OOP);
+        registerStubCall(OSR_MIGRATION_END);
+        registerStubCall(NEW_ARRAY);
+        registerStubCall(UNWIND_EXCEPTION_TO_CALLER);
+        registerStubCall(NEW_INSTANCE);
+        registerStubCall(NEW_MULTI_ARRAY);
+        registerStubCall(LOG_PRIMITIVE);
+        registerStubCall(LOG_PRINTF);
+        registerStubCall(LOG_OBJECT);
+        registerStubCall(THREAD_IS_INTERRUPTED);
+        registerStubCall(VM_ERROR);
+
+        HotSpotVMConfig c = config;
+        registerNoReturnStub(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall);
+        registerNoReturnStub(DEOPT_HANDLER, c.handleDeoptStub, NativeCall);
+        registerNoReturnStub(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall);
+
+        registerLeafCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS);
+        registerLeafCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS);
+        registerLeafCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS);
+        registerLeafCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS);
+        registerLeafCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS);
+
+        registerCRuntimeCall(OSR_MIGRATION_END_C, c.osrMigrationEndAddress);
+        registerCRuntimeCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress);
+        registerCRuntimeCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress);
+        registerCRuntimeCall(NEW_ARRAY_C, c.newArrayAddress);
+        registerCRuntimeCall(NEW_INSTANCE_C, c.newInstanceAddress);
+        registerCRuntimeCall(NEW_MULTI_ARRAY_C, c.newMultiArrayAddress);
+        registerCRuntimeCall(LOG_PRIMITIVE_C, c.logPrimitiveAddress);
+        registerCRuntimeCall(LOG_PRINTF_C, c.logObjectAddress);
+        registerCRuntimeCall(VM_MESSAGE_C, c.vmMessageAddress);
+        registerCRuntimeCall(LOG_OBJECT_C, c.logObjectAddress);
+        registerCRuntimeCall(THREAD_IS_INTERRUPTED_C, c.threadIsInterruptedAddress);
+        registerCRuntimeCall(VM_ERROR_C, c.vmErrorAddress);
+
         if (GraalOptions.IntrinsifyObjectMethods) {
             replacements.registerSubstitutions(ObjectSubstitutions.class);
         }
@@ -516,20 +293,19 @@
         boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget());
         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget());
 
-        link(new NewInstanceStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_INSTANCE)));
-        link(new NewArrayStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_ARRAY)));
-        link(new NewMultiArrayStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_MULTI_ARRAY)));
-        link(new ThreadIsInterruptedStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(THREAD_IS_INTERRUPTED)));
-        link(new ExceptionHandlerStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(EXCEPTION_HANDLER)));
-        link(new UnwindExceptionToCallerStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(UNWIND_EXCEPTION_TO_CALLER)));
-        link(new VerifyOopStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(VERIFY_OOP)));
-        link(new OSRMigrationEndStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(OSR_MIGRATION_END)));
-        link(new LogPrimitiveStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_PRIMITIVE)));
-        link(new LogObjectStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_OBJECT)));
-        link(new LogPrintfStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_PRINTF)));
-        link(new VMErrorStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(VM_ERROR)));
-        link(new WriteBarrierPreStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(WRITE_BARRIER_PRE)));
-        link(new WriteBarrierPostStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(WRITE_BARRIER_POST)));
+        TargetDescription target = getTarget();
+        link(new NewInstanceStub(this, replacements, target, runtimeCalls.get(NEW_INSTANCE)));
+        link(new NewArrayStub(this, replacements, target, runtimeCalls.get(NEW_ARRAY)));
+        link(new NewMultiArrayStub(this, replacements, target, runtimeCalls.get(NEW_MULTI_ARRAY)));
+        link(new ThreadIsInterruptedStub(this, replacements, target, runtimeCalls.get(THREAD_IS_INTERRUPTED)));
+        link(new ExceptionHandlerStub(this, replacements, target, runtimeCalls.get(EXCEPTION_HANDLER)));
+        link(new UnwindExceptionToCallerStub(this, replacements, target, runtimeCalls.get(UNWIND_EXCEPTION_TO_CALLER)));
+        link(new VerifyOopStub(this, replacements, target, runtimeCalls.get(VERIFY_OOP)));
+        link(new OSRMigrationEndStub(this, replacements, target, runtimeCalls.get(OSR_MIGRATION_END)));
+        link(new LogPrimitiveStub(this, replacements, target, runtimeCalls.get(LOG_PRIMITIVE)));
+        link(new LogObjectStub(this, replacements, target, runtimeCalls.get(LOG_OBJECT)));
+        link(new LogPrintfStub(this, replacements, target, runtimeCalls.get(LOG_PRINTF)));
+        link(new VMErrorStub(this, replacements, target, runtimeCalls.get(VM_ERROR)));
 
         linkRuntimeCall(IDENTITY_HASHCODE, config.identityHashCodeAddress, replacements);
         linkRuntimeCall(REGISTER_FINALIZER, config.registerFinalizerAddress, replacements);
@@ -537,17 +313,19 @@
         linkRuntimeCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, config.createOutOfBoundsExceptionAddress, replacements);
         linkRuntimeCall(MONITORENTER, config.monitorenterAddress, replacements);
         linkRuntimeCall(MONITOREXIT, config.monitorexitAddress, replacements);
+        linkRuntimeCall(WRITE_BARRIER_PRE, config.writeBarrierPreAddress, replacements);
+        linkRuntimeCall(WRITE_BARRIER_POST, config.writeBarrierPostAddress, replacements);
     }
 
     private static void link(Stub stub) {
-        stub.getLinkage().setStub(stub);
+        stub.getLinkage().setCompiledStub(stub);
     }
 
     private void linkRuntimeCall(Descriptor descriptor, long address, Replacements replacements) {
-        RuntimeCallStub stub = new RuntimeCallStub(address, descriptor, true, this, replacements, globalStubRegConfig, graalRuntime.getCompilerToVM());
+        RuntimeCallStub stub = new RuntimeCallStub(address, descriptor, true, this, replacements, nativeABI, graalRuntime.getCompilerToVM());
         HotSpotRuntimeCallTarget linkage = stub.getLinkage();
         HotSpotRuntimeCallTarget targetLinkage = stub.getTargetLinkage();
-        linkage.setStub(stub);
+        linkage.setCompiledStub(stub);
         runtimeCalls.put(linkage.getDescriptor(), linkage);
         runtimeCalls.put(targetLinkage.getDescriptor(), targetLinkage);
     }
@@ -575,7 +353,7 @@
         if (compResult != null) {
             HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
             addExceptionHandlersComment(compResult, hcf);
-            Register fp = regConfig.getFrameRegister();
+            Register fp = javaABI.getFrameRegister();
             RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0);
             for (Infopoint infopoint : compResult.getInfopoints()) {
                 if (infopoint instanceof Call) {
@@ -679,7 +457,7 @@
 
     @Override
     public RegisterConfig lookupRegisterConfig() {
-        return regConfig;
+        return javaABI;
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Wed May 15 09:03:43 2013 +0200
@@ -47,7 +47,7 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorEnterStubCall.MONITORENTER);
+        RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MONITORENTER);
         gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object), gen.operand(lock));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java	Wed May 15 09:03:43 2013 +0200
@@ -26,13 +26,12 @@
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
- * Node implementing a call to {@link WriteBarrierPostStub}.
+ * A call to {@code GraalRuntime::write_barrier_post}.
  */
 public class WriteBarrierPostStubCall extends FixedWithNextNode implements LIRGenLowerable {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java	Wed May 15 09:03:43 2013 +0200
@@ -26,12 +26,11 @@
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
- * Node implementing a call to {@link WriteBarrierPreStub}.
+ * A call to {@code GraalRuntime::write_barrier_pre}.
  */
 public class WriteBarrierPreStubCall extends FixedWithNextNode implements LIRGenLowerable {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Wed May 15 09:03:43 2013 +0200
@@ -0,0 +1,283 @@
+/*
+ * 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.hotspot.replacements;
+
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+
+import com.oracle.graal.api.meta.Constant;
+import com.oracle.graal.api.meta.JavaType;
+import com.oracle.graal.api.meta.ResolvedJavaField;
+import com.oracle.graal.api.meta.ResolvedJavaMethod;
+import com.oracle.graal.api.meta.ResolvedJavaType;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.graph.NodeInputList;
+import com.oracle.graal.hotspot.meta.HotSpotResolvedJavaMethod;
+import com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType;
+import com.oracle.graal.hotspot.meta.HotSpotSignature;
+import com.oracle.graal.nodes.CallTargetNode;
+import com.oracle.graal.nodes.Invoke;
+import com.oracle.graal.nodes.InvokeNode;
+import com.oracle.graal.nodes.PiNode;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.java.MethodCallTargetNode;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.java.SelfReplacingMethodCallTargetNode;
+import com.oracle.graal.nodes.spi.Canonicalizable;
+import com.oracle.graal.nodes.type.StampFactory;
+import com.oracle.graal.replacements.nodes.MacroNode;
+
+/**
+ * Common base class for method handle invoke nodes.
+ */
+public abstract class AbstractMethodHandleNode extends MacroNode implements Canonicalizable {
+
+    private static final ResolvedJavaField methodHandleFormField;
+    private static final ResolvedJavaField lambdaFormVmentryField;
+    private static final ResolvedJavaField memberNameClazzField;
+    private static final ResolvedJavaField memberNameVmtargetField;
+
+    // Replacement method data
+    private ResolvedJavaMethod replacementTargetMethod;
+    private JavaType replacementReturnType;
+    @Input private NodeInputList<ValueNode> replacementArguments;
+
+    /**
+     * Search for an instance field with the given name in a class.
+     * 
+     * @param className name of the class to search in
+     * @param fieldName name of the field to be searched
+     * @return resolved java field
+     * @throws ClassNotFoundException
+     */
+    private static ResolvedJavaField findFieldInClass(String className, String fieldName) throws ClassNotFoundException {
+        Class<?> clazz = Class.forName(className);
+        ResolvedJavaType type = HotSpotResolvedObjectType.fromClass(clazz);
+        ResolvedJavaField[] fields = type.getInstanceFields(false);
+        for (ResolvedJavaField field : fields) {
+            if (field.getName().equals(fieldName)) {
+                return field;
+            }
+        }
+        return null;
+    }
+
+    static {
+        try {
+            methodHandleFormField = findFieldInClass("java.lang.invoke.MethodHandle", "form");
+            lambdaFormVmentryField = findFieldInClass("java.lang.invoke.LambdaForm", "vmentry");
+            memberNameClazzField = findFieldInClass("java.lang.invoke.MemberName", "clazz");
+            memberNameVmtargetField = findFieldInClass("java.lang.invoke.MemberName", "vmtarget");
+        } catch (ClassNotFoundException | SecurityException ex) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public AbstractMethodHandleNode(Invoke invoke) {
+        super(invoke);
+
+        // See if we need to save some replacement method data.
+        CallTargetNode callTarget = invoke.callTarget();
+        if (callTarget instanceof SelfReplacingMethodCallTargetNode) {
+            SelfReplacingMethodCallTargetNode selfReplacingMethodCallTargetNode = (SelfReplacingMethodCallTargetNode) callTarget;
+            replacementTargetMethod = selfReplacingMethodCallTargetNode.replacementTargetMethod();
+            replacementReturnType = selfReplacingMethodCallTargetNode.replacementReturnType();
+            replacementArguments = selfReplacingMethodCallTargetNode.replacementArguments();
+        } else {
+            // NodeInputList can't be null.
+            replacementArguments = new NodeInputList<>(this);
+        }
+    }
+
+    /**
+     * Get the receiver of a MethodHandle.invokeBasic call.
+     * 
+     * @return the receiver argument node
+     */
+    private ValueNode getReceiver() {
+        return arguments.first();
+    }
+
+    /**
+     * Get the MemberName argument of a MethodHandle.linkTo* call.
+     * 
+     * @return the MemberName argument node (which is the last argument)
+     */
+    private ValueNode getMemberName() {
+        return arguments.last();
+    }
+
+    /**
+     * Used from {@link MethodHandleInvokeBasicNode} to get the target {@link InvokeNode} if the
+     * method handle receiver is constant.
+     * 
+     * @return invoke node for the {@link java.lang.invoke.MethodHandle} target
+     */
+    protected InvokeNode getInvokeBasicTarget() {
+        ValueNode methodHandleNode = getReceiver();
+        if (methodHandleNode.isConstant() && !methodHandleNode.isNullConstant()) {
+            // Get the data we need from MethodHandle.LambdaForm.MemberName
+            Constant methodHandle = methodHandleNode.asConstant();
+            Constant lambdaForm = methodHandleFormField.readValue(methodHandle);
+            Constant memberName = lambdaFormVmentryField.readValue(lambdaForm);
+            return getTargetInvokeNode(memberName);
+        }
+        return null;
+    }
+
+    /**
+     * Used from {@link MethodHandleLinkToStaticNode}, {@link MethodHandleLinkToSpecialNode},
+     * {@link MethodHandleLinkToVirtualNode}, and {@link MethodHandleLinkToInterfaceNode} to get the
+     * target {@link InvokeNode} if the member name argument is constant.
+     * 
+     * @return invoke node for the member name target
+     */
+    protected InvokeNode getLinkToTarget() {
+        ValueNode memberNameNode = getMemberName();
+        if (memberNameNode.isConstant() && !memberNameNode.isNullConstant()) {
+            Constant memberName = memberNameNode.asConstant();
+            return getTargetInvokeNode(memberName);
+        }
+        return null;
+    }
+
+    /**
+     * Helper function to get the {@link InvokeNode} for the vmtarget of a
+     * java.lang.invoke.MemberName.
+     * 
+     * @param memberName constant member name node
+     * @return invoke node for the member name target
+     */
+    private InvokeNode getTargetInvokeNode(Constant memberName) {
+        // Get the data we need from MemberName
+        Constant clazz = memberNameClazzField.readValue(memberName);
+        Constant vmtarget = memberNameVmtargetField.readValue(memberName);
+
+        // Create a method from the vmtarget pointer
+        Class<?> c = (Class<?>) clazz.asObject();
+        HotSpotResolvedObjectType holderClass = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
+        HotSpotResolvedJavaMethod targetMethod = holderClass.createMethod(vmtarget.asLong());
+
+        // In lamda forms we erase signature types to avoid resolving issues
+        // involving class loaders. When we optimize a method handle invoke
+        // to a direct call we must cast the receiver and arguments to its
+        // actual types.
+        HotSpotSignature signature = targetMethod.getSignature();
+        final boolean isStatic = Modifier.isStatic(targetMethod.getModifiers());
+        final int receiverSkip = isStatic ? 0 : 1;
+
+        // Cast receiver to its type.
+        if (!isStatic) {
+            JavaType receiverType = holderClass;
+            maybeCastArgument(0, receiverType);
+        }
+
+        // Cast reference arguments to its type.
+        for (int index = 0; index < signature.getParameterCount(false); index++) {
+            JavaType parameterType = signature.getParameterType(index, holderClass);
+            maybeCastArgument(receiverSkip + index, parameterType);
+        }
+
+        // Try to get the most accurate receiver type
+        if (this instanceof MethodHandleLinkToVirtualNode || this instanceof MethodHandleLinkToInterfaceNode) {
+            ResolvedJavaType receiverType = getReceiver().objectStamp().type();
+            if (receiverType != null) {
+                ResolvedJavaMethod concreteMethod = receiverType.findUniqueConcreteMethod(targetMethod);
+                if (concreteMethod != null) {
+                    return createTargetInvokeNode(concreteMethod);
+                }
+            }
+        }
+
+        if (targetMethod.canBeStaticallyBound()) {
+            return createTargetInvokeNode(targetMethod);
+        }
+
+        ResolvedJavaMethod concreteMethod = targetMethod.uniqueConcreteMethod();
+        if (concreteMethod != null) {
+            return createTargetInvokeNode(concreteMethod);
+        }
+
+        return null;
+    }
+
+    /**
+     * Inserts a node to cast the argument at index to the given type if the given type is more
+     * concrete than the argument type.
+     * 
+     * @param index of the argument to be cast
+     * @param type the type the argument should be cast to
+     */
+    private void maybeCastArgument(int index, JavaType type) {
+        if (type instanceof ResolvedJavaType) {
+            ResolvedJavaType targetType = (ResolvedJavaType) type;
+            if (!targetType.isPrimitive()) {
+                ValueNode argument = arguments.get(index);
+                ResolvedJavaType argumentType = argument.objectStamp().type();
+                if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) {
+                    PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType)));
+                    arguments.set(index, piNode);
+                }
+            }
+        }
+    }
+
+    /**
+     * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed
+     * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}.
+     * 
+     * @param targetMethod the method the be called
+     * @return invoke node for the member name target
+     */
+    private InvokeNode createTargetInvokeNode(ResolvedJavaMethod targetMethod) {
+        InvokeKind invokeKind = Modifier.isStatic(targetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special;
+        JavaType returnType = targetMethod.getSignature().getReturnType(null);
+
+        // MethodHandleLinkTo* nodes have a trailing MemberName argument which
+        // needs to be popped.
+        ValueNode[] originalArguments = arguments.toArray(new ValueNode[arguments.size()]);
+        ValueNode[] targetArguments;
+        if (this instanceof MethodHandleInvokeBasicNode) {
+            targetArguments = originalArguments;
+        } else {
+            assert this instanceof MethodHandleLinkToStaticNode || this instanceof MethodHandleLinkToSpecialNode || this instanceof MethodHandleLinkToVirtualNode ||
+                            this instanceof MethodHandleLinkToInterfaceNode : this;
+            targetArguments = Arrays.copyOfRange(originalArguments, 0, arguments.size() - 1);
+        }
+
+        // If there is already replacement information, use that instead.
+        MethodCallTargetNode callTarget;
+        if (replacementTargetMethod == null) {
+            callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, getTargetMethod(), originalArguments, getReturnType());
+        } else {
+            ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]);
+            callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType);
+        }
+
+        graph().add(callTarget);
+        InvokeNode invoke = graph().add(new InvokeNode(callTarget, getBci()));
+        invoke.setStateAfter(stateAfter());
+        return invoke;
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java	Wed May 15 09:03:43 2013 +0200
@@ -22,17 +22,29 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
 
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.nodes.Invoke;
+import com.oracle.graal.nodes.InvokeNode;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.spi.CanonicalizerTool;
 
 /**
  * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}.
  */
-public class MethodHandleInvokeBasicNode extends MacroNode {
+public class MethodHandleInvokeBasicNode extends AbstractMethodHandleNode {
 
     public MethodHandleInvokeBasicNode(Invoke invoke) {
         super(invoke);
     }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        InvokeNode invoke = getInvokeBasicTarget();
+        if (invoke != null) {
+            return invoke;
+        }
+        return this;
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java	Wed May 15 09:03:43 2013 +0200
@@ -22,17 +22,29 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
 
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.nodes.Invoke;
+import com.oracle.graal.nodes.InvokeNode;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.spi.CanonicalizerTool;
 
 /**
  * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}.
  */
-public class MethodHandleLinkToInterfaceNode extends MacroNode {
+public class MethodHandleLinkToInterfaceNode extends AbstractMethodHandleNode {
 
     public MethodHandleLinkToInterfaceNode(Invoke invoke) {
         super(invoke);
     }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        InvokeNode invoke = getLinkToTarget();
+        if (invoke != null) {
+            return invoke;
+        }
+        return this;
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java	Wed May 15 09:03:43 2013 +0200
@@ -22,17 +22,29 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
 
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.nodes.Invoke;
+import com.oracle.graal.nodes.InvokeNode;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.spi.CanonicalizerTool;
 
 /**
  * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}.
  */
-public class MethodHandleLinkToSpecialNode extends MacroNode {
+public class MethodHandleLinkToSpecialNode extends AbstractMethodHandleNode {
 
     public MethodHandleLinkToSpecialNode(Invoke invoke) {
         super(invoke);
     }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        InvokeNode invoke = getLinkToTarget();
+        if (invoke != null) {
+            return invoke;
+        }
+        return this;
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java	Wed May 15 09:03:43 2013 +0200
@@ -22,17 +22,29 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
 
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.nodes.Invoke;
+import com.oracle.graal.nodes.InvokeNode;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.spi.CanonicalizerTool;
 
 /**
  * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}.
  */
-public class MethodHandleLinkToStaticNode extends MacroNode {
+public class MethodHandleLinkToStaticNode extends AbstractMethodHandleNode {
 
     public MethodHandleLinkToStaticNode(Invoke invoke) {
         super(invoke);
     }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        InvokeNode invoke = getLinkToTarget();
+        if (invoke != null) {
+            return invoke;
+        }
+        return this;
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java	Wed May 15 09:03:43 2013 +0200
@@ -22,17 +22,29 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
 
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.nodes.Invoke;
+import com.oracle.graal.nodes.InvokeNode;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.spi.CanonicalizerTool;
 
 /**
  * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}.
  */
-public class MethodHandleLinkToVirtualNode extends MacroNode {
+public class MethodHandleLinkToVirtualNode extends AbstractMethodHandleNode {
 
     public MethodHandleLinkToVirtualNode(Invoke invoke) {
         super(invoke);
     }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        InvokeNode invoke = getLinkToTarget();
+        if (invoke != null) {
+            return invoke;
+        }
+        return this;
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java	Wed May 15 09:03:43 2013 +0200
@@ -22,23 +22,24 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
+import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.HotSpotRuntimeCallTarget.RegisterEffect.*;
 
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -79,12 +80,11 @@
      * @param vm the Java to HotSpot C/C++ runtime interface
      */
     public RuntimeCallStub(long address, Descriptor sig, boolean prependThread, HotSpotRuntime runtime, Replacements replacements, RegisterConfig regConfig, CompilerToVM vm) {
-        super(runtime, replacements, new HotSpotRuntimeCallTarget(sig, 0L, false, createCallingConvention(runtime, regConfig, sig), vm));
+        super(runtime, replacements, HotSpotRuntimeCallTarget.create(sig, 0L, PRESERVES_REGISTERS, JavaCallee, regConfig, runtime, vm));
         this.prependThread = prependThread;
         Class[] targetParameterTypes = createTargetParameters(sig);
         Descriptor targetSig = new Descriptor(sig.getName() + ":C", sig.hasSideEffect(), sig.getResultType(), targetParameterTypes);
-        CallingConvention targetCc = createCallingConvention(runtime, regConfig, targetSig);
-        target = new HotSpotRuntimeCallTarget(targetSig, address, true, targetCc, vm);
+        target = HotSpotRuntimeCallTarget.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, regConfig, runtime, vm);
     }
 
     /**
@@ -94,21 +94,6 @@
         return target;
     }
 
-    private static CallingConvention createCallingConvention(HotSpotRuntime runtime, RegisterConfig regConfig, Descriptor d) {
-        Class<?>[] argumentTypes = d.getArgumentTypes();
-        JavaType[] parameterTypes = new JavaType[argumentTypes.length];
-        for (int i = 0; i < parameterTypes.length; ++i) {
-            if (WordBase.class.isAssignableFrom(argumentTypes[i])) {
-                parameterTypes[i] = runtime.lookupJavaType(wordKind().toJavaClass());
-            } else {
-                parameterTypes[i] = runtime.lookupJavaType(argumentTypes[i]);
-            }
-        }
-        TargetDescription target = graalRuntime().getTarget();
-        JavaType returnType = runtime.lookupJavaType(d.getResultType());
-        return regConfig.getCallingConvention(Type.NativeCall, returnType, parameterTypes, target, false);
-    }
-
     private Class[] createTargetParameters(Descriptor sig) {
         Class[] parameters = sig.getArgumentTypes();
         if (prependThread) {
@@ -130,7 +115,7 @@
         return new JavaMethod() {
 
             public Signature getSignature() {
-                Descriptor d = linkage.descriptor;
+                Descriptor d = linkage.getDescriptor();
                 Class<?>[] arguments = d.getArgumentTypes();
                 JavaType[] parameters = new JavaType[arguments.length];
                 for (int i = 0; i < arguments.length; i++) {
@@ -140,7 +125,7 @@
             }
 
             public String getName() {
-                return linkage.descriptor.getName();
+                return linkage.getDescriptor().getName();
             }
 
             public JavaType getDeclaringClass() {
@@ -165,19 +150,19 @@
         final StructuredGraph graph;
         private FixedWithNextNode lastFixedNode;
 
-        <T extends Node> T add(T node) {
+        <T extends FloatingNode> T add(T node) {
+            return graph.unique(node);
+        }
+
+        <T extends FixedNode> T append(T node) {
             T result = graph.add(node);
-            assert node == result;
-            if (result instanceof FixedNode) {
-                assert lastFixedNode != null;
-                FixedNode fixed = (FixedNode) result;
-                assert fixed.predecessor() == null;
-                graph.addAfterFixed(lastFixedNode, fixed);
-                if (fixed instanceof FixedWithNextNode) {
-                    lastFixedNode = (FixedWithNextNode) fixed;
-                } else {
-                    lastFixedNode = null;
-                }
+            assert lastFixedNode != null;
+            assert result.predecessor() == null;
+            graph.addAfterFixed(lastFixedNode, result);
+            if (result instanceof FixedWithNextNode) {
+                lastFixedNode = (FixedWithNextNode) result;
+            } else {
+                lastFixedNode = null;
             }
             return result;
         }
@@ -187,19 +172,17 @@
     protected StructuredGraph getGraph() {
         Class<?>[] args = linkage.getDescriptor().getArgumentTypes();
         boolean isObjectResult = linkage.getCallingConvention().getReturn().getKind() == Kind.Object;
-
         GraphBuilder builder = new GraphBuilder(this);
-
         LocalNode[] locals = createLocals(builder, args);
 
-        ReadRegisterNode thread = prependThread || isObjectResult ? builder.add(new ReadRegisterNode(runtime.threadRegister(), true, false)) : null;
+        ReadRegisterNode thread = prependThread || isObjectResult ? builder.append(new ReadRegisterNode(runtime.threadRegister(), true, false)) : null;
         ValueNode result = createTargetCall(builder, locals, thread);
         createInvoke(builder, StubUtil.class, "handlePendingException", ConstantNode.forBoolean(isObjectResult, builder.graph));
         if (isObjectResult) {
             InvokeNode object = createInvoke(builder, HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
             result = createInvoke(builder, StubUtil.class, "verifyObject", object);
         }
-        builder.add(new ReturnNode(linkage.descriptor.getResultType() == void.class ? null : result));
+        builder.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
 
         if (Debug.isDumpEnabled()) {
             Debug.dump(builder.graph, "Initial stub graph");
@@ -245,8 +228,8 @@
         }
         assert method != null : "did not find method in " + declaringClass + " named " + name;
         JavaType returnType = method.getSignature().getReturnType(null);
-        MethodCallTargetNode callTarget = builder.add(new MethodCallTargetNode(InvokeKind.Static, method, hpeArgs, returnType));
-        InvokeNode invoke = builder.add(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI));
+        MethodCallTargetNode callTarget = builder.graph.add(new MethodCallTargetNode(InvokeKind.Static, method, hpeArgs, returnType));
+        InvokeNode invoke = builder.append(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI));
         return invoke;
     }
 
@@ -255,9 +238,9 @@
             ValueNode[] targetArguments = new ValueNode[1 + locals.length];
             targetArguments[0] = thread;
             System.arraycopy(locals, 0, targetArguments, 1, locals.length);
-            return builder.add(new CRuntimeCall(target.descriptor, targetArguments));
+            return builder.append(new CRuntimeCall(target.getDescriptor(), targetArguments));
         } else {
-            return builder.add(new CRuntimeCall(target.descriptor, locals));
+            return builder.append(new CRuntimeCall(target.getDescriptor(), locals));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/WriteBarrierPostStub.java	Wed May 15 09:03:11 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.stubs;
-
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.hotspot.stubs.StubUtil.*;
-
-import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.Node.ConstantNodeParameter;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.replacements.*;
-import com.oracle.graal.word.*;
-
-/**
- * Stub called from {@link WriteBarrierPostStubCall}.
- */
-public class WriteBarrierPostStub extends CRuntimeStub {
-
-    public WriteBarrierPostStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target, linkage);
-    }
-
-    @Snippet
-    private static void writeBarrierPost(Object object, Word card) {
-        writeBarrierPostC(WRITE_BARRIER_POST_C, thread(), object, card);
-    }
-
-    public static final Descriptor WRITE_BARRIER_POST_C = descriptorFor(WriteBarrierPostStub.class, "writeBarrierPostC", false);
-
-    @NodeIntrinsic(CRuntimeCall.class)
-    public static native void writeBarrierPostC(@ConstantNodeParameter Descriptor vmErrorC, Word thread, Object object, Word card);
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/WriteBarrierPreStub.java	Wed May 15 09:03:11 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.stubs;
-
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.hotspot.stubs.StubUtil.*;
-
-import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.Node.ConstantNodeParameter;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.replacements.*;
-import com.oracle.graal.word.*;
-
-/**
- * Stub called from {@link WriteBarrierPreStubCall}.
- */
-public class WriteBarrierPreStub extends CRuntimeStub {
-
-    public WriteBarrierPreStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target, linkage);
-    }
-
-    @Snippet
-    private static void writeBarrierPre(Object object) {
-        writeBarrierPreC(WRITE_BARRIER_PRE_C, thread(), object);
-    }
-
-    public static final Descriptor WRITE_BARRIER_PRE_C = descriptorFor(WriteBarrierPreStub.class, "writeBarrierPreC", false);
-
-    @NodeIntrinsic(CRuntimeCall.class)
-    public static native void writeBarrierPreC(@ConstantNodeParameter Descriptor vmErrorC, Word thread, Object object);
-}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java	Wed May 15 09:03:43 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.lir.asm.*;
 
 /**
- * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
+ * Convenience class to provide SPARCAssembler for the {@link #emitCode} method.
  */
 public abstract class SPARCLIRInstruction extends LIRInstruction {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed May 15 09:03:43 2013 +0200
@@ -72,6 +72,10 @@
 
     public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
+        if (read.usages().count() == 0) {
+            // Read without usages can be savely removed.
+            return null;
+        }
         if (runtime != null && object != null && object.isConstant()) {
             if (location.getLocationIdentity() == LocationNode.FINAL_LOCATION && location instanceof ConstantLocationNode) {
                 long displacement = ((ConstantLocationNode) location).getDisplacement();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Wed May 15 09:03:43 2013 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.java;
+
+import java.lang.reflect.Modifier;
+
+import com.oracle.graal.api.meta.JavaType;
+import com.oracle.graal.api.meta.ResolvedJavaMethod;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.graph.NodeInputList;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.spi.LIRGeneratorTool;
+import com.oracle.graal.nodes.spi.Lowerable;
+import com.oracle.graal.nodes.spi.LoweringTool;
+
+/**
+ * A SelfReplacingMethodCallTargetNode replaces itself in the graph when being lowered with a
+ * {@link MethodCallTargetNode} that calls the stored replacement target method.
+ * 
+ * This node is used for method handle call nodes which have a constant call target but are not
+ * inlined.
+ */
+public class SelfReplacingMethodCallTargetNode extends MethodCallTargetNode implements Lowerable {
+
+    // Replacement method data
+    private final ResolvedJavaMethod replacementTargetMethod;
+    private final JavaType replacementReturnType;
+    @Input private final NodeInputList<ValueNode> replacementArguments;
+
+    public SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod,
+                    ValueNode[] replacementArguments, JavaType replacementReturnType) {
+        super(invokeKind, targetMethod, arguments, returnType);
+        this.replacementTargetMethod = replacementTargetMethod;
+        this.replacementReturnType = replacementReturnType;
+        this.replacementArguments = new NodeInputList<>(this, replacementArguments);
+    }
+
+    public ResolvedJavaMethod replacementTargetMethod() {
+        return replacementTargetMethod;
+    }
+
+    public JavaType replacementReturnType() {
+        return replacementReturnType;
+    }
+
+    public NodeInputList<ValueNode> replacementArguments() {
+        return replacementArguments;
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        InvokeKind invokeKind = Modifier.isStatic(replacementTargetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special;
+        MethodCallTargetNode replacement = graph().add(
+                        new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType));
+
+        // Replace myself...
+        this.replaceAndDelete(replacement);
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        throw GraalInternalError.shouldNotReachHere("should have replaced itself");
+    }
+}
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed May 15 09:03:11 2013 +0200
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed May 15 09:03:43 2013 +0200
@@ -38,7 +38,7 @@
     // SPARC: Define registers.
 
     public SPARC() {
-        super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, null, LOAD_STORE | STORE_STORE, 1, 0, 8);
+        super("SPARC", 8, ByteOrder.LITTLE_ENDIAN, null, LOAD_STORE | STORE_STORE, 1, 0, 8);
         // SPARC: Fix architecture parameters.
     }
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed May 15 09:03:11 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed May 15 09:03:43 2013 +0200
@@ -768,11 +768,6 @@
 
   set_address("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub());
   set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
-  set_address("javaTimeMillisStub", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
-  set_address("javaTimeNanosStub", CAST_FROM_FN_PTR(address, os::javaTimeNanos));
-  set_address("arithmeticSinStub", CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
-  set_address("arithmeticCosStub", CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
-  set_address("arithmeticTanStub", CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
   set_address("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock());
   set_address("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock());
   set_address("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt());
@@ -799,6 +794,11 @@
   set_address("vmErrorAddress", GraalRuntime::vm_error);
   set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre);
   set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post);
+  set_address("javaTimeMillisAddress", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
+  set_address("javaTimeNanosAddress", CAST_FROM_FN_PTR(address, os::javaTimeNanos));
+  set_address("arithmeticSinAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
+  set_address("arithmeticCosAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
+  set_address("arithmeticTanAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
 
   set_int("deoptReasonNone", Deoptimization::Reason_none);
   set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check);