changeset 6521:2a0c9f20baa1

consolidated framework for runtime and stub calls and moved declaration of descriptors for such calls to the source file in which they are used
author Doug Simon <doug.simon@oracle.com>
date Fri, 05 Oct 2012 17:55:12 +0200
parents 14d158886ce0
children c612043278e9
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.phases/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java src/cpu/x86/vm/c1_Runtime1_x86.cpp src/share/vm/c1/c1_Runtime1.cpp src/share/vm/c1/c1_Runtime1.hpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 56 files changed, 651 insertions(+), 547 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.api.code;
 
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -80,10 +81,9 @@
     Object asCallTarget(Object target);
 
     /**
-     * Returns the maximum absolute offset of a runtime call target from any position in the code cache or -1
-     * when not known or not applicable. Intended for determining the required size of address/offset fields.
+     * Gets the signature and linkage information for a runtime call.
      */
-    long getMaxCallTargetOffset(RuntimeCall rtcall);
+    RuntimeCall getRuntimeCall(Descriptor descriptor);
 
     /**
      * Encodes a deoptimization action and a deoptimization reason in an integer value.
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java	Fri Oct 05 17:55:12 2012 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,67 +22,91 @@
  */
 package com.oracle.graal.api.code;
 
-import static com.oracle.graal.api.meta.Kind.*;
+import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 
 /**
- * Enumerates the calls that must be provided by the runtime system. The compiler may generate code that calls the
- * runtime services for unresolved and slow cases of some bytecodes.
+ * The name, signature and calling convention of a call from compiled code to the runtime.
+ * The target of such a call may be a leaf stub or a call into the runtime code proper.
  */
-public class RuntimeCall {
+public interface RuntimeCall {
+
+    /**
+     * The name and signature of a runtime call.
+     */
+    public static class Descriptor {
+        private final String name;
+        private final Kind resultKind;
+        private final Kind[] argumentKinds;
+
+        public Descriptor(String name, Kind resultKind, Kind... args) {
+            this.name = name;
+            this.resultKind = resultKind;
+            this.argumentKinds = args;
+        }
+
+        /**
+         * Gets the name of this runtime call.
+         */
+        public String getName() {
+            return name;
+        }
 
-    // TODO Move the singletons to projects where they are actually used. A couple of them
-    // are HotSpot-specific.
-    public static final RuntimeCall UnwindException = new RuntimeCall("UnwindException", Void, true, Object);
-    public static final RuntimeCall Deoptimize = new RuntimeCall("Deoptimize", Void, true);
-    public static final RuntimeCall RegisterFinalizer = new RuntimeCall("RegisterFinalizer", Void, true, Object);
-    public static final RuntimeCall SetDeoptInfo = new RuntimeCall("SetDeoptInfo", Void, true, Object);
-    public static final RuntimeCall CreateNullPointerException = new RuntimeCall("CreateNullPointerException", Object, true);
-    public static final RuntimeCall CreateOutOfBoundsException = new RuntimeCall("CreateOutOfBoundsException", Object, true, Int);
-    public static final RuntimeCall JavaTimeMillis = new RuntimeCall("JavaTimeMillis", Long, false);
-    public static final RuntimeCall JavaTimeNanos = new RuntimeCall("JavaTimeNanos", Long, false);
-    public static final RuntimeCall Debug = new RuntimeCall("Debug", Void, true);
-    public static final RuntimeCall ArithmeticFrem = new RuntimeCall("ArithmeticFrem", Float, false, Float, Float);
-    public static final RuntimeCall ArithmeticDrem = new RuntimeCall("ArithmeticDrem", Double, false, Double, Double);
-    public static final RuntimeCall ArithmeticCos = new RuntimeCall("ArithmeticCos", Double, false, Double);
-    public static final RuntimeCall ArithmeticTan = new RuntimeCall("ArithmeticTan", Double, false, Double);
-    public static final RuntimeCall ArithmeticSin = new RuntimeCall("ArithmeticSin", Double, false, Double);
-    public static final RuntimeCall GenericCallback = new RuntimeCall("GenericCallback", Object, true, Object, Object);
-    public static final RuntimeCall LogPrintf = new RuntimeCall("LogPrintf", Void, false, Object, Long);
-    public static final RuntimeCall LogPrimitive = new RuntimeCall("LogPrimitive", Void, false, Int, Long, Boolean);
-    public static final RuntimeCall LogObject = new RuntimeCall("LogObject", Void, false, Object, Int);
+        /**
+         * Gets the return kind of this runtime call.
+         */
+        public Kind getResultKind() {
+            return resultKind;
+        }
+
+        /**
+         * Gets the argument kinds of this runtime call.
+         */
+        public Kind[] getArgumentKinds() {
+            return argumentKinds.clone();
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
 
-    private final String name;
-    private final Kind resultKind;
-    private final Kind[] argumentKinds;
-    private final boolean hasSideEffect;
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Descriptor) {
+                Descriptor nas = (Descriptor) obj;
+                return nas.name.equals(name) && nas.resultKind.equals(resultKind) && Arrays.equals(nas.argumentKinds, argumentKinds);
+            }
+            return false;
+        }
 
-    public RuntimeCall(String name, Kind resultKind, boolean hasSideEffect, Kind... args) {
-        this.name = name;
-        this.resultKind = resultKind;
-        this.argumentKinds = args;
-        this.hasSideEffect = hasSideEffect;
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder(name).append('(');
+            String sep = "";
+            for (Kind arg : argumentKinds) {
+                sb.append(sep).append(arg);
+                sep = ",";
+            }
+            return sb.append(')').append(resultKind).toString();
+        }
     }
 
-    public String getName() {
-        return name;
-    }
+    CallingConvention getCallingConvention();
 
-    public Kind getResultKind() {
-        return resultKind;
-    }
+    /**
+     * Determines if this call changes state visible to other threads.
+     * Such calls denote boundaries across which deoptimization
+     * points cannot be moved.
+     */
+    boolean hasSideEffect();
 
-    public Kind[] getArgumentKinds() {
-        return argumentKinds;
-    }
+    /**
+     * Returns the maximum absolute offset of PC relative call to this stub from any position in the code cache or -1
+     * when not applicable. Intended for determining the required size of address/offset fields.
+     */
+    long getMaxCallTargetOffset();
 
-    public boolean hasSideEffect() {
-        return hasSideEffect;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
+    Descriptor getDescriptor();
 }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Fri Oct 05 17:55:12 2012 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.lir.*;
@@ -34,6 +35,10 @@
 import com.oracle.max.asm.amd64.*;
 
 public class AMD64DeoptimizationStub extends AMD64Code {
+
+    public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", Kind.Void);
+    public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", Kind.Void, Kind.Object);
+
     public final Label label = new Label();
     public final LIRFrameState info;
     public final DeoptimizationAction action;
@@ -60,12 +65,12 @@
             keepAlive.add(deoptInfo.toString());
             AMD64Move.move(tasm, masm, scratch.asValue(), Constant.forObject(deoptInfo));
             // TODO Make this an explicit calling convention instead of using a scratch register
-            AMD64Call.directCall(tasm, masm, RuntimeCall.SetDeoptInfo, info);
+            AMD64Call.directCall(tasm, masm, tasm.runtime.getRuntimeCall(SET_DEOPT_INFO), info);
         }
 
         masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason));
         // TODO Make this an explicit calling convention instead of using a scratch register
-        AMD64Call.directCall(tasm, masm, RuntimeCall.Deoptimize, info);
+        AMD64Call.directCall(tasm, masm, tasm.runtime.getRuntimeCall(DEOPTIMIZE), info);
         AMD64Call.shouldNotReachHere(tasm, masm);
     }
 
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Fri Oct 05 17:55:12 2012 +0200
@@ -28,6 +28,7 @@
 import static com.oracle.graal.lir.amd64.AMD64Compare.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
@@ -77,6 +78,9 @@
  */
 public abstract class AMD64LIRGenerator extends LIRGenerator {
 
+    public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", Kind.Float, Kind.Float, Kind.Float);
+    public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", Kind.Double, Kind.Double, Kind.Double);
+
     private static final RegisterValue RAX_I = AMD64.rax.asValue(Kind.Int);
     private static final RegisterValue RAX_L = AMD64.rax.asValue(Kind.Long);
     private static final RegisterValue RDX_I = AMD64.rdx.asValue(Kind.Int);
@@ -372,10 +376,14 @@
                 emitMove(a, RAX_L);
                 append(new DivOp(LREM, RDX_L, RAX_L, load(b), state()));
                 return emitMove(RDX_L);
-            case Float:
-                return emitCall(RuntimeCall.ArithmeticFrem, false, a, b);
-            case Double:
-                return emitCall(RuntimeCall.ArithmeticDrem, false, a, b);
+            case Float: {
+                RuntimeCall stub = runtime.getRuntimeCall(ARITHMETIC_FREM);
+                return emitCall(stub, stub.getCallingConvention(), false, a, b);
+            }
+            case Double: {
+                RuntimeCall stub = runtime.getRuntimeCall(ARITHMETIC_DREM);
+                return emitCall(stub, stub.getCallingConvention(), false, a, b);
+            }
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.compiler.phases/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.compiler.phases/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -40,7 +41,7 @@
         }
 
         @Override
-        public boolean hasSideEffect() {
+        public boolean hasSideEffect(CodeCacheProvider runtime) {
             return false;
         }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Oct 05 17:55:12 2012 +0200
@@ -108,6 +108,11 @@
         return target;
     }
 
+    @Override
+    public CodeCacheProvider getRuntime() {
+        return runtime;
+    }
+
     public ResolvedJavaMethod method() {
         return method;
     }
@@ -782,14 +787,9 @@
     }
 
     @Override
-    public Value emitCall(RuntimeCall runtimeCall, boolean canTrap, Value... args) {
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, runtimeCall.getResultKind(), runtimeCall.getArgumentKinds(), target, false);
-        return emitCall(runtimeCall, cc, canTrap, args);
-    }
-
-    @Override
-    public void emitRuntimeCall(RuntimeCallNode x) {
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, x.kind(), x.call().getArgumentKinds(), target(), false);
+    public void visitRuntimeCall(RuntimeCallNode x) {
+        RuntimeCall call = runtime.getRuntimeCall(x.getDescriptor());
+        CallingConvention cc = call.getCallingConvention();
         frameMap.callsMethod(cc);
         Value resultOperand = cc.getReturn();
         Value[] args = visitInvokeArguments(cc, x.arguments());
@@ -811,12 +811,12 @@
             info = stateFor(stateBeforeReturn, -1);
         } else {
             // Every runtime call needs an info
-            // TODO This is conservative. It's not needed for RuntimeCalls that are implemented purely in a stub
+            // TODO This is conservative. It's not needed for calls that are implemented purely in a stub
             //       that does not trash any registers and does not call into the runtime.
             info = state();
         }
 
-        emitCall(x.call(), resultOperand, args, cc.getTemporaries(), Constant.forLong(0), info);
+        emitCall(call, resultOperand, args, cc.getTemporaries(), Constant.forLong(0), info);
 
         if (isLegal(resultOperand)) {
             setResult(x, emitMove(resultOperand));
@@ -951,31 +951,6 @@
         }
     }
 
-    protected final Value callRuntime(RuntimeCall runtimeCall, LIRFrameState info, Value... args) {
-        // get a result register
-        Kind[] arguments = runtimeCall.getArgumentKinds();
-
-        // move the arguments into the correct location
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(RuntimeCall, runtimeCall.getResultKind(), arguments, target(), false);
-        frameMap.callsMethod(cc);
-        assert cc.getArgumentCount() == args.length : "argument count mismatch";
-        Value[] argLocations = new Value[args.length];
-        for (int i = 0; i < args.length; i++) {
-            Value arg = args[i];
-            Value loc = cc.getArgument(i);
-            emitMove(arg, loc);
-            argLocations[i] = loc;
-        }
-        emitCall(runtimeCall, cc.getReturn(), argLocations, cc.getTemporaries(), Constant.forLong(0), info);
-
-        return cc.getReturn();
-    }
-
-    protected final Variable callRuntimeWithResult(RuntimeCall runtimeCall, LIRFrameState info, Value... args) {
-        Value location = callRuntime(runtimeCall, info, args);
-        return emitMove(location);
-    }
-
     public FrameMap frameMap() {
         return frameMap;
     }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Oct 05 17:55:12 2012 +0200
@@ -24,13 +24,11 @@
 
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.max.asm.amd64.AMD64.*;
 
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Register.RegisterFlag;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.gen.*;
@@ -48,7 +46,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.max.asm.*;
 import com.oracle.max.asm.amd64.*;
-import com.oracle.max.asm.amd64.AMD64Assembler.*;
+import com.oracle.max.asm.amd64.AMD64Assembler.ConditionFlag;
 
 /**
  * HotSpot AMD64 specific backend.
@@ -57,61 +55,6 @@
 
     public AMD64HotSpotBackend(HotSpotRuntime runtime, TargetDescription target) {
         super(runtime, target);
-        HotSpotVMConfig c = runtime.config;
-        Kind word = target.wordKind;
-
-        Register[] jargs = runtime.getGlobalStubRegisterConfig().getCallingConventionRegisters(RuntimeCall, RegisterFlag.CPU);
-        Register jarg0 = jargs[0];
-        Register jarg1 = jargs[1];
-        Register jarg2 = jargs[2];
-
-        addStub(MONITORENTER_STUB_NAME, c.fastMonitorEnterStub,
-                /*        temps */ new Register[] {rax, rbx},
-                /*          ret */ IllegalValue,
-                /* arg0: object */ jarg0.asValue(Kind.Object),
-                /* arg1:   lock */ jarg1.asValue(word));
-
-        addStub(MONITOREXIT_STUB_NAME, c.fastMonitorExitStub,
-                /*        temps */ new Register[] {rax, rbx},
-                /*          ret */ IllegalValue,
-                /* arg0: object */ jarg0.asValue(Kind.Object),
-                /* arg1:   lock */ jarg1.asValue(word));
-
-        addStub(NEW_OBJECT_ARRAY_STUB_NAME, c.newObjectArrayStub,
-                /*        temps */ new Register[] {rcx, rdi, rsi},
-                /*          ret */ rax.asValue(Kind.Object),
-                /* arg0:    hub */ rdx.asValue(Kind.Object),
-                /* arg1: length */ rbx.asValue(Kind.Int));
-
-        addStub(NEW_TYPE_ARRAY_STUB_NAME, c.newTypeArrayStub,
-                /*        temps */ new Register[] {rcx, rdi, rsi},
-                /*          ret */ rax.asValue(Kind.Object),
-                /* arg0:    hub */ rdx.asValue(Kind.Object),
-                /* arg1: length */ rbx.asValue(Kind.Int));
-
-        addStub(NEW_INSTANCE_STUB_NAME, c.newInstanceStub,
-                /*        temps */ null,
-                /*          ret */ rax.asValue(Kind.Object),
-                /* arg0:    hub */ rdx.asValue(Kind.Object));
-
-        addStub(NEW_MULTI_ARRAY_STUB_NAME, c.newMultiArrayStub,
-                /*        temps */ null,
-                /*          ret */ rax.asValue(Kind.Object),
-                /* arg0:    hub */ rax.asValue(Kind.Object),
-                /* arg1:   rank */ rbx.asValue(Kind.Int),
-                /* arg2:   dims */ rcx.asValue(word));
-
-        addStub(VERIFY_OOP_STUB_NAME, c.verifyOopStub,
-                /*        temps */ null,
-                /*          ret */ IllegalValue,
-                /* arg0: object */ r13.asValue(Kind.Object));
-
-        addStub(VM_ERROR_STUB_NAME, c.vmErrorStub,
-                /*        temps */ null,
-                /*          ret */ IllegalValue,
-                /* arg0:  where */ jarg0.asValue(Kind.Object),
-                /* arg1: format */ jarg1.asValue(Kind.Object),
-                /* arg2:  value */ jarg2.asValue(Kind.Object));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Oct 05 17:55:12 2012 +0200
@@ -64,7 +64,6 @@
 
     private final Register[] generalParameterRegisters;
     private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7};
-    private final Register[] allParameterRegisters;
 
     private final CalleeSaveLayout csl;
 
@@ -93,8 +92,6 @@
         }
 
         attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
-        allParameterRegisters = Arrays.copyOf(generalParameterRegisters, generalParameterRegisters.length + xmmParameterRegisters.length);
-        System.arraycopy(xmmParameterRegisters, 0, allParameterRegisters, generalParameterRegisters.length, xmmParameterRegisters.length);
     }
 
     @Override
@@ -116,7 +113,10 @@
     }
 
     public Register[] getCallingConventionRegisters(Type type, RegisterFlag flag) {
-        return allParameterRegisters;
+        if (flag == RegisterFlag.FPU) {
+            return xmmParameterRegisters;
+        }
+        return generalParameterRegisters;
     }
 
     private CallingConvention callingConvention(Kind returnKind, Kind[] kinds, Type type, TargetDescription target, boolean stackOnly) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,9 +22,20 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
+import static com.oracle.graal.compiler.target.amd64.AMD64DeoptimizationStub.*;
+import static com.oracle.graal.compiler.target.amd64.AMD64LIRGenerator.*;
+import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
+import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
+import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
+import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*;
+import static com.oracle.graal.lir.amd64.AMD64Call.*;
 import static com.oracle.max.asm.amd64.AMD64.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -32,6 +43,83 @@
 
     public AMD64HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
         super(config, graalRuntime);
+
+        HotSpotVMConfig c = config;
+        Kind word = graalRuntime.getTarget().wordKind;
+
+        addRuntimeCall(DEOPTIMIZE, config.deoptimizeStub, true,
+                /*           temps */ null,
+                /*             ret */ ret(Kind.Void));
+
+        addRuntimeCall(SET_DEOPT_INFO, config.setDeoptInfoStub, true,
+                /*           temps */ null,
+                /*             ret */ ret(Kind.Void),
+                /* arg0:      info */ scratch(Kind.Object));
+
+        addRuntimeCall(DEBUG, config.debugStub, false,
+                /*           temps */ null,
+                /*             ret */ ret(Kind.Void));
+
+        addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub, false,
+                /*           temps */ null,
+                /*             ret */ ret(Kind.Float),
+                /* arg0:         a */ arg(0, Kind.Float),
+                /* arg1:         b */ arg(1, Kind.Float));
+
+        addRuntimeCall(ARITHMETIC_DREM, config.arithmeticDremStub, false,
+                /*           temps */ null,
+                /*             ret */ ret(Kind.Double),
+                /* arg0:         a */ arg(0, Kind.Double),
+                /* arg1:         b */ arg(1, Kind.Double));
+
+        addRuntimeCall(MONITORENTER, config.fastMonitorEnterStub, true,
+                /*        temps */ new Register[] {rax, rbx},
+                /*          ret */ ret(Kind.Void),
+                /* arg0: object */ arg(0, Kind.Object),
+                /* arg1:   lock */ arg(1, word));
+
+        addRuntimeCall(MONITOREXIT, c.fastMonitorExitStub, true,
+                /*        temps */ new Register[] {rax, rbx},
+                /*          ret */ ret(Kind.Void),
+                /* arg0: object */ arg(0, Kind.Object),
+                /* arg1:   lock */ arg(1, word));
+
+        addRuntimeCall(NEW_OBJECT_ARRAY, c.newObjectArrayStub, false,
+                /*        temps */ new Register[] {rcx, rdi, rsi},
+                /*          ret */ rax.asValue(Kind.Object),
+                /* arg0:    hub */ rdx.asValue(Kind.Object),
+                /* arg1: length */ rbx.asValue(Kind.Int));
+
+        addRuntimeCall(NEW_TYPE_ARRAY, c.newTypeArrayStub, false,
+                /*        temps */ new Register[] {rcx, rdi, rsi},
+                /*          ret */ rax.asValue(Kind.Object),
+                /* arg0:    hub */ rdx.asValue(Kind.Object),
+                /* arg1: length */ rbx.asValue(Kind.Int));
+
+        addRuntimeCall(NEW_INSTANCE, c.newInstanceStub, false,
+                /*        temps */ null,
+                /*          ret */ rax.asValue(Kind.Object),
+                /* arg0:    hub */ rdx.asValue(Kind.Object));
+
+        addRuntimeCall(NEW_MULTI_ARRAY, c.newMultiArrayStub, false,
+                /*        temps */ null,
+                /*          ret */ rax.asValue(Kind.Object),
+                /* arg0:    hub */ rax.asValue(Kind.Object),
+                /* arg1:   rank */ rbx.asValue(Kind.Int),
+                /* arg2:   dims */ rcx.asValue(word));
+
+        addRuntimeCall(VERIFY_OOP, c.verifyOopStub, false,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void),
+                /* arg0: object */ r13.asValue(Kind.Object));
+
+        addRuntimeCall(VM_ERROR, c.vmErrorStub, false,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void),
+                /* arg0:  where */ arg(0, Kind.Object),
+                /* arg1: format */ arg(1, Kind.Object),
+                /* arg2:  value */ arg(2, Kind.Long));
+
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,10 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
-import java.util.*;
-
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -34,17 +31,6 @@
  */
 public abstract class HotSpotBackend extends Backend {
 
-    public static final String VM_ERROR_STUB_NAME = "vm_error";
-    public static final String VERIFY_OOP_STUB_NAME = "verify_oop";
-    public static final String NEW_MULTI_ARRAY_STUB_NAME = "new_multi_array";
-    public static final String NEW_INSTANCE_STUB_NAME = "new_instance";
-    public static final String NEW_TYPE_ARRAY_STUB_NAME = "new_type_array";
-    public static final String NEW_OBJECT_ARRAY_STUB_NAME = "new_object_array";
-    public static final String MONITOREXIT_STUB_NAME = "monitorexit";
-    public static final String MONITORENTER_STUB_NAME = "monitorenter";
-
-    private final Map<String, HotSpotStub> stubsMap = new HashMap<>();
-
     public HotSpotBackend(HotSpotRuntime runtime, TargetDescription target) {
         super(runtime, target);
     }
@@ -53,31 +39,4 @@
     public HotSpotRuntime runtime() {
         return (HotSpotRuntime) super.runtime();
     }
-
-    /**
-     * Gets the linkage information for a global stub.
-     */
-    public HotSpotStub getStub(String name) {
-        HotSpotStub stub = stubsMap.get(name);
-        assert stub != null : "no stub named " + name;
-        return stub;
-    }
-
-    /**
-     * Registers the details for linking a global stub.
-     *
-     * @param name name of the stub
-     * @param address address of the stub
-     * @param tempRegs temporary registers used (and killed) by the stub (null if none)
-     * @param ret where the stub returns its result
-     * @param args where arguments are passed to the stub
-     */
-    protected void addStub(String name, long address, Register[] tempRegs, Value ret, Value... args) {
-        Value[] temps = tempRegs == null || tempRegs.length == 0 ? Value.NONE : new Value[tempRegs.length];
-        for (int i = 0; i < temps.length; i++) {
-            temps[i] = tempRegs[i].asValue();
-        }
-        HotSpotStub stub = new HotSpotStub(name, address, new CallingConvention(temps, 0, ret, args));
-        stubsMap.put(name, stub);
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Fri Oct 05 17:55:12 2012 +0200
@@ -59,6 +59,13 @@
         instance = runtime;
     }
 
+    private static Kind wordKind;
+
+    public static Kind wordKind() {
+        assert wordKind != null;
+        return wordKind;
+    }
+
     protected final CompilerToVM compilerToVm;
     protected final VMToCompiler vmToCompiler;
 
@@ -99,6 +106,9 @@
         }
 
         target = createTarget();
+        assert wordKind == null || wordKind.equals(target.wordKind);
+        wordKind = target.wordKind;
+
         runtime = createRuntime();
 
         HotSpotBackend backend = createBackend();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCall.java	Fri Oct 05 17:55:12 2012 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.bridge.*;
+
+/**
+ * The details required to link a HotSpot runtime or stub call.
+ */
+public class HotSpotRuntimeCall implements RuntimeCall {
+
+    /**
+     * The descriptor of the stub. This is for informational purposes only.
+     */
+    public final Descriptor descriptor;
+
+    /**
+     * The entry point address of the stub.
+     */
+    public final long address;
+
+    /**
+     * Where the stub gets its arguments and where it places its result.
+     */
+    public final CallingConvention cc;
+
+    private final boolean hasSideEffect;
+    private final CompilerToVM vm;
+
+    public HotSpotRuntimeCall(Descriptor descriptor, long address, boolean hasSideEffect, CallingConvention cc, CompilerToVM vm) {
+        this.address = address;
+        this.descriptor = descriptor;
+        this.cc = cc;
+        this.hasSideEffect = hasSideEffect;
+        this.vm = vm;
+    }
+
+    @Override
+    public String toString() {
+        return descriptor + "@0x" + Long.toHexString(address) + ":" + cc;
+    }
+
+    public CallingConvention getCallingConvention() {
+        return cc;
+    }
+
+    public boolean hasSideEffect() {
+        return hasSideEffect;
+    }
+
+    public long getMaxCallTargetOffset() {
+        return vm.getMaxCallTargetOffset(address);
+    }
+
+    public Descriptor getDescriptor() {
+        return descriptor;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotStub.java	Fri Oct 05 15:54:08 2012 +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;
-
-import com.oracle.graal.api.code.*;
-
-/**
- * The details required to link a call to a HotSpot stub.
- */
-public class HotSpotStub {
-
-    /**
-     * The name of the stub. This is for informational purposes only.
-     */
-    public final String name;
-
-    /**
-     * The entry point address of the stub.
-     */
-    public final long address;
-
-    /**
-     * Where the stub gets its arguments and where it places its result.
-     */
-    public final CallingConvention cc;
-
-    public HotSpotStub(String name, long address, CallingConvention cc) {
-        this.address = address;
-        this.name = name;
-        this.cc = cc;
-    }
-
-    @Override
-    public String toString() {
-        return name + "@0x" + Long.toHexString(address) + ":" + cc;
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Oct 05 17:55:12 2012 +0200
@@ -177,6 +177,23 @@
     public long fastMonitorExitStub;
     public long verifyOopStub;
     public long vmErrorStub;
+    public long deoptimizeStub;
+    public long unwindExceptionStub;
+    public long registerFinalizerStub;
+    public long setDeoptInfoStub;
+    public long createNullPointerExceptionStub;
+    public long createOutOfBoundsExceptionStub;
+    public long javaTimeMillisStub;
+    public long javaTimeNanosStub;
+    public long arithmeticFremStub;
+    public long arithmeticDremStub;
+    public long arithmeticSinStub;
+    public long arithmeticCosStub;
+    public long arithmeticTanStub;
+    public long logPrimitiveStub;
+    public long logObjectStub;
+    public long logPrintfStub;
+
 
     public void check() {
         assert vmPageSize >= 16;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Oct 05 17:55:12 2012 +0200
@@ -25,7 +25,6 @@
 
 import java.lang.reflect.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -103,7 +102,7 @@
 
     ResolvedJavaField getJavaField(Field reflectionField);
 
-    long getMaxCallTargetOffset(RuntimeCall rtcall);
+    long getMaxCallTargetOffset(long stub);
 
     String disassembleNative(byte[] code, long address);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Oct 05 17:55:12 2012 +0200
@@ -25,7 +25,6 @@
 
 import java.lang.reflect.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -147,7 +146,7 @@
     public native int JavaMethod_getCompiledCodeSize(HotSpotResolvedJavaMethod method);
 
     @Override
-    public native long getMaxCallTargetOffset(RuntimeCall rtcall);
+    public native long getMaxCallTargetOffset(long stub);
 
     @Override
     public native String disassembleNative(byte[] code, long address);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Oct 05 17:55:12 2012 +0200
@@ -23,6 +23,13 @@
 package com.oracle.graal.hotspot.meta;
 
 import static com.oracle.graal.api.code.MemoryBarriers.*;
+import static com.oracle.graal.api.meta.Value.*;
+import static com.oracle.graal.hotspot.snippets.SystemSnippets.*;
+import static com.oracle.graal.java.GraphBuilderPhase.*;
+import static com.oracle.graal.nodes.UnwindNode.*;
+import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
+import static com.oracle.graal.snippets.Log.*;
+import static com.oracle.graal.snippets.MathSnippetsX86.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -33,6 +40,8 @@
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.code.CompilationResult.Safepoint;
+import com.oracle.graal.api.code.Register.RegisterFlag;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaType.Representation;
 import com.oracle.graal.compiler.*;
@@ -55,19 +64,131 @@
  */
 public abstract class HotSpotRuntime implements GraalCodeCacheProvider {
     public final HotSpotVMConfig config;
-    private final RegisterConfig regConfig;
-    private final RegisterConfig globalStubRegConfig;
-    private final HotSpotGraalRuntime graalRuntime;
+
+    protected final RegisterConfig regConfig;
+    protected final RegisterConfig globalStubRegConfig;
+    protected final HotSpotGraalRuntime graalRuntime;
+
     private CheckCastSnippets.Templates checkcastSnippets;
     private InstanceOfSnippets.Templates instanceofSnippets;
     private NewObjectSnippets.Templates newObjectSnippets;
     private MonitorSnippets.Templates monitorSnippets;
 
+    private final Map<Descriptor, RuntimeCall> runtimeCalls = new HashMap<>();
+
+    protected Value ret(Kind kind) {
+        if (kind.isVoid()) {
+            return IllegalValue;
+        }
+        return globalStubRegConfig.getReturnRegister(kind).asValue(kind);
+    }
+
+    protected Value arg(int index, Kind kind) {
+        if (kind.isFloat() || kind.isDouble()) {
+            return globalStubRegConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.FPU)[index].asValue(kind);
+        }
+        return globalStubRegConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index].asValue(kind);
+    }
+
+    protected Value scratch(Kind kind) {
+        return globalStubRegConfig.getScratchRegister().asValue(kind);
+    }
+
     public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
         this.config = config;
         this.graalRuntime = graalRuntime;
         regConfig = createRegisterConfig(false);
         globalStubRegConfig = createRegisterConfig(true);
+
+        addRuntimeCall(UNWIND_EXCEPTION, config.unwindExceptionStub, true,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Void),
+                        /* arg0: exception */ arg(0, Kind.Object));
+
+        addRuntimeCall(REGISTER_FINALIZER, config.registerFinalizerStub, true,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Void),
+                        /* arg0:    object */ arg(0, Kind.Object));
+
+        addRuntimeCall(CREATE_NULL_POINTER_EXCEPTION, config.createNullPointerExceptionStub, true,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Object));
+
+        addRuntimeCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, config.createOutOfBoundsExceptionStub, true,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Object),
+                        /* arg0:     index */ arg(0, Kind.Int));
+
+        addRuntimeCall(JAVA_TIME_MILLIS, config.javaTimeMillisStub, false,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Long));
+
+        addRuntimeCall(JAVA_TIME_NANOS, config.javaTimeNanosStub, false,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Long));
+
+        addRuntimeCall(ARITHMETIC_SIN, config.arithmeticSinStub, false,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Double),
+                        /* arg0:     index */ arg(0, Kind.Double));
+
+        addRuntimeCall(ARITHMETIC_COS, config.arithmeticCosStub, false,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Double),
+                        /* arg0:     index */ arg(0, Kind.Double));
+
+        addRuntimeCall(ARITHMETIC_TAN, config.arithmeticTanStub, false,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Double),
+                        /* arg0:     index */ arg(0, Kind.Double));
+
+        addRuntimeCall(LOG_PRIMITIVE, config.logPrimitiveStub, false,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Void),
+                        /* arg0:  typeChar */ arg(0, Kind.Int),
+                        /* arg1:     value */ arg(1, Kind.Long),
+                        /* arg2:   newline */ arg(2, Kind.Boolean));
+
+        addRuntimeCall(LOG_PRINTF, config.logPrintfStub, false,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Void),
+                        /* arg0:    format */ arg(0, Kind.Object),
+                        /* arg1:     value */ arg(1, Kind.Long));
+
+        addRuntimeCall(LOG_OBJECT, config.logObjectStub, false,
+                        /*           temps */ null,
+                        /*             ret */ ret(Kind.Void),
+                        /* arg0:    object */ arg(0, Kind.Object),
+                        /* arg1:     flags */ arg(1, Kind.Int));
+    }
+
+
+    /**
+     * 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
+     */
+    protected void addRuntimeCall(Descriptor descriptor, long address, boolean hasSideEffect, Register[] tempRegs, Value ret, Value... args) {
+        Value[] temps = tempRegs == null || tempRegs.length == 0 ? Value.NONE : new Value[tempRegs.length];
+        for (int i = 0; i < temps.length; i++) {
+            temps[i] = tempRegs[i].asValue();
+        }
+        Kind retKind = ret.getKind();
+        if (retKind == Kind.Illegal) {
+            retKind = Kind.Void;
+        }
+        assert retKind.equals(descriptor.getResultKind()) : descriptor + " incompatible with result location " + ret;
+        Kind[] argKinds = descriptor.getArgumentKinds();
+        assert argKinds.length == args.length : descriptor + " incompatible with number of argument locations: " + args.length;
+        for (int i = 0; i < argKinds.length; i++) {
+            assert argKinds[i].equals(args[i].getKind()) : descriptor + " incompatible with argument location " + i + ": " + args[i];
+        }
+        HotSpotRuntimeCall runtimeCall = new HotSpotRuntimeCall(descriptor, address, hasSideEffect, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM());
+        runtimeCalls.put(descriptor, runtimeCall);
     }
 
     protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig);
@@ -523,11 +644,15 @@
     }
 
     public Object asCallTarget(Object target) {
+        if (target instanceof HotSpotRuntimeCall) {
+            return ((HotSpotRuntimeCall) target).address;
+        }
         return target;
     }
 
-    public long getMaxCallTargetOffset(RuntimeCall rtcall) {
-        return graalRuntime.getCompilerToVM().getMaxCallTargetOffset(rtcall);
+    public RuntimeCall getRuntimeCall(Descriptor descriptor) {
+        assert runtimeCalls.containsKey(descriptor) : descriptor;
+        return runtimeCalls.get(descriptor);
     }
 
     public ResolvedJavaMethod getResolvedJavaMethod(Method reflectionMethod) {
@@ -559,10 +684,6 @@
         return graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, compResult), false, hsInfo);
     }
 
-    public RegisterConfig getGlobalStubRegisterConfig() {
-        return globalStubRegConfig;
-    }
-
     @Override
     public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
         final int actionShift = 0;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return false;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
@@ -39,7 +40,7 @@
     }
 
     @Override
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return false;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,11 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.snippets.*;
@@ -38,6 +40,7 @@
 
     @Input private final ValueNode object;
     @Input private final ValueNode lock;
+    public static final Descriptor MONITORENTER = new Descriptor("monitorenter", Kind.Void, Kind.Object, wordKind());
 
     public MonitorEnterStubCall(ValueNode object, ValueNode lock) {
         super(StampFactory.forVoid());
@@ -47,9 +50,8 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        HotSpotBackend backend = (HotSpotBackend) HotSpotGraalRuntime.getInstance().getCompiler().backend;
-        HotSpotStub stub = backend.getStub(MONITORENTER_STUB_NAME);
-        gen.emitCall(stub.address, stub.cc, true, gen.operand(object), gen.operand(lock));
+        RuntimeCall stub = gen.getRuntime().getRuntimeCall(MonitorEnterStubCall.MONITORENTER);
+        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.operand(lock));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,11 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -36,6 +38,7 @@
 public class MonitorExitStubCall extends FixedWithNextNode implements LIRGenLowerable {
 
     @Input private final ValueNode object;
+    public static final Descriptor MONITOREXIT = new Descriptor("monitorexit", Kind.Void, Kind.Object, wordKind());
 
     public MonitorExitStubCall(ValueNode object) {
         super(StampFactory.forVoid());
@@ -44,9 +47,8 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        HotSpotBackend backend = (HotSpotBackend) HotSpotGraalRuntime.getInstance().getCompiler().backend;
-        HotSpotStub stub = backend.getStub(MONITOREXIT_STUB_NAME);
-        gen.emitCall(stub.address, stub.cc, true, gen.operand(object), gen.emitLea(gen.peekLock()));
+        RuntimeCall stub = gen.getRuntime().getRuntimeCall(MonitorExitStubCall.MONITOREXIT);
+        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.emitLea(gen.peekLock()));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
-
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
@@ -42,6 +43,10 @@
     @Input private final ValueNode length;
     private final boolean isObjectArray;
 
+    public static final Descriptor NEW_OBJECT_ARRAY = new Descriptor("new_object_array", Kind.Object, Kind.Object, Kind.Int);
+
+    public static final Descriptor NEW_TYPE_ARRAY = new Descriptor("new_type_array", Kind.Object, Kind.Object, Kind.Int);
+
     public NewArrayStubCall(boolean isObjectArray, ValueNode hub, ValueNode length) {
         super(defaultStamp);
         this.isObjectArray = isObjectArray;
@@ -61,9 +66,8 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        HotSpotBackend backend = (HotSpotBackend) HotSpotGraalRuntime.getInstance().getCompiler().backend;
-        HotSpotStub stub = backend.getStub(isObjectArray ? NEW_OBJECT_ARRAY_STUB_NAME : NEW_TYPE_ARRAY_STUB_NAME);
-        Variable result = gen.emitCall(stub.address, stub.cc, true, gen.operand(hub), gen.operand(length));
+        RuntimeCall stub = gen.getRuntime().getRuntimeCall(isObjectArray ? NewArrayStubCall.NEW_OBJECT_ARRAY : NewArrayStubCall.NEW_TYPE_ARRAY);
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), gen.operand(length));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
-
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
@@ -40,6 +41,8 @@
 
     @Input private final ValueNode hub;
 
+    public static final Descriptor NEW_INSTANCE = new Descriptor("new_instance", Kind.Object, Kind.Object);
+
     public NewInstanceStubCall(ValueNode hub) {
         super(defaultStamp);
         this.hub = hub;
@@ -57,9 +60,8 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        HotSpotBackend backend = (HotSpotBackend) HotSpotGraalRuntime.getInstance().getCompiler().backend;
-        HotSpotStub stub = backend.getStub(NEW_INSTANCE_STUB_NAME);
-        Variable result = gen.emitCall(stub.address, stub.cc, true, gen.operand(hub));
+        RuntimeCall stub = gen.getRuntime().getRuntimeCall(NewInstanceStubCall.NEW_INSTANCE);
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
@@ -44,6 +46,8 @@
     @Input private final ValueNode dims;
     private final int rank;
 
+    public static final Descriptor NEW_MULTI_ARRAY = new Descriptor("new_multi_array", Kind.Object, Kind.Object, Kind.Int, wordKind());
+
     public NewMultiArrayStubCall(ValueNode hub, int rank, ValueNode dims) {
         super(defaultStamp);
         this.hub = hub;
@@ -63,9 +67,8 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        HotSpotBackend backend = (HotSpotBackend) HotSpotGraalRuntime.getInstance().getCompiler().backend;
-        HotSpotStub stub = backend.getStub(NEW_MULTI_ARRAY_STUB_NAME);
-        Variable result = gen.emitCall(stub.address, stub.cc, true, gen.operand(hub), Constant.forInt(rank), gen.operand(dims));
+        RuntimeCall stub = gen.getRuntime().getRuntimeCall(NewMultiArrayStubCall.NEW_MULTI_ARRAY);
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), Constant.forInt(rank), gen.operand(dims));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,13 +22,11 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
-
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
@@ -42,6 +40,7 @@
 
     @Input private ValueNode format;
     @Input private ValueNode value;
+    public static final Descriptor VM_ERROR = new Descriptor("vm_error", Kind.Void, Kind.Object, Kind.Object, Kind.Long);
 
     public VMErrorNode(ValueNode format, ValueNode value) {
         super(StampFactory.forVoid());
@@ -61,9 +60,8 @@
             where = "in compiled code for " + MetaUtil.format("%H.%n(%p)", gen.method());
         }
 
-        HotSpotBackend backend = (HotSpotBackend) HotSpotGraalRuntime.getInstance().getCompiler().backend;
-        HotSpotStub stub = backend.getStub(VM_ERROR_STUB_NAME);
-        gen.emitCall(stub.address, stub.cc, false, Constant.forObject(where), gen.operand(format), gen.operand(value));
+        RuntimeCall stub = gen.getRuntime().getRuntimeCall(VMErrorNode.VM_ERROR);
+        gen.emitCall(stub, stub.getCallingConvention(), false, Constant.forObject(where), gen.operand(format), gen.operand(value));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
-
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -36,6 +36,7 @@
 public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable {
 
     @Input private final ValueNode object;
+    public static final Descriptor VERIFY_OOP = new Descriptor("verify_oop", Kind.Void, Kind.Object);
 
     public VerifyOopStubCall(ValueNode object) {
         super(StampFactory.objectNonNull());
@@ -44,9 +45,8 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        HotSpotBackend backend = (HotSpotBackend) HotSpotGraalRuntime.getInstance().getCompiler().backend;
-        HotSpotStub stub = backend.getStub(VERIFY_OOP_STUB_NAME);
-        gen.emitCall(stub.address, stub.cc, true, gen.operand(object));
+        RuntimeCall stub = gen.getRuntime().getRuntimeCall(VerifyOopStubCall.VERIFY_OOP);
+        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Fri Oct 05 17:55:12 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.snippets;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Register.RegisterFlag;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
@@ -244,9 +243,4 @@
         assert arrayIndexScale(Kind.Float) == 4;
         assert arrayIndexScale(Kind.Double) == 8;
     }
-
-    public static Register getStubParameterRegister(int index) {
-        RegisterConfig regConfig = HotSpotGraalRuntime.getInstance().getRuntime().getGlobalStubRegisterConfig();
-        return regConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index];
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,7 +22,10 @@
  */
 package com.oracle.graal.hotspot.snippets;
 
-import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.snippets.*;
 
@@ -32,12 +35,18 @@
 @ClassSubstitution(java.lang.System.class)
 public class SystemSnippets implements SnippetsInterface {
 
+    public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", Kind.Long);
+    public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", Kind.Long);
+
     public static long currentTimeMillis() {
-        return RuntimeCallNode.callLong(RuntimeCall.JavaTimeMillis);
+        return callLong(JAVA_TIME_MILLIS);
     }
 
     public static long nanoTime() {
-        return RuntimeCallNode.callLong(RuntimeCall.JavaTimeNanos);
+        return callLong(JAVA_TIME_NANOS);
     }
 
+    @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true)
+    public static native long callLong(@ConstantNodeParameter Descriptor descriptor);
+
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Oct 05 17:55:12 2012 +0200
@@ -29,6 +29,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaType.Representation;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
@@ -53,6 +54,10 @@
  */
 public final class GraphBuilderPhase extends Phase {
 
+    public static final Descriptor CREATE_NULL_POINTER_EXCEPTION = new Descriptor("createNullPointerException", Kind.Object);
+    public static final Descriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new Descriptor("createOutOfBoundsException", Kind.Object, Kind.Int);
+
+
     /**
      * The minimum value to which {@link GraalOptions#TraceBytecodeParserLevel} must be set to trace
      * the bytecode instructions as they are parsed.
@@ -765,7 +770,7 @@
             ValueNode exception = ConstantNode.forObject(new NullPointerException(), runtime, currentGraph);
             trueSucc.setNext(handleException(exception, bci()));
         } else {
-            RuntimeCallNode call = currentGraph.add(new RuntimeCallNode(RuntimeCall.CreateNullPointerException));
+            RuntimeCallNode call = currentGraph.add(new RuntimeCallNode(CREATE_NULL_POINTER_EXCEPTION));
             call.setStateAfter(frameState.create(bci()));
             trueSucc.setNext(call);
             call.setNext(handleException(call, bci()));
@@ -784,7 +789,7 @@
             ValueNode exception = ConstantNode.forObject(new ArrayIndexOutOfBoundsException(), runtime, currentGraph);
             falseSucc.setNext(handleException(exception, bci()));
         } else {
-            RuntimeCallNode call = currentGraph.add(new RuntimeCallNode(RuntimeCall.CreateOutOfBoundsException, new ValueNode[] {index}));
+            RuntimeCallNode call = currentGraph.add(new RuntimeCallNode(CREATE_OUT_OF_BOUNDS_EXCEPTION, index));
             call.setStateAfter(frameState.create(bci()));
             falseSucc.setNext(call);
             call.setNext(handleException(call, bci()));
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Fri Oct 05 17:55:12 2012 +0200
@@ -26,14 +26,17 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.amd64.*;
 
 public class AMD64Call {
 
+    public static final Descriptor DEBUG = new Descriptor("debug", Kind.Void);
+
     @Opcode("CALL_DIRECT")
     public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
         @Def({REG, ILLEGAL}) protected Value result;
@@ -103,7 +106,7 @@
     public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRFrameState info) {
         int before = masm.codeBuffer.position();
         if (target instanceof RuntimeCall) {
-            long maxOffset = tasm.runtime.getMaxCallTargetOffset((RuntimeCall) target);
+            long maxOffset = ((RuntimeCall) target).getMaxCallTargetOffset();
             if (maxOffset != (int) maxOffset) {
                 // offset might not fit a 32-bit immediate, generate an
                 // indirect call with a 64-bit immediate
@@ -114,6 +117,7 @@
             } else {
                 masm.call();
             }
+
         } else {
             masm.call();
         }
@@ -145,7 +149,7 @@
         assert (assertions = true) == true;
 
         if (assertions) {
-            directCall(tasm, masm, RuntimeCall.Debug, null);
+            directCall(tasm, masm, tasm.runtime.getRuntimeCall(DEBUG), null);
             masm.hlt();
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -41,7 +42,7 @@
         stateAfter = x;
     }
 
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return true;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -26,6 +26,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.spi.*;
@@ -44,7 +45,7 @@
         stateAfter = x;
     }
 
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return false;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.code.*;
+
 /**
  * Base class for {@link BeginNode}s that are associated with a frame state.
  * TODO (dnsimon) this not needed until {@link BeginNode} no longer implements {@link StateSplit}
@@ -33,7 +35,7 @@
      * A begin node has no side effect.
      */
     @Override
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return false;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
@@ -149,7 +150,7 @@
         this.stateAfter = stateAfter;
     }
 
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return true;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.code.*;
+
 /**
  * A state split is a node that may have a frame state associated with it.
  */
@@ -42,5 +44,5 @@
      * state visible to other threads. These nodes denote boundaries across which deoptimization
      * points cannot be moved.
      */
-    boolean hasSideEffect();
+    boolean hasSideEffect(CodeCacheProvider runtime);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
@@ -33,6 +34,8 @@
  */
 public final class UnwindNode extends FixedNode implements LIRLowerable, Node.IterableNodeType {
 
+    public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", Kind.Void, Kind.Object);
+
     @Input private ValueNode exception;
 
     public ValueNode exception() {
@@ -47,6 +50,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitCall(RuntimeCall.UnwindException, false, gen.operand(exception()));
+        RuntimeCall call = gen.getRuntime().getRuntimeCall(UNWIND_EXCEPTION);
+        gen.emitCall(call, call.getCallingConvention(), false, gen.operand(exception()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -31,46 +32,32 @@
 @NodeInfo(nameTemplate = "RuntimeCall#{p#call/s}")
 public final class RuntimeCallNode extends AbstractCallNode implements LIRLowerable {
 
-    private final RuntimeCall call;
+    private final Descriptor descriptor;
 
-    public RuntimeCall call() {
-        return call;
+    public RuntimeCallNode(Descriptor descriptor, ValueNode... arguments) {
+        super(StampFactory.forKind(descriptor.getResultKind()), arguments);
+        this.descriptor = descriptor;
     }
 
-    public RuntimeCallNode(RuntimeCall call) {
-        this(call, new ValueNode[0]);
-    }
-
-    public RuntimeCallNode(RuntimeCall call, ValueNode... arguments) {
-        super(StampFactory.forKind(call.getResultKind()), arguments);
-        this.call = call;
+    public Descriptor getDescriptor() {
+        return descriptor;
     }
 
     @Override
-    public boolean hasSideEffect() {
-        return call.hasSideEffect();
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
+        return runtime.getRuntimeCall(descriptor).hasSideEffect();
     }
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitRuntimeCall(this);
+        gen.visitRuntimeCall(this);
     }
 
     @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
-            return super.toString(verbosity) + "#" + call;
+            return super.toString(verbosity) + "#" + descriptor;
         }
         return super.toString(verbosity);
     }
-
-    // specialized on return type (instead of public static <T> T performCall) until boxing/unboxing is sorted out in intrinsification
-    @NodeIntrinsic
-    public static native <S> double callDouble(@ConstantNodeParameter RuntimeCall call, S arg1);
-
-    @NodeIntrinsic
-    public static native long callLong(@ConstantNodeParameter RuntimeCall call);
-
-    @NodeIntrinsic
-    public static native void runtimeCall(@ConstantNodeParameter RuntimeCall call);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -45,7 +46,7 @@
         stateAfter = x;
     }
 
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return true;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -49,7 +50,7 @@
         stateAfter = x;
     }
 
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return true;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -46,7 +46,7 @@
         stateAfter = x;
     }
 
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return true;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -32,6 +34,8 @@
  */
 public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable {
 
+    public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", Kind.Void, Kind.Object);
+
     @Input private ValueNode object;
 
     public ValueNode object() {
@@ -45,7 +49,8 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitCall(RuntimeCall.RegisterFinalizer, true, gen.operand(object()));
+        RuntimeCall call = gen.getRuntime().getRuntimeCall(REGISTER_FINALIZER);
+        gen.emitCall(call, call.getCallingConvention(), true, gen.operand(object()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -46,7 +47,7 @@
         stateAfter = x;
     }
 
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return true;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -45,7 +46,7 @@
         stateAfter = x;
     }
 
-    public boolean hasSideEffect() {
+    public boolean hasSideEffect(CodeCacheProvider runtime) {
         return true;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Oct 05 17:55:12 2012 +0200
@@ -32,6 +32,8 @@
 public abstract class LIRGeneratorTool {
     public abstract TargetDescription target();
 
+    public abstract CodeCacheProvider getRuntime();
+
     /**
      * Checks whether the supplied constant can be used without loading it into a register
      * for most operations, i.e., for commonly used arithmetic, logical, and comparison operations.
@@ -84,7 +86,6 @@
     public abstract void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo);
     public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo, long leafGraphId);
     public abstract Value emitCall(Object target, CallingConvention cc, boolean canTrap, Value... args);
-    public abstract Value emitCall(RuntimeCall runtimeCall, boolean canTrap, Value... args);
 
     public abstract void emitIf(IfNode i);
     public abstract void emitConditional(ConditionalNode i);
@@ -93,7 +94,7 @@
     public abstract void emitSwitch(SwitchNode i);
 
     public abstract void emitInvoke(Invoke i);
-    public abstract void emitRuntimeCall(RuntimeCallNode i);
+    public abstract void visitRuntimeCall(RuntimeCallNode i);
 
     // Handling of block-end nodes still needs to be unified in the LIRGenerator.
     public abstract void visitMerge(MergeNode i);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java	Fri Oct 05 17:55:12 2012 +0200
@@ -24,7 +24,7 @@
 
 import java.io.*;
 
-import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
@@ -37,42 +37,46 @@
  */
 public final class Log {
 
+    public static final Descriptor LOG_PRIMITIVE = new Descriptor("logPrimitive", Kind.Void, Kind.Int, Kind.Long, Kind.Boolean);
+    public static final Descriptor LOG_OBJECT = new Descriptor("logObject", Kind.Void, Kind.Object, Kind.Int);
+    public static final Descriptor LOG_PRINTF = new Descriptor("logPrintf", Kind.Void, Kind.Object, Kind.Long);
+
     // Note: Must be kept in sync with constants in c1_Runtime1.hpp
     private static final int LOG_OBJECT_NEWLINE = 0x01;
     private static final int LOG_OBJECT_STRING  = 0x02;
     private static final int LOG_OBJECT_ADDRESS = 0x04;
 
     @NodeIntrinsic(RuntimeCallNode.class)
-    private static native void log(@ConstantNodeParameter RuntimeCall logObject, Object object, int flags);
+    private static native void log(@ConstantNodeParameter Descriptor logObject, Object object, int flags);
 
     @NodeIntrinsic(RuntimeCallNode.class)
-    private static native void log(@ConstantNodeParameter RuntimeCall logPrimitive, int typeChar, long value, boolean newline);
+    private static native void log(@ConstantNodeParameter Descriptor logPrimitive, int typeChar, long value, boolean newline);
 
     @NodeIntrinsic(RuntimeCallNode.class)
-    private static native void printf(@ConstantNodeParameter RuntimeCall logPrintf, String format, long value);
+    private static native void printf(@ConstantNodeParameter Descriptor logPrintf, String format, long value);
 
     public static void print(boolean value) {
-        log(RuntimeCall.LogPrimitive, Kind.Boolean.typeChar, value ? 1L : 0L, false);
+        log(LOG_PRIMITIVE, Kind.Boolean.typeChar, value ? 1L : 0L, false);
     }
 
     public static void print(byte value) {
-        log(RuntimeCall.LogPrimitive, Kind.Byte.typeChar, value, false);
+        log(LOG_PRIMITIVE, Kind.Byte.typeChar, value, false);
     }
 
     public static void print(char value) {
-        log(RuntimeCall.LogPrimitive, Kind.Char.typeChar, value, false);
+        log(LOG_PRIMITIVE, Kind.Char.typeChar, value, false);
     }
 
     public static void print(short value) {
-        log(RuntimeCall.LogPrimitive, Kind.Short.typeChar, value, false);
+        log(LOG_PRIMITIVE, Kind.Short.typeChar, value, false);
     }
 
     public static void print(int value) {
-        log(RuntimeCall.LogPrimitive, Kind.Int.typeChar, value, false);
+        log(LOG_PRIMITIVE, Kind.Int.typeChar, value, false);
     }
 
     public static void print(long value) {
-        log(RuntimeCall.LogPrimitive, Kind.Long.typeChar, value, false);
+        log(LOG_PRIMITIVE, Kind.Long.typeChar, value, false);
     }
 
     /**
@@ -82,7 +86,7 @@
      *            of characters starting with '%').
      */
     public static void printf(String format, long value) {
-        printf(RuntimeCall.LogPrintf, format, value);
+        printf(LOG_PRINTF, format, value);
     }
 
     public static void print(float value) {
@@ -93,7 +97,7 @@
         } else if (value == Float.NEGATIVE_INFINITY) {
             print("-Infinity");
         } else {
-            log(RuntimeCall.LogPrimitive, Kind.Float.typeChar, Float.floatToRawIntBits(value), false);
+            log(LOG_PRIMITIVE, Kind.Float.typeChar, Float.floatToRawIntBits(value), false);
         }
     }
 
@@ -105,44 +109,44 @@
         } else if (value == Double.NEGATIVE_INFINITY) {
             print("-Infinity");
         } else {
-            log(RuntimeCall.LogPrimitive, Kind.Double.typeChar, Double.doubleToRawLongBits(value), false);
+            log(LOG_PRIMITIVE, Kind.Double.typeChar, Double.doubleToRawLongBits(value), false);
         }
     }
 
     public static void print(String value) {
-        log(RuntimeCall.LogObject, value, LOG_OBJECT_STRING);
+        log(LOG_OBJECT, value, LOG_OBJECT_STRING);
     }
 
     public static void printAddress(Object o) {
-        log(RuntimeCall.LogObject, o, LOG_OBJECT_ADDRESS);
+        log(LOG_OBJECT, o, LOG_OBJECT_ADDRESS);
     }
 
     public static void printObject(Object o) {
-        log(RuntimeCall.LogObject, o, 0);
+        log(LOG_OBJECT, o, 0);
     }
 
     public static void println(boolean value) {
-        log(RuntimeCall.LogPrimitive, Kind.Boolean.typeChar, value ? 1L : 0L, true);
+        log(LOG_PRIMITIVE, Kind.Boolean.typeChar, value ? 1L : 0L, true);
     }
 
     public static void println(byte value) {
-        log(RuntimeCall.LogPrimitive, Kind.Byte.typeChar, value, true);
+        log(LOG_PRIMITIVE, Kind.Byte.typeChar, value, true);
     }
 
     public static void println(char value) {
-        log(RuntimeCall.LogPrimitive, Kind.Char.typeChar, value, true);
+        log(LOG_PRIMITIVE, Kind.Char.typeChar, value, true);
     }
 
     public static void println(short value) {
-        log(RuntimeCall.LogPrimitive, Kind.Short.typeChar, value, true);
+        log(LOG_PRIMITIVE, Kind.Short.typeChar, value, true);
     }
 
     public static void println(int value) {
-        log(RuntimeCall.LogPrimitive, Kind.Int.typeChar, value, true);
+        log(LOG_PRIMITIVE, Kind.Int.typeChar, value, true);
     }
 
     public static void println(long value) {
-        log(RuntimeCall.LogPrimitive, Kind.Long.typeChar, value, true);
+        log(LOG_PRIMITIVE, Kind.Long.typeChar, value, true);
     }
 
     public static void println(float value) {
@@ -153,7 +157,7 @@
         } else if (value == Float.NEGATIVE_INFINITY) {
             println("-Infinity");
         } else {
-            log(RuntimeCall.LogPrimitive, Kind.Float.typeChar, Float.floatToRawIntBits(value), true);
+            log(LOG_PRIMITIVE, Kind.Float.typeChar, Float.floatToRawIntBits(value), true);
         }
     }
 
@@ -165,20 +169,20 @@
         } else if (value == Double.NEGATIVE_INFINITY) {
             println("-Infinity");
         } else {
-            log(RuntimeCall.LogPrimitive, Kind.Double.typeChar, Double.doubleToRawLongBits(value), true);
+            log(LOG_PRIMITIVE, Kind.Double.typeChar, Double.doubleToRawLongBits(value), true);
         }
     }
 
     public static void println(String value) {
-        log(RuntimeCall.LogObject, value, LOG_OBJECT_NEWLINE | LOG_OBJECT_STRING);
+        log(LOG_OBJECT, value, LOG_OBJECT_NEWLINE | LOG_OBJECT_STRING);
     }
 
     public static void printlnAddress(Object o) {
-        log(RuntimeCall.LogObject, o, LOG_OBJECT_NEWLINE | LOG_OBJECT_ADDRESS);
+        log(LOG_OBJECT, o, LOG_OBJECT_NEWLINE | LOG_OBJECT_ADDRESS);
     }
 
     public static void printlnObject(Object o) {
-        log(RuntimeCall.LogObject, o, LOG_OBJECT_NEWLINE);
+        log(LOG_OBJECT, o, LOG_OBJECT_NEWLINE);
     }
 
     public static void println() {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java	Fri Oct 05 17:55:12 2012 +0200
@@ -22,7 +22,10 @@
  */
 package com.oracle.graal.snippets;
 
-import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCall.Descriptor;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.snippets.nodes.*;
 import com.oracle.graal.snippets.nodes.MathIntrinsicNode.Operation;
@@ -61,7 +64,7 @@
         if (abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.SIN);
         } else {
-            return RuntimeCallNode.callDouble(RuntimeCall.ArithmeticSin, x);
+            return callDouble(ARITHMETIC_SIN, x);
         }
     }
 
@@ -69,7 +72,7 @@
         if (abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.COS);
         } else {
-            return RuntimeCallNode.callDouble(RuntimeCall.ArithmeticCos, x);
+            return callDouble(ARITHMETIC_COS, x);
         }
     }
 
@@ -77,8 +80,14 @@
         if (abs(x) < PI_4) {
             return MathIntrinsicNode.compute(x, Operation.TAN);
         } else {
-            return RuntimeCallNode.callDouble(RuntimeCall.ArithmeticTan, x);
+            return callDouble(ARITHMETIC_TAN, x);
         }
     }
 
+    public static final Descriptor ARITHMETIC_SIN = new Descriptor("arithmeticSin", Kind.Double, Kind.Double);
+    public static final Descriptor ARITHMETIC_COS = new Descriptor("arithmeticCos", Kind.Double, Kind.Double);
+    public static final Descriptor ARITHMETIC_TAN = new Descriptor("arithmeticTan", Kind.Double, Kind.Double);
+
+    @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true)
+    public static native double callDouble(@ConstantNodeParameter Descriptor descriptor, double value);
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Fri Oct 05 17:55:12 2012 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -98,6 +99,9 @@
 
     private void installSubstitutions(Class< ? extends SnippetsInterface> clazz, Class<?> originalClazz) {
         for (Method method : clazz.getDeclaredMethods()) {
+            if (method.getAnnotation(NodeIntrinsic.class) != null) {
+                continue;
+            }
             try {
                 Method originalMethod = originalClazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
                 if (!originalMethod.getReturnType().isAssignableFrom(method.getReturnType())) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Fri Oct 05 15:54:08 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Fri Oct 05 17:55:12 2012 +0200
@@ -153,10 +153,10 @@
     public static class Cache {
 
         private final ConcurrentHashMap<SnippetTemplate.Key, SnippetTemplate> templates = new ConcurrentHashMap<>();
-        private final MetaAccessProvider runtime;
+        private final CodeCacheProvider runtime;
 
 
-        public Cache(MetaAccessProvider runtime) {
+        public Cache(CodeCacheProvider runtime) {
             this.runtime = runtime;
         }
 
@@ -215,7 +215,7 @@
     /**
      * Creates a snippet template.
      */
-    public SnippetTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key) {
+    public SnippetTemplate(CodeCacheProvider runtime, SnippetTemplate.Key key) {
         ResolvedJavaMethod method = key.method;
         assert Modifier.isStatic(method.accessFlags()) : "snippet method must be static: " + method;
         Signature signature = method.signature();
@@ -336,7 +336,7 @@
             if (node instanceof StateSplit) {
                 StateSplit stateSplit = (StateSplit) node;
                 FrameState frameState = stateSplit.stateAfter();
-                if (stateSplit.hasSideEffect()) {
+                if (stateSplit.hasSideEffect(runtime)) {
                     assert curSideEffectNode == null : "Currently limited to one side-effecting node (but this can be converted to a List if necessary)";
                     curSideEffectNode = node;
                 }
@@ -520,7 +520,7 @@
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      * @return the map of duplicated nodes (original -> duplicate)
      */
-    public Map<Node, Node> instantiate(MetaAccessProvider runtime,
+    public Map<Node, Node> instantiate(CodeCacheProvider runtime,
                     FixedWithNextNode replacee, SnippetTemplate.Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
@@ -540,7 +540,7 @@
         replacee.setNext(null);
 
         if (sideEffectNode != null) {
-            assert ((StateSplit) replacee).hasSideEffect();
+            assert ((StateSplit) replacee).hasSideEffect(runtime);
             Node sideEffectDup = duplicates.get(sideEffectNode);
             ((StateSplit) sideEffectDup).setStateAfter(((StateSplit) replacee).stateAfter());
         }
@@ -582,7 +582,7 @@
      * @param lastFixedNode the CFG of the snippet is inserted after this node
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      */
-    public void instantiate(MetaAccessProvider runtime,
+    public void instantiate(CodeCacheProvider runtime,
                     FloatingNode replacee,
                     FixedWithNextNode lastFixedNode, SnippetTemplate.Arguments args) {
 
@@ -603,7 +603,7 @@
         replaceeGraph.addAfterFixed(lastFixedNode, firstCFGNodeDuplicate);
 
         if (sideEffectNode != null) {
-            assert ((StateSplit) replacee).hasSideEffect();
+            assert ((StateSplit) replacee).hasSideEffect(runtime);
             Node sideEffectDup = duplicates.get(sideEffectNode);
             ((StateSplit) sideEffectDup).setStateAfter(((StateSplit) replacee).stateAfter());
         }
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Fri Oct 05 15:54:08 2012 +0200
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Fri Oct 05 17:55:12 2012 +0200
@@ -1965,17 +1965,6 @@
       break;
     }
 
-    case graal_generic_callback_id: {
-    __ enter();
-    oop_maps = new OopMapSet();
-    OopMap* oop_map = save_live_registers(sasm, 0);
-    int call_offset = __ call_RT(rax, noreg, (address)graal_generic_callback, j_rarg0, j_rarg1);
-    oop_maps->add_gc_map(call_offset, oop_map);
-    __ leave();
-    __ ret(0);
-      break;
-    }
-
     case graal_verify_oop_id: {
       // We use enter & leave so that a better stack trace is produced in the hs_err file
       __ enter();
--- a/src/share/vm/c1/c1_Runtime1.cpp	Fri Oct 05 15:54:08 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Fri Oct 05 17:55:12 2012 +0200
@@ -663,25 +663,6 @@
   thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message)());
 JRT_END
 
-JRT_ENTRY(void, Runtime1::graal_generic_callback(JavaThread* thread, oop _callback, oop _argument))
-  HandleMark hm;
-  Handle callback(_callback);
-  Handle argument(_argument);
-
-  KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_oracle_graal_api_code_GenericCallback(), SystemDictionary::java_system_loader(), NULL, thread);
-  if (klass.is_null()) {
-    tty->print_cr("couldn't resolve com_oracle_graal_api_code_GenericCallback");
-  }
-
-  JavaValue result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_oop(Handle(callback));
-  args.push_oop(Handle(argument));
-  JavaCalls::call_virtual(&result, klass, vmSymbols::callbackInternal_name(), vmSymbols::callback_signature(), &args, thread);
-
-  thread->set_vm_result((oop) result.get_jobject());
-JRT_END
-
 JRT_ENTRY_NO_ASYNC(void, Runtime1::graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock))
   NOT_PRODUCT(_monitorenter_slowcase_cnt++;)
 #ifdef ASSERT
--- a/src/share/vm/c1/c1_Runtime1.hpp	Fri Oct 05 15:54:08 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Fri Oct 05 17:55:12 2012 +0200
@@ -80,7 +80,6 @@
   stub(graal_set_deopt_info)         \
   stub(graal_create_null_pointer_exception) \
   stub(graal_create_out_of_bounds_exception) \
-  stub(graal_generic_callback)       \
   stub(graal_log_object)             \
   stub(graal_log_printf)             \
   stub(graal_log_primitive)          \
@@ -204,7 +203,6 @@
 #ifdef GRAAL
   static void graal_create_null_exception(JavaThread* thread);
   static void graal_create_out_of_bounds_exception(JavaThread* thread, jint index);
-  static void graal_generic_callback(JavaThread* thread, oop _callback, oop _argument);
   static void graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
   static void graal_monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
   static void graal_vm_error(JavaThread* thread, oop where, oop format, jlong value);
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Oct 05 15:54:08 2012 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Oct 05 17:55:12 2012 +0200
@@ -210,7 +210,6 @@
   template(code_MonitorValue_klass,               com_oracle_graal_api_code_MonitorValue,                       Opt) \
   template(code_Register_klass,                   com_oracle_graal_api_code_Register,                           Opt) \
   template(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Opt) \
-  template(RuntimeCall_klass,                     com_oracle_graal_api_code_RuntimeCall,                        Opt) \
   template(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
   template(VirtualObject_klass,                   com_oracle_graal_api_code_VirtualObject,                      Opt) \
   /* graal.api.meta */                                                                                                \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Oct 05 15:54:08 2012 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Oct 05 17:55:12 2012 +0200
@@ -303,7 +303,6 @@
   template(com_oracle_graal_api_code_Assumptions_MethodContents,     "com/oracle/graal/api/code/Assumptions$MethodContents")          \
   template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype,    "com/oracle/graal/api/code/Assumptions$ConcreteSubtype")         \
   template(com_oracle_graal_api_code_Assumptions_ConcreteMethod,     "com/oracle/graal/api/code/Assumptions$ConcreteMethod")          \
-  template(com_oracle_graal_api_code_GenericCallback,                "com/oracle/graal/api/code/GenericCallback")                     \
   template(com_oracle_graal_api_code_InstalledCode,                  "com/oracle/graal/api/code/CompilationResult")                   \
   template(com_oracle_graal_api_code_InstalledCode_Call,             "com/oracle/graal/api/code/CompilationResult$Call")              \
   template(com_oracle_graal_api_code_InstalledCode_DataPatch,        "com/oracle/graal/api/code/CompilationResult$DataPatch")         \
@@ -317,7 +316,6 @@
   template(com_oracle_graal_api_code_MonitorValue,                   "com/oracle/graal/api/code/MonitorValue")                        \
   template(com_oracle_graal_api_code_Register,                       "com/oracle/graal/api/code/Register")                            \
   template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue")                       \
-  template(com_oracle_graal_api_code_RuntimeCall,                    "com/oracle/graal/api/code/RuntimeCall")                         \
   template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot")                           \
   template(com_oracle_graal_api_code_VirtualObject,                  "com/oracle/graal/api/code/VirtualObject")                       \
   template(startCompiler_name,                    "startCompiler")                                                                    \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Oct 05 15:54:08 2012 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Fri Oct 05 17:55:12 2012 +0200
@@ -529,87 +529,22 @@
   _debug_recorder->end_safepoint(pc_offset);
 }
 
-address CodeInstaller::runtime_call_target_address(oop runtime_call) {
-  address target_addr = 0x0;
-  if (runtime_call == RuntimeCall::Debug()) {
-    TRACE_graal_3("RuntimeCall::Debug()");
-  } else if (runtime_call == RuntimeCall::UnwindException()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id);
-    TRACE_graal_3("RuntimeCall::UnwindException()");
-  } else if (runtime_call == RuntimeCall::SetDeoptInfo()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_set_deopt_info_id);
-    TRACE_graal_3("RuntimeCall::SetDeoptInfo()");
-  } else if (runtime_call == RuntimeCall::CreateNullPointerException()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_create_null_pointer_exception_id);
-    TRACE_graal_3("RuntimeCall::CreateNullPointerException()");
-  } else if (runtime_call == RuntimeCall::CreateOutOfBoundsException()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_create_out_of_bounds_exception_id);
-    TRACE_graal_3("RuntimeCall::CreateOutOfBoundsException()");
-  } else if (runtime_call == RuntimeCall::JavaTimeMillis()) {
-    target_addr = CAST_FROM_FN_PTR(address, os::javaTimeMillis);
-    TRACE_graal_3("RuntimeCall::JavaTimeMillis()");
-  } else if (runtime_call == RuntimeCall::JavaTimeNanos()) {
-    target_addr = CAST_FROM_FN_PTR(address, os::javaTimeNanos);
-    TRACE_graal_3("RuntimeCall::JavaTimeNanos()");
-  } else if (runtime_call == RuntimeCall::ArithmeticFrem()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_arithmetic_frem_id);
-    TRACE_graal_3("RuntimeCall::ArithmeticFrem()");
-  } else if (runtime_call == RuntimeCall::ArithmeticDrem()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_arithmetic_drem_id);
-    TRACE_graal_3("RuntimeCall::ArithmeticDrem()");
-  } else if (runtime_call == RuntimeCall::ArithmeticSin()) {
-    target_addr = CAST_FROM_FN_PTR(address, SharedRuntime::dsin);
-    TRACE_graal_3("RuntimeCall::ArithmeticSin()");
-  } else if (runtime_call == RuntimeCall::ArithmeticCos()) {
-    target_addr = CAST_FROM_FN_PTR(address, SharedRuntime::dcos);
-    TRACE_graal_3("RuntimeCall::ArithmeticCos()");
-  } else if (runtime_call == RuntimeCall::ArithmeticTan()) {
-    target_addr = CAST_FROM_FN_PTR(address, SharedRuntime::dtan);
-    TRACE_graal_3("RuntimeCall::ArithmeticTan()");
-  } else if (runtime_call == RuntimeCall::RegisterFinalizer()) {
-    target_addr = Runtime1::entry_for(Runtime1::register_finalizer_id);
-    TRACE_graal_3("RuntimeCall::RegisterFinalizer()");
-  } else if (runtime_call == RuntimeCall::Deoptimize()) {
-    target_addr = SharedRuntime::deopt_blob()->uncommon_trap();
-    TRACE_graal_3("RuntimeCall::Deoptimize()");
-  } else if (runtime_call == RuntimeCall::GenericCallback()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_generic_callback_id);
-    TRACE_graal_3("RuntimeCall::GenericCallback()");
-  } else if (runtime_call == RuntimeCall::LogPrimitive()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_log_primitive_id);
-    TRACE_graal_3("RuntimeCall::LogPrimitive()");
-  } else if (runtime_call == RuntimeCall::LogPrintf()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_log_printf_id);
-    TRACE_graal_3("RuntimeCall::LogPrintf()");
-  } else if (runtime_call == RuntimeCall::LogObject()) {
-    target_addr = Runtime1::entry_for(Runtime1::graal_log_object_id);
-    TRACE_graal_3("RuntimeCall::LogObject()");
-  } else {
-    runtime_call->print();
-    fatal("runtime_call not implemented");
-  }
-  return target_addr;
-}
-
 void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) {
   oop target = InstalledCode_Call::target(site);
   instanceKlass* target_klass = instanceKlass::cast(target->klass());
 
-  oop runtime_call = NULL; // RuntimeCall
   oop hotspot_method = NULL; // JavaMethod
   oop global_stub = NULL;
 
   if (target_klass->is_subclass_of(SystemDictionary::Long_klass())) {
     global_stub = target;
-  } else if (target->is_a(RuntimeCall::klass())) {
-    runtime_call = target;
   } else {
     hotspot_method = target;
   }
 
   oop debug_info = InstalledCode_Call::debugInfo(site);
 
-  assert((runtime_call ? 1 : 0) + (hotspot_method ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type");
+  assert((hotspot_method ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type");
 
   NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
   jint next_pc_offset = 0x0;
@@ -630,7 +565,6 @@
     next_pc_offset = pc_offset + ((NativeCallReg *) inst)->next_instruction_offset();
   } else {
     tty->print_cr("at pc_offset %d", pc_offset);
-    runtime_call->print();
     fatal("unsupported type of instruction for call site");
   }
 
@@ -650,34 +584,24 @@
     record_scope(next_pc_offset, frame, new GrowableArray<ScopeValue*>());
   }
 
-  if (runtime_call != NULL) {
-    if (runtime_call != RuntimeCall::Debug()) {
-      address target_addr = runtime_call_target_address(runtime_call);
-
-      if (inst->is_call()) {
-        // NOTE: for call without a mov, the offset must fit a 32-bit immediate
-        //       see also CompilerToVM.getMaxCallTargetOffset()
-        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-        call->set_destination(target_addr);
-        _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
-      } else if (inst->is_mov_literal64()) {
-        NativeMovConstReg* mov = nativeMovConstReg_at(_instructions->start() + pc_offset);
-        mov->set_data((intptr_t) target_addr);
-        _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
-      } else {
-        runtime_call->print();
-        fatal("unknown type of instruction for runtime call");
-      }
-    }
-  } else if (global_stub != NULL) {
+  if (global_stub != NULL) {
     assert(java_lang_boxing_object::is_instance(global_stub, T_LONG), "global_stub needs to be of type Long");
 
     if (inst->is_call()) {
-      nativeCall_at((address)inst)->set_destination(VmIds::getStub(global_stub));
+      // NOTE: for call without a mov, the offset must fit a 32-bit immediate
+      //       see also CompilerToVM.getMaxCallTargetOffset()
+      NativeCall* call = nativeCall_at((address) (inst));
+      call->set_destination(VmIds::getStub(global_stub));
+      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+    } else if (inst->is_mov_literal64()) {
+      NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst));
+      mov->set_data((intptr_t) VmIds::getStub(global_stub));
+      _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
     } else {
-      nativeJump_at((address)inst)->set_jump_destination(VmIds::getStub(global_stub));
+      NativeJump* jump = nativeJump_at((address) (inst));
+      jump->set_jump_destination(VmIds::getStub(global_stub));
+      _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
     }
-    _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
     TRACE_graal_3("relocating (stub)  at %016x", inst);
   } else { // method != NULL
     assert(hotspot_method != NULL, "unexpected JavaMethod");
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Oct 05 15:54:08 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Fri Oct 05 17:55:12 2012 +0200
@@ -608,9 +608,8 @@
   return JNIHandles::make_local(THREAD, result());
 C2V_END
 
-C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jobject rtcall))
-  oop call = JNIHandles::resolve(rtcall);
-  address target_addr = CodeInstaller::runtime_call_target_address(call);
+C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jlong stub))
+  address target_addr = (address) stub;
   if (target_addr != 0x0) {
     int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int));
     int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int));
@@ -734,6 +733,22 @@
   set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorexit_id)));
   set_long(env, config, "verifyOopStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_oop_id)));
   set_long(env, config, "vmErrorStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_vm_error_id)));
+  set_long(env, config, "deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap()));
+  set_long(env, config, "unwindExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id)));
+  set_long(env, config, "registerFinalizerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::register_finalizer_id)));
+  set_long(env, config, "setDeoptInfoStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_set_deopt_info_id)));
+  set_long(env, config, "createNullPointerExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_create_null_pointer_exception_id)));
+  set_long(env, config, "createOutOfBoundsExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_create_out_of_bounds_exception_id)));
+  set_long(env, config, "javaTimeMillisStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeMillis)));
+  set_long(env, config, "javaTimeNanosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeNanos)));
+  set_long(env, config, "arithmeticFremStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_arithmetic_frem_id)));
+  set_long(env, config, "arithmeticDremStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_arithmetic_drem_id)));
+  set_long(env, config, "arithmeticSinStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dsin)));
+  set_long(env, config, "arithmeticCosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dcos)));
+  set_long(env, config, "arithmeticTanStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dtan)));
+  set_long(env, config, "logPrimitiveStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_log_primitive_id)));
+  set_long(env, config, "logObjectStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_log_printf_id)));
+  set_long(env, config, "logPrintfStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_log_object_id)));
 
 
   BarrierSet* bs = Universe::heap()->barrier_set();
@@ -976,7 +991,7 @@
   {CC"JavaType_isInitialized",              CC"("RESOLVED_TYPE")Z",                               FN_PTR(JavaType_isInitialized)},
 
   {CC"getPrimitiveArrayType",               CC"("KIND")"TYPE,                                     FN_PTR(getPrimitiveArrayType)},
-  {CC"getMaxCallTargetOffset",              CC"("RUNTIME_CALL")J",                                FN_PTR(getMaxCallTargetOffset)},
+  {CC"getMaxCallTargetOffset",              CC"(J)J",                                             FN_PTR(getMaxCallTargetOffset)},
   {CC"getType",                             CC"("CLASS")"TYPE,                                    FN_PTR(getType)},
   {CC"getJavaMethod",                       CC"("REFLECT_METHOD")"METHOD         ,                FN_PTR(getJavaMethod)},
   {CC"getJavaField",                        CC"("REFLECT_FIELD")"RESOLVED_FIELD,                  FN_PTR(getJavaField)},
--- a/src/share/vm/graal/graalJavaAccess.hpp	Fri Oct 05 15:54:08 2012 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Fri Oct 05 17:55:12 2012 +0200
@@ -187,26 +187,6 @@
     static_oop_field(Kind, Int, "Lcom/oracle/graal/api/meta/Kind;");                    \
     static_oop_field(Kind, Long, "Lcom/oracle/graal/api/meta/Kind;");                   \
   end_class                                                                             \
-  start_class(RuntimeCall)                                                            \
-    static_oop_field(RuntimeCall, UnwindException, "Lcom/oracle/graal/api/code/RuntimeCall;"); \
-    static_oop_field(RuntimeCall, RegisterFinalizer, "Lcom/oracle/graal/api/code/RuntimeCall;"); \
-    static_oop_field(RuntimeCall, SetDeoptInfo, "Lcom/oracle/graal/api/code/RuntimeCall;");    \
-    static_oop_field(RuntimeCall, CreateNullPointerException, "Lcom/oracle/graal/api/code/RuntimeCall;"); \
-    static_oop_field(RuntimeCall, CreateOutOfBoundsException, "Lcom/oracle/graal/api/code/RuntimeCall;"); \
-    static_oop_field(RuntimeCall, JavaTimeMillis, "Lcom/oracle/graal/api/code/RuntimeCall;");  \
-    static_oop_field(RuntimeCall, JavaTimeNanos, "Lcom/oracle/graal/api/code/RuntimeCall;");   \
-    static_oop_field(RuntimeCall, Debug, "Lcom/oracle/graal/api/code/RuntimeCall;");           \
-    static_oop_field(RuntimeCall, ArithmeticFrem, "Lcom/oracle/graal/api/code/RuntimeCall;");  \
-    static_oop_field(RuntimeCall, ArithmeticDrem, "Lcom/oracle/graal/api/code/RuntimeCall;");  \
-    static_oop_field(RuntimeCall, ArithmeticCos, "Lcom/oracle/graal/api/code/RuntimeCall;");   \
-    static_oop_field(RuntimeCall, ArithmeticTan, "Lcom/oracle/graal/api/code/RuntimeCall;");   \
-    static_oop_field(RuntimeCall, ArithmeticSin, "Lcom/oracle/graal/api/code/RuntimeCall;");   \
-    static_oop_field(RuntimeCall, Deoptimize, "Lcom/oracle/graal/api/code/RuntimeCall;");      \
-    static_oop_field(RuntimeCall, GenericCallback, "Lcom/oracle/graal/api/code/RuntimeCall;"); \
-    static_oop_field(RuntimeCall, LogPrintf, "Lcom/oracle/graal/api/code/RuntimeCall;");       \
-    static_oop_field(RuntimeCall, LogPrimitive, "Lcom/oracle/graal/api/code/RuntimeCall;");    \
-    static_oop_field(RuntimeCall, LogObject, "Lcom/oracle/graal/api/code/RuntimeCall;");       \
-  end_class                                                                             \
   start_class(JavaMethod)                                                                 \
   end_class                                                                             \
   start_class(Value)                                                                  \