changeset 9625:bce1c7759d9d

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 09 May 2013 11:32:08 +0200
parents 87eafaddf9d9 (current diff) ac96c2062de4 (diff)
children 29abc1e22280
files
diffstat 58 files changed, 754 insertions(+), 519 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Thu May 09 11:32:08 2013 +0200
@@ -326,9 +326,17 @@
     public static CallingConvention getCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, boolean stackOnly) {
         Signature sig = method.getSignature();
         JavaType retType = sig.getReturnType(null);
-        JavaType[] argTypes = new JavaType[sig.getParameterCount(!Modifier.isStatic(method.getModifiers()))];
-        for (int i = 0; i < argTypes.length; i++) {
-            argTypes[i] = sig.getParameterType(i, null);
+        int sigCount = sig.getParameterCount(false);
+        JavaType[] argTypes;
+        int argIndex = 0;
+        if (!Modifier.isStatic(method.getModifiers())) {
+            argTypes = new JavaType[sigCount + 1];
+            argTypes[argIndex++] = method.getDeclaringClass();
+        } else {
+            argTypes = new JavaType[sigCount];
+        }
+        for (int i = 0; i < sigCount; i++) {
+            argTypes[argIndex++] = sig.getParameterType(i, null);
         }
 
         RegisterConfig registerConfig = codeCache.lookupRegisterConfig();
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu May 09 11:32:08 2013 +0200
@@ -208,4 +208,11 @@
      * @return a constant representing a reference to this method
      */
     Constant getEncoding();
+
+    /**
+     * Checks if this method is present in the virtual table.
+     * 
+     * @return true is this method is present in the virtual table
+     */
+    boolean isInVirtualMethodTable();
 }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu May 09 11:32:08 2013 +0200
@@ -92,8 +92,8 @@
         }
     }
 
-    public AMD64LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        super(graph, runtime, target, frameMap, method, lir);
+    public AMD64LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        super(graph, runtime, target, frameMap, cc, lir);
         lir.spillMoveFactory = new AMD64SpillMoveFactory();
     }
 
@@ -919,8 +919,7 @@
             sig[i] = node.arguments.get(i).stamp().javaType(runtime);
         }
 
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false);
-        Value[] parameters = visitInvokeArguments(cc, node.arguments);
+        Value[] parameters = visitInvokeArguments(frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false), node.arguments);
         append(new AMD64BreakpointOp(parameters));
     }
 
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Thu May 09 11:32:08 2013 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.compiler.ptx.test;
 
+import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
-import com.oracle.graal.api.code.CompilationResult;
-import com.oracle.graal.api.code.SpeculationLog;
-import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.*;
 import com.oracle.graal.api.runtime.Graal;
 import com.oracle.graal.compiler.GraalCompiler;
 import com.oracle.graal.compiler.ptx.PTXBackend;
@@ -56,9 +56,9 @@
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase());
         new PTXPhase().apply(graph);
-        CompilationResult result = GraalCompiler.compileMethod(runtime, graalRuntime().getReplacements(),
-                                                               ptxBackend, target, graph.method(), graph, null, phasePlan,
-                                                               OptimisticOptimizations.NONE, new SpeculationLog());
+        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, graalRuntime().getReplacements(), ptxBackend, target, null, phasePlan, OptimisticOptimizations.NONE,
+                        new SpeculationLog());
         return result;
     }
 
@@ -71,7 +71,8 @@
         try {
             // not quite yet - need multi-architecture Method changes from JDK-8013168
             // Object[] executeArgs = argsWithReceiver(this, args);
-            // InstalledCode installedCode = runtime.addMethod(getStructuredGraph().method(), result);
+            // InstalledCode installedCode =
+            // runtime.addMethod(getStructuredGraph().method(), result);
             // installedCode.executeVarargs(executeArgs);
         } catch (Throwable th) {
             th.printStackTrace();
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Thu May 09 11:32:08 2013 +0200
@@ -42,8 +42,8 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        return new PTXLIRGenerator(graph, runtime(), target, frameMap, method, lir);
+    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        return new PTXLIRGenerator(graph, runtime(), target, frameMap, cc, lir);
     }
 
     class HotSpotFrameContext implements FrameContext {
@@ -79,16 +79,17 @@
     }
 
     @Override
-    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
+    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
         // Emit the prologue
-        final String name = method.getName();
+        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
+        final String name = codeCacheOwner.getName();
         Buffer codeBuffer = tasm.asm.codeBuffer;
         codeBuffer.emitString(".version 1.4");
         codeBuffer.emitString(".target sm_10");
         codeBuffer.emitString0(".entry " + name + " (");
         codeBuffer.emitString("");
 
-        Signature signature = method.getSignature();
+        Signature signature = codeCacheOwner.getSignature();
         for (int i = 0; i < signature.getParameterCount(false); i++) {
             String param = ".param .u32 param" + i;
             codeBuffer.emitString(param);
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu May 09 11:32:08 2013 +0200
@@ -28,11 +28,7 @@
 import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.ptx.PTXCompare.*;
 
-import com.oracle.graal.api.code.CodeCacheProvider;
-import com.oracle.graal.api.code.DeoptimizationAction;
-import com.oracle.graal.api.code.RuntimeCallTarget;
-import com.oracle.graal.api.code.StackSlot;
-import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.NumUtil;
@@ -85,8 +81,8 @@
         }
     }
 
-    public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        super(graph, runtime, target, frameMap, method, lir);
+    public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        super(graph, runtime, target, frameMap, cc, lir);
         lir.spillMoveFactory = new PTXSpillMoveFactory();
     }
 
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java	Thu May 09 11:32:08 2013 +0200
@@ -22,16 +22,14 @@
  */
 package com.oracle.graal.compiler.ptx;
 
-import com.oracle.graal.api.code.CodeCacheProvider;
-import com.oracle.graal.api.code.CompilationResult;
-import com.oracle.graal.api.code.TargetDescription;
-import com.oracle.graal.asm.AbstractAssembler;
-import com.oracle.graal.hotspot.HotSpotGraalRuntime;
-import com.oracle.graal.hotspot.bridge.CompilerToGPU;
-import com.oracle.graal.hotspot.meta.HotSpotMethod;
-import com.oracle.graal.lir.FrameMap;
-import com.oracle.graal.lir.asm.FrameContext;
-import com.oracle.graal.lir.asm.TargetMethodAssembler;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.*;
 
 public class PTXTargetMethodAssembler extends TargetMethodAssembler {
 
@@ -40,20 +38,18 @@
 
     // detach ??
 
-    public PTXTargetMethodAssembler(TargetDescription target,
-                                    CodeCacheProvider runtime, FrameMap frameMap,
-                                    AbstractAssembler asm, FrameContext frameContext,
-                                    CompilationResult compilationResult) {
+    public PTXTargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, CompilationResult compilationResult) {
         super(target, runtime, frameMap, asm, frameContext, compilationResult);
     }
 
     @Override
-    public CompilationResult finishTargetMethod(Object name, boolean isStub) {
-        CompilationResult graalCompile = super.finishTargetMethod(name, isStub);
+    public CompilationResult finishTargetMethod(StructuredGraph graph) {
+        ResolvedJavaMethod method = graph.method();
+        assert method != null : graph + " is not associated wth a method";
+        CompilationResult graalCompile = super.finishTargetMethod(graph);
 
         try {
             if (validDevice) {
-                HotSpotMethod method = (HotSpotMethod) name;
                 toGPU.generateKernel(graalCompile.getTargetCode(), method.getName());
             }
         } catch (Throwable th) {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu May 09 11:32:08 2013 +0200
@@ -38,8 +38,8 @@
  */
 public class SPARCLIRGenerator extends LIRGenerator {
 
-    public SPARCLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        super(graph, runtime, target, frameMap, method, lir);
+    public SPARCLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        super(graph, runtime, target, frameMap, cc, lir);
         // SPARC: Implement lir generator.
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu May 09 11:32:08 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.test;
 
+import static com.oracle.graal.api.code.CodeUtil.*;
+
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -29,6 +31,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.*;
@@ -410,7 +413,8 @@
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                 phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
                 editPhasePlan(method, graph, phasePlan);
-                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL,
+                CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+                CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
                                 new SpeculationLog());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Thu May 09 11:32:08 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.compiler.test;
 
+import static com.oracle.graal.api.code.CodeUtil.*;
 import static org.junit.Assert.*;
 
 import java.lang.reflect.*;
@@ -29,6 +30,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.compiler.*;
@@ -56,7 +58,8 @@
     public void callInfopoints() {
         final Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
-        final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(),
+        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, getDefaultPhasePlan(),
                         OptimisticOptimizations.ALL, new SpeculationLog());
         for (Infopoint sp : cr.getInfopoints()) {
             assertNotNull(sp.reason);
@@ -77,7 +80,8 @@
             }
         }
         assertTrue(graphLineSPs > 0);
-        final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(true),
+        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, getDefaultPhasePlan(true),
                         OptimisticOptimizations.ALL, new SpeculationLog());
         int lineSPs = 0;
         for (Infopoint sp : cr.getInfopoints()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Thu May 09 11:32:08 2013 +0200
@@ -22,12 +22,15 @@
  */
 package com.oracle.graal.compiler.test.backend;
 
+import static com.oracle.graal.api.code.CodeUtil.*;
+
 import java.util.*;
 import java.util.concurrent.*;
 
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.test.*;
@@ -123,7 +126,8 @@
 
             @Override
             public RegisterStats call() {
-                GraalCompiler.emitLIR(backend, backend.target, lir, graph, graph.method());
+                CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+                GraalCompiler.emitLIR(backend, backend.target, lir, graph, cc);
                 return new RegisterStats(lir);
             }
         });
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu May 09 11:32:08 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.compiler;
 
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -47,15 +46,26 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
+/**
+ * Static methods for orchestrating the compilation of a {@linkplain StructuredGraph graph}.
+ */
 public class GraalCompiler {
 
-    public static CompilationResult compileMethod(final GraalCodeCacheProvider runtime, final Replacements replacements, final Backend backend, final TargetDescription target,
-                    final ResolvedJavaMethod method, final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts,
+    /**
+     * Requests compilation of a given graph.
+     * 
+     * @param graph the graph to be compiled
+     * @param cc the calling convention for calls to the code compiled for {@code graph}
+     * @param installedCodeOwner the method the compiled code will be
+     *            {@linkplain InstalledCode#getMethod() associated} with once installed. This
+     *            argument can be null.
+     * @return the result of the compilation
+     */
+    public static CompilationResult compileGraph(final StructuredGraph graph, final CallingConvention cc, final ResolvedJavaMethod installedCodeOwner, final GraalCodeCacheProvider runtime,
+                    final Replacements replacements, final Backend backend, final TargetDescription target, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts,
                     final SpeculationLog speculationLog) {
-        assert (method.getModifiers() & Modifier.NATIVE) == 0 : "compiling native methods is not supported";
-
         final CompilationResult compilationResult = new CompilationResult();
-        Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Runnable() {
+        Debug.scope("GraalCompiler", new Object[]{graph, runtime}, new Runnable() {
 
             public void run() {
                 final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions);
@@ -68,13 +78,13 @@
                 final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
 
                     public LIRGenerator call() {
-                        return emitLIR(backend, target, lir, graph, method);
+                        return emitLIR(backend, target, lir, graph, cc);
                     }
                 });
                 Debug.scope("CodeGen", lirGen, new Runnable() {
 
                     public void run() {
-                        emitCode(backend, getLeafGraphIdArray(graph), assumptions, method, lirGen, compilationResult);
+                        emitCode(backend, getLeafGraphIdArray(graph), assumptions, lirGen, compilationResult, installedCodeOwner);
                     }
 
                 });
@@ -174,9 +184,9 @@
 
     }
 
-    public static LIRGenerator emitLIR(Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) {
+    public static LIRGenerator emitLIR(Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, CallingConvention cc) {
         final FrameMap frameMap = backend.newFrameMap();
-        final LIRGenerator lirGen = backend.newLIRGenerator(graph, frameMap, method, lir);
+        final LIRGenerator lirGen = backend.newLIRGenerator(graph, frameMap, cc, lir);
 
         Debug.scope("LIRGen", lirGen, new Runnable() {
 
@@ -205,16 +215,16 @@
         Debug.scope("Allocator", new Runnable() {
 
             public void run() {
-                new LinearScan(target, method, lir, lirGen, frameMap).allocate();
+                new LinearScan(target, lir, lirGen, frameMap).allocate();
             }
         });
         return lirGen;
     }
 
-    public static void emitCode(Backend backend, long[] leafGraphIds, Assumptions assumptions, ResolvedJavaMethod method, LIRGenerator lirGen, CompilationResult compilationResult) {
+    public static void emitCode(Backend backend, long[] leafGraphIds, Assumptions assumptions, LIRGenerator lirGen, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner) {
         TargetMethodAssembler tasm = backend.newAssembler(lirGen, compilationResult);
-        backend.emitCode(tasm, method, lirGen);
-        CompilationResult result = tasm.finishTargetMethod(method, false);
+        backend.emitCode(tasm, lirGen, installedCodeOwner);
+        CompilationResult result = tasm.finishTargetMethod(lirGen.getGraph());
         if (!assumptions.isEmpty()) {
             result.setAssumptions(assumptions);
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Thu May 09 11:32:08 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 
@@ -94,6 +95,24 @@
         return filter != null && filter.matches(currentScope);
     }
 
+    /**
+     * Extracts a {@link JavaMethod} from an opaque debug context.
+     * 
+     * @return the {@link JavaMethod} represented by {@code context} or null
+     */
+    public static JavaMethod asJavaMethod(Object context) {
+        if (context instanceof JavaMethod) {
+            return (JavaMethod) context;
+        }
+        if (context instanceof StructuredGraph) {
+            ResolvedJavaMethod method = ((StructuredGraph) context).method();
+            if (method != null) {
+                return method;
+            }
+        }
+        return null;
+    }
+
     private boolean checkMethodFilter() {
         if (methodFilter == null && extraFilters.isEmpty()) {
             return true;
@@ -102,9 +121,10 @@
                 if (extraFilters.contains(o)) {
                     return true;
                 } else if (methodFilter != null) {
-                    if (o instanceof JavaMethod) {
+                    JavaMethod method = asJavaMethod(o);
+                    if (method != null) {
                         for (MethodFilter filter : methodFilter) {
-                            if (filter.matches((JavaMethod) o)) {
+                            if (filter.matches(method)) {
                                 return true;
                             }
                         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu May 09 11:32:08 2013 +0200
@@ -56,7 +56,6 @@
 public final class LinearScan {
 
     final TargetDescription target;
-    final JavaMethod method;
     final LIR ir;
     final LIRGenerator gen;
     final FrameMap frameMap;
@@ -156,9 +155,8 @@
      */
     private final int firstVariableNumber;
 
-    public LinearScan(TargetDescription target, ResolvedJavaMethod method, LIR ir, LIRGenerator gen, FrameMap frameMap) {
+    public LinearScan(TargetDescription target, LIR ir, LIRGenerator gen, FrameMap frameMap) {
         this.target = target;
-        this.method = method;
         this.ir = ir;
         this.gen = gen;
         this.frameMap = frameMap;
@@ -884,7 +882,7 @@
     }
 
     private void reportFailure(int numBlocks) {
-        TTY.println(method.toString());
+        TTY.println(gen.getGraph().toString());
         TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined)");
         TTY.print("affected registers:");
         TTY.println(blockData.get(ir.cfg.getStartBlock()).liveIn.toString());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu May 09 11:32:08 2013 +0200
@@ -61,7 +61,7 @@
     protected final StructuredGraph graph;
     protected final CodeCacheProvider runtime;
     protected final TargetDescription target;
-    protected final ResolvedJavaMethod method;
+    protected final CallingConvention cc;
 
     protected final DebugInfoBuilder debugInfoBuilder;
 
@@ -85,12 +85,18 @@
      */
     public abstract boolean canStoreConstant(Constant c);
 
-    public LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
+    public LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
         this.graph = graph;
         this.runtime = runtime;
         this.target = target;
         this.frameMap = frameMap;
-        this.method = method;
+        if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
+            this.cc = cc;
+        } else {
+            JavaType[] parameterTypes = new JavaType[]{runtime.lookupJavaType(long.class)};
+            CallingConvention tmp = frameMap.registerConfig.getCallingConvention(JavaCallee, runtime.lookupJavaType(void.class), parameterTypes, target, false);
+            this.cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0));
+        }
         this.nodeOperands = graph.createNodeMap();
         this.lir = lir;
         this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands);
@@ -112,8 +118,8 @@
         return runtime;
     }
 
-    public ResolvedJavaMethod method() {
-        return method;
+    public StructuredGraph getGraph() {
+        return graph;
     }
 
     /**
@@ -423,12 +429,8 @@
         ((LIRLowerable) node).generate(this);
     }
 
-    protected CallingConvention createCallingConvention() {
-        return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), MetaUtil.signatureToTypes(method), target, false);
-    }
-
     protected void emitPrologue() {
-        CallingConvention incomingArguments = createCallingConvention();
+        CallingConvention incomingArguments = cc;
 
         Value[] params = new Value[incomingArguments.getArgumentCount()];
         for (int i = 0; i < params.length; i++) {
@@ -594,10 +596,10 @@
     @Override
     public void emitInvoke(Invoke x) {
         LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget();
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(runtime), callTarget.signature(), target(), false);
-        frameMap.callsMethod(cc);
+        CallingConvention invokeCc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(runtime), callTarget.signature(), target(), false);
+        frameMap.callsMethod(invokeCc);
 
-        Value[] parameters = visitInvokeArguments(cc, callTarget.arguments());
+        Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments());
 
         LabelRef exceptionEdge = null;
         if (x instanceof InvokeWithExceptionNode) {
@@ -605,11 +607,11 @@
         }
         LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge);
 
-        Value result = cc.getReturn();
+        Value result = invokeCc.getReturn();
         if (callTarget instanceof DirectCallTargetNode) {
-            emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, cc.getTemporaries(), callState);
+            emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, invokeCc.getTemporaries(), callState);
         } else if (callTarget instanceof IndirectCallTargetNode) {
-            emitIndirectCall((IndirectCallTargetNode) callTarget, result, parameters, cc.getTemporaries(), callState);
+            emitIndirectCall((IndirectCallTargetNode) callTarget, result, parameters, invokeCc.getTemporaries(), callState);
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -640,13 +642,13 @@
         return value;
     }
 
-    public Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments) {
+    public Value[] visitInvokeArguments(CallingConvention invokeCc, Collection<ValueNode> arguments) {
         // for each argument, load it into the correct location
         Value[] result = new Value[arguments.size()];
         int j = 0;
         for (ValueNode arg : arguments) {
             if (arg != null) {
-                AllocatableValue operand = toStackKind(cc.getArgument(j));
+                AllocatableValue operand = toStackKind(invokeCc.getArgument(j));
                 emitMove(operand, operand(arg));
                 result[j] = operand;
                 j++;
@@ -658,23 +660,23 @@
     }
 
     @Override
-    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args) {
+    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention callCc, DeoptimizingNode info, Value... args) {
         LIRFrameState state = info != null ? state(info) : null;
 
         // move the arguments into the correct location
-        frameMap.callsMethod(cc);
-        assert cc.getArgumentCount() == args.length : "argument count mismatch";
+        frameMap.callsMethod(callCc);
+        assert callCc.getArgumentCount() == args.length : "argument count mismatch";
         Value[] argLocations = new Value[args.length];
         for (int i = 0; i < args.length; i++) {
             Value arg = args[i];
-            AllocatableValue loc = cc.getArgument(i);
+            AllocatableValue loc = callCc.getArgument(i);
             emitMove(loc, arg);
             argLocations[i] = loc;
         }
-        emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), state);
+        emitCall(callTarget, callCc.getReturn(), argLocations, callCc.getTemporaries(), state);
 
-        if (isLegal(cc.getReturn())) {
-            return emitMove(cc.getReturn());
+        if (isLegal(callCc.getReturn())) {
+            return emitMove(callCc.getReturn());
         } else {
             return null;
         }
@@ -683,12 +685,12 @@
     @Override
     public void visitRuntimeCall(RuntimeCallNode x) {
         RuntimeCallTarget call = runtime.lookupRuntimeCall(x.getDescriptor());
-        CallingConvention cc = call.getCallingConvention();
-        frameMap.callsMethod(cc);
-        Value resultOperand = cc.getReturn();
-        Value[] args = visitInvokeArguments(cc, x.arguments());
+        CallingConvention callCc = call.getCallingConvention();
+        frameMap.callsMethod(callCc);
+        Value resultOperand = callCc.getReturn();
+        Value[] args = visitInvokeArguments(callCc, x.arguments());
 
-        emitCall(call, resultOperand, args, cc.getTemporaries(), state(x));
+        emitCall(call, resultOperand, args, callCc.getTemporaries(), state(x));
 
         if (isLegal(resultOperand)) {
             setResult(x, emitMove(resultOperand));
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu May 09 11:32:08 2013 +0200
@@ -51,17 +51,18 @@
         return new FrameMap(runtime, target, runtime.lookupRegisterConfig());
     }
 
-    public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir);
+    public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir);
 
     protected abstract AbstractAssembler createAssembler(FrameMap frameMap);
 
     public abstract TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult);
 
     /**
-     * Emits the code for a given method. This includes any architecture/runtime specific
-     * prefix/suffix. A prefix typically contains the code for setting up the frame, spilling
-     * callee-save registers, stack overflow checking, handling multiple entry points etc. A suffix
-     * may contain out-of-line stubs and method end guard instructions.
+     * Emits the code for a given graph.
+     * 
+     * @param installedCodeOwner the method the compiled code will be
+     *            {@linkplain InstalledCode#getMethod() associated} with once installed. This
+     *            argument can be null.
      */
-    public abstract void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen);
+    public abstract void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner);
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu May 09 11:32:08 2013 +0200
@@ -26,8 +26,8 @@
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.phases.GraalOptions.*;
+import static java.lang.reflect.Modifier.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import sun.misc.*;
@@ -64,8 +64,8 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        return new AMD64HotSpotLIRGenerator(graph, runtime(), target, frameMap, method, lir);
+    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        return new AMD64HotSpotLIRGenerator(graph, runtime(), target, frameMap, cc, lir);
     }
 
     /**
@@ -160,7 +160,7 @@
         LIR lir = gen.lir;
         boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
 
-        Stub stub = runtime().asStub(lirGen.method());
+        Stub stub = gen.getStub();
         AbstractAssembler masm = createAssembler(frameMap);
         HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(stub != null);
         TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult);
@@ -219,17 +219,16 @@
     }
 
     @Override
-    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
+    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) {
         AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
         FrameMap frameMap = tasm.frameMap;
         RegisterConfig regConfig = frameMap.registerConfig;
         HotSpotVMConfig config = runtime().config;
-        boolean isStatic = Modifier.isStatic(method.getModifiers());
-        Label unverifiedStub = isStatic ? null : new Label();
+        Label unverifiedStub = installedCodeOwner == null || isStatic(installedCodeOwner.getModifiers()) ? null : new Label();
 
         // Emit the prefix
 
-        if (!isStatic) {
+        if (unverifiedStub != null) {
             tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
             CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{runtime().lookupJavaType(Object.class)}, target, false);
             Register inlineCacheKlass = rax; // see definition of IC_Klass in
@@ -257,7 +256,7 @@
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
-            assert !frameMap.accessesCallerFrame() : method;
+            assert !frameMap.accessesCallerFrame() : lirGen.getGraph();
         }
 
         if (unverifiedStub != null) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu May 09 11:32:08 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.amd64.AMD64.*;
-import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 
@@ -60,8 +59,8 @@
         return (HotSpotRuntime) runtime;
     }
 
-    protected AMD64HotSpotLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        super(graph, runtime, target, frameMap, method, lir);
+    protected AMD64HotSpotLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        super(graph, runtime, target, frameMap, cc, lir);
     }
 
     /**
@@ -139,7 +138,7 @@
     @Override
     protected void emitPrologue() {
 
-        CallingConvention incomingArguments = createCallingConvention();
+        CallingConvention incomingArguments = cc;
 
         RegisterValue rbpParam = rbp.asValue(Kind.Long);
         Value[] params = new Value[incomingArguments.getArgumentCount() + 1];
@@ -175,7 +174,7 @@
     @Override
     protected boolean needOnlyOopMaps() {
         // Stubs only need oop maps
-        return runtime().asStub(method) != null;
+        return graph.start() instanceof StubStartNode;
     }
 
     /**
@@ -202,11 +201,18 @@
         append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save));
     }
 
+    Stub getStub() {
+        if (graph.start() instanceof StubStartNode) {
+            return ((StubStartNode) graph.start()).getStub();
+        }
+        return null;
+    }
+
     @Override
-    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args) {
-        Stub stub = runtime().asStub(method);
+    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention callCc, DeoptimizingNode info, Value... args) {
+        Stub stub = getStub();
         boolean isCRuntimeCall = ((HotSpotRuntimeCallTarget) callTarget).isCRuntimeCall();
-        assert !isCRuntimeCall || stub != null : "direct call to C runtime can only be made from compiled stubs, not from " + method;
+        assert !isCRuntimeCall || stub != null : "direct call to C runtime can only be made from compiled stubs, not from " + graph;
 
         AMD64SaveRegistersOp save = null;
         StackSlot[] savedRegisterLocations = null;
@@ -225,7 +231,7 @@
             append(new AMD64HotSpotCRuntimeCallPrologueOp());
         }
 
-        Variable result = super.emitCall(callTarget, cc, info, args);
+        Variable result = super.emitCall(callTarget, callCc, info, args);
 
         if (isCRuntimeCall) {
             append(new AMD64HotSpotCRuntimeCallEpilogueOp());
@@ -261,20 +267,6 @@
     }
 
     @Override
-    protected CallingConvention createCallingConvention() {
-        Stub stub = runtime().asStub(method);
-        if (stub != null) {
-            return stub.getLinkage().getCallingConvention();
-        }
-
-        if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
-            return super.createCallingConvention();
-        } else {
-            return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), new JavaType[]{runtime.lookupJavaType(long.class)}, target, false);
-        }
-    }
-
-    @Override
     public void visitSafepointNode(SafepointNode i) {
         LIRFrameState info = state(i);
         append(new AMD64SafepointOp(info, runtime().config, this));
@@ -340,9 +332,9 @@
     @Override
     public void emitUnwind(Value exception) {
         RuntimeCallTarget stub = getRuntime().lookupRuntimeCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER);
-        CallingConvention cc = stub.getCallingConvention();
-        assert cc.getArgumentCount() == 2;
-        RegisterValue exceptionParameter = (RegisterValue) cc.getArgument(0);
+        CallingConvention stubCc = stub.getCallingConvention();
+        assert stubCc.getArgumentCount() == 2;
+        RegisterValue exceptionParameter = (RegisterValue) stubCc.getArgument(0);
         emitMove(exceptionParameter, exception);
         append(new AMD64HotSpotUnwindOp(exceptionParameter));
     }
@@ -366,10 +358,10 @@
     public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
         Variable handler = load(operand(handlerInCallerPc));
         RuntimeCallTarget stub = getRuntime().lookupRuntimeCall(EXCEPTION_HANDLER_IN_CALLER);
-        CallingConvention cc = stub.getCallingConvention();
-        assert cc.getArgumentCount() == 2;
-        RegisterValue exceptionFixed = (RegisterValue) cc.getArgument(0);
-        RegisterValue exceptionPcFixed = (RegisterValue) cc.getArgument(1);
+        CallingConvention stubCc = stub.getCallingConvention();
+        assert stubCc.getArgumentCount() == 2;
+        RegisterValue exceptionFixed = (RegisterValue) stubCc.getArgument(0);
+        RegisterValue exceptionPcFixed = (RegisterValue) stubCc.getArgument(1);
         emitMove(exceptionFixed, operand(exception));
         emitMove(exceptionPcFixed, operand(exceptionPc));
         AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu May 09 11:32:08 2013 +0200
@@ -43,8 +43,8 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        return new SPARCLIRGenerator(graph, this.runtime(), this.target, frameMap, method, lir);
+    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        return new SPARCLIRGenerator(graph, this.runtime(), this.target, frameMap, cc, lir);
     }
 
     @Override
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
+    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
         // SPARC: Emit code
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu May 09 11:32:08 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
 import static com.oracle.graal.phases.common.InliningUtil.*;
 
@@ -29,6 +30,7 @@
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
@@ -157,8 +159,10 @@
                             graph = graph.copy();
                         }
                         InlinedBytecodes.add(method.getCodeSize());
-                        return GraalCompiler.compileMethod(graalRuntime.getRuntime(), replacements, graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan,
-                                        optimisticOpts, method.getSpeculationLog());
+                        HotSpotRuntime runtime = graalRuntime.getRuntime();
+                        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+                        return GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, graalRuntime.getBackend(), graalRuntime.getTarget(), graalRuntime.getCache(), plan, optimisticOpts,
+                                        method.getSpeculationLog());
                     }
                 });
             } finally {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Thu May 09 11:32:08 2013 +0200
@@ -74,7 +74,7 @@
 
     @Override
     public String toString() {
-        return (stub == null ? descriptor.toString() : MetaUtil.format("%h.%n", stub.getMethod())) + "@0x" + Long.toHexString(address) + ":" + cc;
+        return (stub == null ? descriptor.toString() : stub) + "@0x" + Long.toHexString(address) + ":" + cc;
     }
 
     public CallingConvention getCallingConvention() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu May 09 11:32:08 2013 +0200
@@ -210,6 +210,8 @@
 
     int getVtableEntryOffset(long metaspaceMethod);
 
+    boolean hasVtableEntry(long metaspaceMethod);
+
     long[] getDeoptedLeafGraphIds();
 
     long[] getLineNumberTable(HotSpotResolvedJavaMethod method);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu May 09 11:32:08 2013 +0200
@@ -145,6 +145,9 @@
     public native int getVtableEntryOffset(long metaspaceMethod);
 
     @Override
+    public native boolean hasVtableEntry(long metaspaceMethod);
+
+    @Override
     public native long[] getDeoptedLeafGraphIds();
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu May 09 11:32:08 2013 +0200
@@ -383,7 +383,8 @@
 
     /**
      * Returns the offset of this method into the v-table. If the holder is not initialized, returns
-     * -1
+     * -1. If it is initialized the method must have a v-table entry has indicated by
+     * {@link #hasVtableEntry()}.
      * 
      * @return the offset of this method into the v-table
      */
@@ -394,6 +395,10 @@
         return graalRuntime().getCompilerToVM().getVtableEntryOffset(metaspaceMethod);
     }
 
+    public boolean hasVtableEntry() {
+        return graalRuntime().getCompilerToVM().hasVtableEntry(metaspaceMethod);
+    }
+
     public void setCurrentTask(CompilationTask task) {
         currentTask = task;
     }
@@ -455,4 +460,9 @@
             throw new IllegalArgumentException(ex);
         }
     }
+
+    @Override
+    public boolean isInVirtualMethodTable() {
+        return hasVtableEntry();
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu May 09 11:32:08 2013 +0200
@@ -56,6 +56,7 @@
 import static com.oracle.graal.hotspot.stubs.NewMultiArrayStub.*;
 import static com.oracle.graal.hotspot.stubs.OSRMigrationEndStub.*;
 import static com.oracle.graal.hotspot.stubs.RegisterFinalizerStub.*;
+import static com.oracle.graal.hotspot.stubs.StubUtil.*;
 import static com.oracle.graal.hotspot.stubs.ThreadIsInterruptedStub.*;
 import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*;
 import static com.oracle.graal.hotspot.stubs.VMErrorStub.*;
@@ -123,7 +124,6 @@
     private LoadExceptionObjectSnippets.Templates exceptionObjectSnippets;
 
     private final Map<Descriptor, HotSpotRuntimeCallTarget> runtimeCalls = new HashMap<>();
-    private final Map<ResolvedJavaMethod, Stub> stubs = new HashMap<>();
 
     /**
      * The offset from the origin of an array to the first element.
@@ -577,31 +577,30 @@
         boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget());
         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget());
 
-        registerStub(new NewInstanceStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_INSTANCE)));
-        registerStub(new NewArrayStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_ARRAY)));
-        registerStub(new NewMultiArrayStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_MULTI_ARRAY)));
-        registerStub(new RegisterFinalizerStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(REGISTER_FINALIZER)));
-        registerStub(new ThreadIsInterruptedStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(THREAD_IS_INTERRUPTED)));
-        registerStub(new IdentityHashCodeStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(IDENTITY_HASHCODE)));
-        registerStub(new ExceptionHandlerStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(EXCEPTION_HANDLER)));
-        registerStub(new UnwindExceptionToCallerStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(UNWIND_EXCEPTION_TO_CALLER)));
-        registerStub(new VerifyOopStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(VERIFY_OOP)));
-        registerStub(new OSRMigrationEndStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(OSR_MIGRATION_END)));
-        registerStub(new MonitorEnterStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(MONITORENTER)));
-        registerStub(new MonitorExitStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(MONITOREXIT)));
-        registerStub(new CreateNullPointerExceptionStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(CREATE_NULL_POINTER_EXCEPTION)));
-        registerStub(new CreateOutOfBoundsExceptionStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(CREATE_OUT_OF_BOUNDS_EXCEPTION)));
-        registerStub(new LogPrimitiveStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_PRIMITIVE)));
-        registerStub(new LogObjectStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_OBJECT)));
-        registerStub(new LogPrintfStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_PRINTF)));
-        registerStub(new VMErrorStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(VM_ERROR)));
-        registerStub(new WriteBarrierPreStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(WRITE_BARRIER_PRE)));
-        registerStub(new WriteBarrierPostStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(WRITE_BARRIER_POST)));
+        link(new NewInstanceStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_INSTANCE)));
+        link(new NewArrayStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_ARRAY)));
+        link(new NewMultiArrayStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_MULTI_ARRAY)));
+        link(new RegisterFinalizerStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(REGISTER_FINALIZER)));
+        link(new ThreadIsInterruptedStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(THREAD_IS_INTERRUPTED)));
+        link(new IdentityHashCodeStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(IDENTITY_HASHCODE)));
+        link(new ExceptionHandlerStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(EXCEPTION_HANDLER)));
+        link(new UnwindExceptionToCallerStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(UNWIND_EXCEPTION_TO_CALLER)));
+        link(new VerifyOopStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(VERIFY_OOP)));
+        link(new OSRMigrationEndStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(OSR_MIGRATION_END)));
+        link(new MonitorEnterStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(MONITORENTER)));
+        link(new MonitorExitStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(MONITOREXIT)));
+        link(new CreateNullPointerExceptionStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(CREATE_NULL_POINTER_EXCEPTION)));
+        link(new CreateOutOfBoundsExceptionStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(CREATE_OUT_OF_BOUNDS_EXCEPTION)));
+        link(new LogPrimitiveStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_PRIMITIVE)));
+        link(new LogObjectStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_OBJECT)));
+        link(new LogPrintfStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(LOG_PRINTF)));
+        link(new VMErrorStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(VM_ERROR)));
+        link(new WriteBarrierPreStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(WRITE_BARRIER_PRE)));
+        link(new WriteBarrierPostStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(WRITE_BARRIER_POST)));
     }
 
-    private void registerStub(Stub stub) {
+    private static void link(Stub stub) {
         stub.getLinkage().setStub(stub);
-        stubs.put(stub.getMethod(), stub);
     }
 
     public HotSpotGraalRuntime getGraalRuntime() {
@@ -773,8 +772,8 @@
 
                     HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
                     if (!hsMethod.getDeclaringClass().isInterface()) {
-                        int vtableEntryOffset = hsMethod.vtableEntryOffset();
-                        if (vtableEntryOffset > 0) {
+                        if (hsMethod.hasVtableEntry()) {
+                            int vtableEntryOffset = hsMethod.vtableEntryOffset();
                             assert vtableEntryOffset > 0;
                             ReadNode hub = this.createReadHub(tool, graph, wordKind, receiver);
                             ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod);
@@ -1049,6 +1048,7 @@
     private static ReadNode createReadVirtualMethod(StructuredGraph graph, Kind wordKind, ValueNode hub, ResolvedJavaMethod method) {
         HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
         assert !hsMethod.getDeclaringClass().isInterface();
+        assert hsMethod.hasVtableEntry();
 
         int vtableEntryOffset = hsMethod.vtableEntryOffset();
         assert vtableEntryOffset > 0;
@@ -1130,16 +1130,6 @@
         return HotSpotResolvedObjectType.fromClass(clazz);
     }
 
-    /**
-     * Gets the stub corresponding to a given method.
-     * 
-     * @return the stub {@linkplain Stub#getMethod() implemented} by {@code method} or null if
-     *         {@code method} does not implement a stub
-     */
-    public Stub asStub(ResolvedJavaMethod method) {
-        return stubs.get(method);
-    }
-
     public HotSpotRuntimeCallTarget lookupRuntimeCall(Descriptor descriptor) {
         HotSpotRuntimeCallTarget callTarget = runtimeCalls.get(descriptor);
         assert runtimeCalls != null : descriptor;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java	Thu May 09 11:32:08 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Start node for a {@link Stub}'s graph.
+ */
+public class StubStartNode extends StartNode {
+
+    private final Stub stub;
+
+    public StubStartNode(Stub stub) {
+        this.stub = stub;
+    }
+
+    public Stub getStub() {
+        return stub;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        String whereString = "in compiled code for " + MetaUtil.format("%H.%n(%p)", gen.method());
+        String whereString = "in compiled code for " + graph();
 
         // As these strings will end up embedded as oops in the code, they
         // must be interned or else they will cause the nmethod to be unloaded
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/CRuntimeStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/CRuntimeStub.java	Thu May 09 11:32:08 2013 +0200
@@ -32,7 +32,7 @@
 /**
  * Base class for a stub that saves registers around a C runtime call.
  */
-public abstract class CRuntimeStub extends Stub {
+public abstract class CRuntimeStub extends SnippetStub {
 
     public CRuntimeStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
         super(runtime, replacements, target, linkage);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/CreateNullPointerExceptionStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/CreateNullPointerExceptionStub.java	Thu May 09 11:32:08 2013 +0200
@@ -46,11 +46,11 @@
     @Snippet
     private static Object createNullPointerException() {
         createNullPointerExceptionC(CREATE_NULL_POINTER_EXCEPTION_C, thread());
-        handlePendingException(true);
-        return verifyObject(getAndClearObjectResult(thread()));
+        StubUtil.handlePendingException(true);
+        return StubUtil.verifyObject(getAndClearObjectResult(thread()));
     }
 
-    public static final Descriptor CREATE_NULL_POINTER_EXCEPTION_C = descriptorFor(CreateNullPointerExceptionStub.class, "createNullPointerExceptionC", false);
+    public static final Descriptor CREATE_NULL_POINTER_EXCEPTION_C = StubUtil.descriptorFor(CreateNullPointerExceptionStub.class, "createNullPointerExceptionC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void createNullPointerExceptionC(@ConstantNodeParameter Descriptor createNullPointerExceptionC, Word thread);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/CreateOutOfBoundsExceptionStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/CreateOutOfBoundsExceptionStub.java	Thu May 09 11:32:08 2013 +0200
@@ -46,11 +46,11 @@
     @Snippet
     private static Object createOutOfBoundsException(int index) {
         createOutOfBoundsExceptionC(CREATE_OUT_OF_BOUNDS_C, thread(), index);
-        handlePendingException(true);
-        return verifyObject(getAndClearObjectResult(thread()));
+        StubUtil.handlePendingException(true);
+        return StubUtil.verifyObject(getAndClearObjectResult(thread()));
     }
 
-    public static final Descriptor CREATE_OUT_OF_BOUNDS_C = descriptorFor(CreateOutOfBoundsExceptionStub.class, "createOutOfBoundsExceptionC", false);
+    public static final Descriptor CREATE_OUT_OF_BOUNDS_C = StubUtil.descriptorFor(CreateOutOfBoundsExceptionStub.class, "createOutOfBoundsExceptionC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void createOutOfBoundsExceptionC(@ConstantNodeParameter Descriptor createOutOfBoundsExceptionC, Word thread, int index);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java	Thu May 09 11:32:08 2013 +0200
@@ -70,11 +70,11 @@
         writeExceptionOop(thread(), exception);
         writeExceptionPc(thread(), exceptionPc);
         if (logging()) {
-            printf("handling exception %p (", Word.fromObject(exception).rawValue());
-            decipher(Word.fromObject(exception).rawValue());
-            printf(") at %p (", Word.fromObject(exception).rawValue(), exceptionPc.rawValue());
-            decipher(exceptionPc.rawValue());
-            printf(")\n");
+            StubUtil.printf("handling exception %p (", Word.fromObject(exception).rawValue());
+            StubUtil.decipher(Word.fromObject(exception).rawValue());
+            StubUtil.printf(") at %p (", Word.fromObject(exception).rawValue(), exceptionPc.rawValue());
+            StubUtil.decipher(exceptionPc.rawValue());
+            StubUtil.printf(")\n");
         }
 
         // patch throwing pc into return address so that deoptimization finds the right debug info
@@ -83,9 +83,9 @@
         Word handlerPc = exceptionHandlerForPc(EXCEPTION_HANDLER_FOR_PC, thread());
 
         if (logging()) {
-            printf("handler for exception %p at %p is at %p (", Word.fromObject(exception).rawValue(), exceptionPc.rawValue(), handlerPc.rawValue());
-            decipher(handlerPc.rawValue());
-            printf(")\n");
+            StubUtil.printf("handler for exception %p at %p is at %p (", Word.fromObject(exception).rawValue(), exceptionPc.rawValue(), handlerPc.rawValue());
+            StubUtil.decipher(handlerPc.rawValue());
+            StubUtil.printf(")\n");
         }
 
         // patch the return address so that this stub returns to the exception handler
@@ -96,18 +96,18 @@
         if (enabled) {
             Object currentException = readExceptionOop(thread());
             if (currentException != null) {
-                fatal("exception object in thread must be null, not %p", Word.fromObject(currentException).rawValue());
+                StubUtil.fatal("exception object in thread must be null, not %p", Word.fromObject(currentException).rawValue());
             }
             Word currentExceptionPc = readExceptionPc(thread());
             if (currentExceptionPc.notEqual(Word.zero())) {
-                fatal("exception PC in thread must be zero, not %p", currentExceptionPc.rawValue());
+                StubUtil.fatal("exception PC in thread must be zero, not %p", currentExceptionPc.rawValue());
             }
         }
     }
 
     static void checkExceptionNotNull(boolean enabled, Object exception) {
         if (enabled && exception == null) {
-            fatal("exception must not be null");
+            StubUtil.fatal("exception must not be null");
         }
     }
 
@@ -124,7 +124,7 @@
         return enabled || graalRuntime().getConfig().cAssertions;
     }
 
-    public static final Descriptor EXCEPTION_HANDLER_FOR_PC = descriptorFor(ExceptionHandlerStub.class, "exceptionHandlerForPc", false);
+    public static final Descriptor EXCEPTION_HANDLER_FOR_PC = StubUtil.descriptorFor(ExceptionHandlerStub.class, "exceptionHandlerForPc", false);
 
     @NodeIntrinsic(value = CRuntimeCall.class, setStampFromReturnType = true)
     public static native Word exceptionHandlerForPc(@ConstantNodeParameter Descriptor exceptionHandlerForPc, Word thread);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/IdentityHashCodeStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/IdentityHashCodeStub.java	Thu May 09 11:32:08 2013 +0200
@@ -47,11 +47,11 @@
     @Snippet
     private static int identityHashCode(Object object) {
         int result = identityHashCodeC(IDENTITY_HASH_CODE_C, thread(), object);
-        handlePendingException(false);
+        StubUtil.handlePendingException(false);
         return result;
     }
 
-    public static final Descriptor IDENTITY_HASH_CODE_C = descriptorFor(IdentityHashCodeStub.class, "identityHashCodeC", false);
+    public static final Descriptor IDENTITY_HASH_CODE_C = StubUtil.descriptorFor(IdentityHashCodeStub.class, "identityHashCodeC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native int identityHashCodeC(@ConstantNodeParameter Descriptor identityHashCodeC, Word thread, Object object);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/LogObjectStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/LogObjectStub.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
         logObjectC(LOG_OBJECT_C, thread(), object, flags);
     }
 
-    public static final Descriptor LOG_OBJECT_C = descriptorFor(LogObjectStub.class, "logObjectC", false);
+    public static final Descriptor LOG_OBJECT_C = StubUtil.descriptorFor(LogObjectStub.class, "logObjectC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void logObjectC(@ConstantNodeParameter Descriptor logObjectC, Word thread, Object object, int flags);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/LogPrimitiveStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/LogPrimitiveStub.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
         logPrimitivefC(LOG_PRIMITIVE_C, thread(), typeChar, value, newline);
     }
 
-    public static final Descriptor LOG_PRIMITIVE_C = descriptorFor(LogPrimitiveStub.class, "logPrimitivefC", false);
+    public static final Descriptor LOG_PRIMITIVE_C = StubUtil.descriptorFor(LogPrimitiveStub.class, "logPrimitivefC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void logPrimitivefC(@ConstantNodeParameter Descriptor logPrimitivefC, Word thread, char typeChar, long value, boolean newline);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/LogPrintfStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/LogPrintfStub.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
         logPrintfC(LOG_PRINTF_C, thread(), format, v1, v2, v3);
     }
 
-    public static final Descriptor LOG_PRINTF_C = descriptorFor(LogPrintfStub.class, "logPrintfC", false);
+    public static final Descriptor LOG_PRINTF_C = StubUtil.descriptorFor(LogPrintfStub.class, "logPrintfC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void logPrintfC(@ConstantNodeParameter Descriptor logPrintfC, Word thread, String format, long v1, long v2, long v3);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/MonitorEnterStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/MonitorEnterStub.java	Thu May 09 11:32:08 2013 +0200
@@ -47,10 +47,10 @@
     @Snippet
     private static void monitorenter(Object object, Word lock) {
         monitorenterC(MONITORENTER_C, thread(), object, lock);
-        handlePendingException(false);
+        StubUtil.handlePendingException(false);
     }
 
-    public static final Descriptor MONITORENTER_C = descriptorFor(MonitorEnterStub.class, "monitorenterC", false);
+    public static final Descriptor MONITORENTER_C = StubUtil.descriptorFor(MonitorEnterStub.class, "monitorenterC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void monitorenterC(@ConstantNodeParameter Descriptor monitorenterC, Word thread, Object object, Word lock);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/MonitorExitStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/MonitorExitStub.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
         monitorexitC(MONITOREXIT_C, thread(), object, lock);
     }
 
-    public static final Descriptor MONITOREXIT_C = descriptorFor(MonitorExitStub.class, "monitorexitC", false);
+    public static final Descriptor MONITOREXIT_C = StubUtil.descriptorFor(MonitorExitStub.class, "monitorexitC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void monitorexitC(@ConstantNodeParameter Descriptor monitorexitC, Word thread, Object object, Word lock);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Thu May 09 11:32:08 2013 +0200
@@ -50,7 +50,7 @@
  * code when TLAB allocation fails. If this stub fails to refill the TLAB or allocate the object, it
  * calls out to the HotSpot C++ runtime to complete the allocation.
  */
-public class NewArrayStub extends Stub {
+public class NewArrayStub extends SnippetStub {
 
     public NewArrayStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
         super(runtime, replacements, target, linkage);
@@ -94,10 +94,10 @@
         int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask();
         int sizeInBytes = computeArrayAllocationSize(length, wordSize(), headerSize, log2ElementSize);
         if (logging()) {
-            printf("newArray: element kind %d\n", elementKind);
-            printf("newArray: array length %d\n", length);
-            printf("newArray: array size %d\n", sizeInBytes);
-            printf("newArray: hub=%p\n", hub.rawValue());
+            StubUtil.printf("newArray: element kind %d\n", elementKind);
+            StubUtil.printf("newArray: array length %d\n", length);
+            StubUtil.printf("newArray: array size %d\n", sizeInBytes);
+            StubUtil.printf("newArray: hub=%p\n", hub.rawValue());
         }
 
         // check that array length is small enough for fast path.
@@ -105,29 +105,29 @@
             Word memory = refillAllocate(intArrayHub, sizeInBytes, logging());
             if (memory.notEqual(0)) {
                 if (logging()) {
-                    printf("newArray: allocated new array at %p\n", memory.rawValue());
+                    StubUtil.printf("newArray: allocated new array at %p\n", memory.rawValue());
                 }
                 formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true);
-                return verifyObject(memory.toObject());
+                return StubUtil.verifyObject(memory.toObject());
             }
         }
         if (logging()) {
-            printf("newArray: calling new_array_c\n");
+            StubUtil.printf("newArray: calling new_array_c\n");
         }
 
         newArrayC(NEW_ARRAY_C, thread(), hub, length);
 
         if (clearPendingException(thread())) {
             if (logging()) {
-                printf("newArray: deoptimizing to caller\n");
+                StubUtil.printf("newArray: deoptimizing to caller\n");
             }
             getAndClearObjectResult(thread());
             DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
         }
-        return verifyObject(getAndClearObjectResult(thread()));
+        return StubUtil.verifyObject(getAndClearObjectResult(thread()));
     }
 
-    public static final Descriptor NEW_ARRAY_C = descriptorFor(NewArrayStub.class, "newArrayC", false);
+    public static final Descriptor NEW_ARRAY_C = StubUtil.descriptorFor(NewArrayStub.class, "newArrayC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void newArrayC(@ConstantNodeParameter Descriptor newArrayC, Word thread, Word hub, int length);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Thu May 09 11:32:08 2013 +0200
@@ -52,7 +52,7 @@
  * code when TLAB allocation fails. If this stub fails to refill the TLAB or allocate the object, it
  * calls out to the HotSpot C++ runtime for to complete the allocation.
  */
-public class NewInstanceStub extends Stub {
+public class NewInstanceStub extends SnippetStub {
 
     public NewInstanceStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
         super(runtime, replacements, target, linkage);
@@ -98,25 +98,25 @@
                     for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) {
                         memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                     }
-                    return verifyObject(memory.toObject());
+                    return StubUtil.verifyObject(memory.toObject());
                 }
             }
         }
 
         if (logging()) {
-            printf("newInstance: calling new_instance_c\n");
+            StubUtil.printf("newInstance: calling new_instance_c\n");
         }
 
         newInstanceC(NEW_INSTANCE_C, thread(), hub);
 
         if (clearPendingException(thread())) {
             if (logging()) {
-                printf("newInstance: deoptimizing to caller\n");
+                StubUtil.printf("newInstance: deoptimizing to caller\n");
             }
             getAndClearObjectResult(thread());
             DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
         }
-        return verifyObject(getAndClearObjectResult(thread()));
+        return StubUtil.verifyObject(getAndClearObjectResult(thread()));
     }
 
     /**
@@ -143,10 +143,10 @@
         Word tlabFreeSpaceInBytes = end.subtract(top);
 
         if (log) {
-            printf("refillTLAB: thread=%p\n", thread.rawValue());
-            printf("refillTLAB: top=%p\n", top.rawValue());
-            printf("refillTLAB: end=%p\n", end.rawValue());
-            printf("refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes.rawValue());
+            StubUtil.printf("refillTLAB: thread=%p\n", thread.rawValue());
+            StubUtil.printf("refillTLAB: top=%p\n", top.rawValue());
+            StubUtil.printf("refillTLAB: end=%p\n", end.rawValue());
+            StubUtil.printf("refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes.rawValue());
         }
 
         Word tlabFreeSpaceInWords = tlabFreeSpaceInBytes.unsignedShiftRight(log2WordSize());
@@ -159,12 +159,12 @@
                 // increment number of refills
                 thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION) + 1, TLAB_NOF_REFILLS_LOCATION);
                 if (log) {
-                    printf("thread: %p -- number_of_refills %d\n", thread.rawValue(), thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION));
+                    StubUtil.printf("thread: %p -- number_of_refills %d\n", thread.rawValue(), thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION));
                 }
                 // accumulate wastage
                 Word wastage = thread.readWord(tlabFastRefillWasteOffset(), TLAB_FAST_REFILL_WASTE_LOCATION).add(tlabFreeSpaceInWords);
                 if (log) {
-                    printf("thread: %p -- accumulated wastage %d\n", thread.rawValue(), wastage.rawValue());
+                    StubUtil.printf("thread: %p -- accumulated wastage %d\n", thread.rawValue(), wastage.rawValue());
                 }
                 thread.writeWord(tlabFastRefillWasteOffset(), wastage, TLAB_FAST_REFILL_WASTE_LOCATION);
             }
@@ -202,7 +202,7 @@
             Word newRefillWasteLimit = refillWasteLimit.add(tlabRefillWasteIncrement());
             thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit, TLAB_REFILL_WASTE_LIMIT_LOCATION);
             if (log) {
-                printf("refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.rawValue());
+                StubUtil.printf("refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.rawValue());
             }
 
             if (tlabStats()) {
@@ -247,7 +247,7 @@
         return Boolean.getBoolean("graal.newInstanceStub.forceSlowPath");
     }
 
-    public static final Descriptor NEW_INSTANCE_C = descriptorFor(NewInstanceStub.class, "newInstanceC", false);
+    public static final Descriptor NEW_INSTANCE_C = StubUtil.descriptorFor(NewInstanceStub.class, "newInstanceC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void newInstanceC(@ConstantNodeParameter Descriptor newInstanceC, Word thread, Word hub);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewMultiArrayStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewMultiArrayStub.java	Thu May 09 11:32:08 2013 +0200
@@ -47,11 +47,11 @@
     @Snippet
     private static Object newMultiArray(Word hub, int rank, Word dims) {
         newMultiArrayC(NEW_MULTI_ARRAY_C, thread(), hub, rank, dims);
-        handlePendingException(true);
+        StubUtil.handlePendingException(true);
         return getAndClearObjectResult(thread());
     }
 
-    public static final Descriptor NEW_MULTI_ARRAY_C = descriptorFor(NewMultiArrayStub.class, "newMultiArrayC", false);
+    public static final Descriptor NEW_MULTI_ARRAY_C = StubUtil.descriptorFor(NewMultiArrayStub.class, "newMultiArrayC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void newMultiArrayC(@ConstantNodeParameter Descriptor newArrayC, Word thread, Word hub, int rank, Word dims);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/OSRMigrationEndStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/OSRMigrationEndStub.java	Thu May 09 11:32:08 2013 +0200
@@ -48,7 +48,7 @@
         osrMigrationEndC(OSR_MIGRATION_END_C, buffer);
     }
 
-    public static final Descriptor OSR_MIGRATION_END_C = descriptorFor(OSRMigrationEndStub.class, "osrMigrationEndC", false);
+    public static final Descriptor OSR_MIGRATION_END_C = StubUtil.descriptorFor(OSRMigrationEndStub.class, "osrMigrationEndC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void osrMigrationEndC(@ConstantNodeParameter Descriptor osrMigrationEndC, Word buffer);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RegisterFinalizerStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RegisterFinalizerStub.java	Thu May 09 11:32:08 2013 +0200
@@ -48,10 +48,10 @@
     @Snippet
     private static void registerFinalizer(Object object) {
         registerFinalizerC(REGISTER_FINALIZER_C, thread(), object);
-        handlePendingException(false);
+        StubUtil.handlePendingException(false);
     }
 
-    public static final Descriptor REGISTER_FINALIZER_C = descriptorFor(RegisterFinalizerStub.class, "registerFinalizerC", false);
+    public static final Descriptor REGISTER_FINALIZER_C = StubUtil.descriptorFor(RegisterFinalizerStub.class, "registerFinalizerC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void registerFinalizerC(@ConstantNodeParameter Descriptor registerFinalizerC, Word thread, Object object);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Thu May 09 11:32:08 2013 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.stubs;
+
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+
+/**
+ * Base class for a stub defined by a snippet.
+ */
+public abstract class SnippetStub extends Stub implements Snippets {
+
+    static class Template extends AbstractTemplates {
+
+        Template(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, Class<? extends Snippets> declaringClass) {
+            super(runtime, replacements, target);
+            this.info = snippet(declaringClass, null);
+        }
+
+        /**
+         * Info for the method implementing the stub.
+         */
+        protected final SnippetInfo info;
+
+        protected StructuredGraph getGraph(Arguments args) {
+            SnippetTemplate template = template(args);
+            return template.copySpecializedGraph();
+        }
+    }
+
+    protected final Template snippet;
+
+    /**
+     * Creates a new snippet stub.
+     * 
+     * @param linkage linkage details for a call to the stub
+     */
+    public SnippetStub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
+        super(runtime, replacements, linkage);
+        this.snippet = new Template(runtime, replacements, target, getClass());
+    }
+
+    @Override
+    protected StructuredGraph getGraph() {
+        return snippet.getGraph(makeArguments(snippet.info));
+    }
+
+    /**
+     * Adds the {@linkplain ConstantParameter constant} arguments of this stub.
+     */
+    protected abstract Arguments makeArguments(SnippetInfo stub);
+
+    @Override
+    public ResolvedJavaMethod getInstalledCodeOwner() {
+        return snippet.info.getMethod();
+    }
+
+    @Override
+    public String toString() {
+        ResolvedJavaMethod method = getInstalledCodeOwner();
+        return "Stub<" + (method != null ? format("%h.%n", method) : linkage) + ">";
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Thu May 09 11:32:08 2013 +0200
@@ -22,15 +22,8 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.hotspot.nodes.CStringNode.*;
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.word.Word.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -38,14 +31,11 @@
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
-import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.graph.Node.ConstantNodeParameter;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
@@ -54,29 +44,15 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
-import com.oracle.graal.replacements.SnippetTemplate.Arguments;
-import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
-import com.oracle.graal.word.*;
 
 //JaCoCo Exclude
 
 /**
- * Base class for implementing some low level code providing the out-of-line slow path for a
- * snippet. A stub may make a direct call to a HotSpot C/C++ runtime function. Stubs are installed
- * as an instance of the C++ RuntimeStub class (as opposed to nmethod).
- * <p>
- * Implementation detail: The stub classes re-use some of the functionality for {@link Snippet}s
- * purely for convenience (e.g., can re-use the {@link ReplacementsImpl}).
+ * Base class for implementing some low level code providing the out-of-line slow path for a snippet
+ * and/or a callee saved call to a HotSpot C/C++ runtime function or even a another compiled Java
+ * method.
  */
-public abstract class Stub extends AbstractTemplates implements Snippets {
-
-    /**
-     * The method implementing the stub.
-     */
-    protected final SnippetInfo stubInfo;
+public abstract class Stub {
 
     /**
      * The linkage information for the stub.
@@ -116,31 +92,19 @@
         return true;
     }
 
+    protected final HotSpotRuntime runtime;
+
+    protected final Replacements replacements;
+
     /**
-     * Creates a new stub container..
+     * Creates a new stub.
      * 
      * @param linkage linkage details for a call to the stub
      */
-    public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target);
-        this.stubInfo = snippet(getClass(), null);
+    public Stub(HotSpotRuntime runtime, Replacements replacements, HotSpotRuntimeCallTarget linkage) {
         this.linkage = linkage;
-    }
-
-    /**
-     * Adds the {@linkplain ConstantParameter constant} arguments of this stub.
-     */
-    protected abstract Arguments makeArguments(SnippetInfo stub);
-
-    protected HotSpotRuntime runtime() {
-        return (HotSpotRuntime) runtime;
-    }
-
-    /**
-     * Gets the method implementing this stub.
-     */
-    public ResolvedJavaMethod getMethod() {
-        return stubInfo.getMethod();
+        this.runtime = runtime;
+        this.replacements = replacements;
     }
 
     public HotSpotRuntimeCallTarget getLinkage() {
@@ -153,40 +117,32 @@
     private boolean checkStubInvariants(CompilationResult compResult) {
         for (DataPatch data : compResult.getDataReferences()) {
             Constant constant = data.constant;
-            assert constant.getKind() != Kind.Object : format("%h.%n(%p): ", getMethod()) + "cannot have embedded object constant: " + constant;
-            assert constant.getPrimitiveAnnotation() == null : format("%h.%n(%p): ", getMethod()) + "cannot have embedded metadata: " + constant;
+            assert constant.getKind() != Kind.Object : this + " cannot have embedded object constant: " + constant;
+            assert constant.getPrimitiveAnnotation() == null : this + " cannot have embedded metadata: " + constant;
         }
         for (Infopoint infopoint : compResult.getInfopoints()) {
-            assert infopoint instanceof Call : format("%h.%n(%p): ", getMethod()) + "cannot have non-call infopoint: " + infopoint;
+            assert infopoint instanceof Call : this + " cannot have non-call infopoint: " + infopoint;
             Call call = (Call) infopoint;
-            assert call.target instanceof HotSpotRuntimeCallTarget : format("%h.%n(%p): ", getMethod()) + "cannot have non runtime call: " + call.target;
+            assert call.target instanceof HotSpotRuntimeCallTarget : this + " cannot have non runtime call: " + call.target;
             HotSpotRuntimeCallTarget callTarget = (HotSpotRuntimeCallTarget) call.target;
-            assert callTarget.getAddress() == graalRuntime().getConfig().uncommonTrapStub || callTarget.isCRuntimeCall() : format("%h.%n(%p): ", getMethod()) +
-                            "must only call C runtime or deoptimization stub, not " + call.target;
+            assert callTarget.getAddress() == graalRuntime().getConfig().uncommonTrapStub || callTarget.isCRuntimeCall() : this + "must only call C runtime or deoptimization stub, not " + call.target;
         }
         return true;
     }
 
+    protected abstract StructuredGraph getGraph();
+
+    @Override
+    public abstract String toString();
+
     /**
-     * Looks for a {@link CRuntimeCall} node intrinsic named {@code name} in {@code stubClass} and
-     * returns a {@link Descriptor} based on its signature and the value of {@code hasSideEffect}.
+     * Gets the method the stub's code will be {@linkplain InstalledCode#getMethod() associated}
+     * with once installed. This may be null.
      */
-    protected static <T extends Stub> Descriptor descriptorFor(Class<T> stubClass, String name, boolean hasSideEffect) {
-        Method found = null;
-        for (Method method : stubClass.getDeclaredMethods()) {
-            if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) {
-                if (method.getAnnotation(NodeIntrinsic.class).value() == CRuntimeCall.class) {
-                    assert found == null : "found more than one C runtime call named " + name + " in " + stubClass;
-                    assert method.getParameterTypes().length != 0 && method.getParameterTypes()[0] == Descriptor.class : "first parameter of C runtime call '" + name + "' in " + stubClass +
-                                    " must be of type " + Descriptor.class.getSimpleName();
-                    found = method;
-                }
-            }
-        }
-        assert found != null : "could not find C runtime call named " + name + " in " + stubClass;
-        List<Class<?>> paramList = Arrays.asList(found.getParameterTypes());
-        Class[] cCallTypes = paramList.subList(1, paramList.size()).toArray(new Class[paramList.size() - 1]);
-        return new Descriptor(name, hasSideEffect, found.getReturnType(), cCallTypes);
+    protected abstract ResolvedJavaMethod getInstalledCodeOwner();
+
+    protected Object debugScopeContext() {
+        return getInstalledCodeOwner();
     }
 
     /**
@@ -194,19 +150,22 @@
      */
     public synchronized InstalledCode getCode(final Backend backend) {
         if (code == null) {
-            Debug.sandbox("CompilingStub", new Object[]{runtime(), getMethod()}, DebugScope.getConfig(), new Runnable() {
+            Debug.sandbox("CompilingStub", new Object[]{runtime, debugScopeContext()}, DebugScope.getConfig(), new Runnable() {
 
                 @Override
                 public void run() {
 
-                    Arguments args = makeArguments(stubInfo);
-                    SnippetTemplate template = template(args);
-                    StructuredGraph graph = template.copySpecializedGraph();
+                    final StructuredGraph graph = getGraph();
+                    StubStartNode newStart = graph.add(new StubStartNode(Stub.this));
+                    newStart.setStateAfter(graph.start().stateAfter());
+                    graph.replaceFixed(graph.start(), newStart);
+                    graph.setStart(newStart);
 
                     PhasePlan phasePlan = new PhasePlan();
                     GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                     phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-                    final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan,
+                    CallingConvention cc = linkage.getCallingConvention();
+                    final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, getInstalledCodeOwner(), runtime, replacements, backend, runtime.getTarget(), null, phasePlan,
                                     OptimisticOptimizations.ALL, new SpeculationLog());
 
                     assert checkStubInvariants(compResult);
@@ -216,8 +175,8 @@
 
                         @Override
                         public InstalledCode call() {
-                            InstalledCode installedCode = runtime().addMethod(getMethod(), compResult);
-                            assert installedCode != null : "error installing stub " + getMethod();
+                            InstalledCode installedCode = runtime.addMethod(getInstalledCodeOwner(), compResult);
+                            assert installedCode != null : "error installing stub " + this;
                             if (Debug.isDumpEnabled()) {
                                 Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                             }
@@ -228,181 +187,8 @@
                     });
                 }
             });
-            assert code != null : "error installing stub " + getMethod();
+            assert code != null : "error installing stub " + this;
         }
         return code;
     }
-
-    static void handlePendingException(boolean isObjectResult) {
-        if (clearPendingException(thread())) {
-            if (isObjectResult) {
-                getAndClearObjectResult(thread());
-            }
-            DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
-        }
-    }
-
-    public static final Descriptor VM_MESSAGE_C = descriptorFor(Stub.class, "vmMessageC", false);
-
-    @NodeIntrinsic(CRuntimeCall.class)
-    private static native void vmMessageC(@ConstantNodeParameter Descriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
-
-    /**
-     * Prints a message to the log stream.
-     * <p>
-     * <b>Stubs must use this instead of {@link Log#printf(String, long)} to avoid an object
-     * constant in a RuntimeStub.</b>
-     * 
-     * @param message a message string
-     */
-    public static void printf(String message) {
-        vmMessageC(VM_MESSAGE_C, false, cstring(message), 0L, 0L, 0L);
-    }
-
-    /**
-     * Prints a message to the log stream.
-     * <p>
-     * <b>Stubs must use this instead of {@link Log#printf(String, long)} to avoid an object
-     * constant in a RuntimeStub.</b>
-     * 
-     * @param format a C style printf format value
-     * @param value the value associated with the first conversion specifier in {@code format}
-     */
-    public static void printf(String format, long value) {
-        vmMessageC(VM_MESSAGE_C, false, cstring(format), value, 0L, 0L);
-    }
-
-    /**
-     * Prints a message to the log stream.
-     * <p>
-     * <b>Stubs must use this instead of {@link Log#printf(String, long, long)} to avoid an object
-     * constant in a RuntimeStub.</b>
-     * 
-     * @param format a C style printf format value
-     * @param v1 the value associated with the first conversion specifier in {@code format}
-     * @param v2 the value associated with the second conversion specifier in {@code format}
-     */
-    public static void printf(String format, long v1, long v2) {
-        vmMessageC(VM_MESSAGE_C, false, cstring(format), v1, v2, 0L);
-    }
-
-    /**
-     * Prints a message to the log stream.
-     * <p>
-     * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
-     * object constant in a RuntimeStub.</b>
-     * 
-     * @param format a C style printf format value
-     * @param v1 the value associated with the first conversion specifier in {@code format}
-     * @param v2 the value associated with the second conversion specifier in {@code format}
-     * @param v3 the value associated with the third conversion specifier in {@code format}
-     */
-    public static void printf(String format, long v1, long v2, long v3) {
-        vmMessageC(VM_MESSAGE_C, false, cstring(format), v1, v2, v3);
-    }
-
-    /**
-     * Analyzes a given value and prints information about it to the log stream.
-     */
-    public static void decipher(long value) {
-        vmMessageC(VM_MESSAGE_C, false, Word.zero(), value, 0L, 0L);
-    }
-
-    /**
-     * Exits the VM with a given error message.
-     * <p>
-     * <b>Stubs must use this instead of {@link VMErrorNode#vmError(String, long)} to avoid an
-     * object constant in a RuntimeStub.</b>
-     * 
-     * @param message an error message
-     */
-    public static void fatal(String message) {
-        vmMessageC(VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L);
-    }
-
-    /**
-     * Exits the VM with a given error message.
-     * <p>
-     * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
-     * object constant in a RuntimeStub.</b>
-     * 
-     * @param format a C style printf format value
-     * @param value the value associated with the first conversion specifier in {@code format}
-     */
-    public static void fatal(String format, long value) {
-        vmMessageC(VM_MESSAGE_C, true, cstring(format), value, 0L, 0L);
-    }
-
-    /**
-     * Exits the VM with a given error message.
-     * <p>
-     * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
-     * object constant in a RuntimeStub.</b>
-     * 
-     * @param format a C style printf format value
-     * @param v1 the value associated with the first conversion specifier in {@code format}
-     * @param v2 the value associated with the second conversion specifier in {@code format}
-     */
-    public static void fatal(String format, long v1, long v2) {
-        vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, 0L);
-    }
-
-    /**
-     * Exits the VM with a given error message.
-     * <p>
-     * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
-     * object constant in a RuntimeStub.</b>
-     * 
-     * @param format a C style printf format value
-     * @param v1 the value associated with the first conversion specifier in {@code format}
-     * @param v2 the value associated with the second conversion specifier in {@code format}
-     * @param v3 the value associated with the third conversion specifier in {@code format}
-     */
-    public static void fatal(String format, long v1, long v2, long v3) {
-        vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, v3);
-    }
-
-    /**
-     * Verifies that a given object value is well formed if {@code -XX:+VerifyOops} is enabled.
-     */
-    public static Object verifyObject(Object object) {
-        if (verifyOops()) {
-            Word verifyOopCounter = Word.unsigned(verifyOopCounterAddress());
-            verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1);
-
-            Pointer oop = Word.fromObject(object);
-            if (object != null) {
-                // make sure object is 'reasonable'
-                if (!oop.and(unsigned(verifyOopMask())).equal(unsigned(verifyOopBits()))) {
-                    fatal("oop not in heap: %p", oop.rawValue());
-                }
-
-                Word klass = oop.readWord(hubOffset());
-                if (klass.equal(Word.zero())) {
-                    fatal("klass for oop %p is null", oop.rawValue());
-                }
-            }
-        }
-        return object;
-    }
-
-    @Fold
-    private static long verifyOopCounterAddress() {
-        return config().verifyOopCounterAddress;
-    }
-
-    @Fold
-    private static long verifyOopMask() {
-        return config().verifyOopMask;
-    }
-
-    @Fold
-    private static long verifyOopBits() {
-        return config().verifyOopBits;
-    }
-
-    @Fold
-    private static int hubOffset() {
-        return config().hubOffset;
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Thu May 09 11:32:08 2013 +0200
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.stubs;
+
+import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.hotspot.nodes.CStringNode.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.word.Word.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.Fold;
+import com.oracle.graal.word.*;
+
+//JaCoCo Exclude
+
+/**
+ * A collection of methods used in {@link Stub}s.
+ */
+public class StubUtil {
+
+    public static final Descriptor VM_MESSAGE_C = descriptorFor(StubUtil.class, "vmMessageC", false);
+
+    /**
+     * Looks for a {@link CRuntimeCall} node intrinsic named {@code name} in {@code stubClass} and
+     * returns a {@link Descriptor} based on its signature and the value of {@code hasSideEffect}.
+     */
+    public static Descriptor descriptorFor(Class<?> stubClass, String name, boolean hasSideEffect) {
+        Method found = null;
+        for (Method method : stubClass.getDeclaredMethods()) {
+            if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) {
+                if (method.getAnnotation(NodeIntrinsic.class).value() == CRuntimeCall.class) {
+                    assert found == null : "found more than one C runtime call named " + name + " in " + stubClass;
+                    assert method.getParameterTypes().length != 0 && method.getParameterTypes()[0] == Descriptor.class : "first parameter of C runtime call '" + name + "' in " + stubClass +
+                                    " must be of type " + Descriptor.class.getSimpleName();
+                    found = method;
+                }
+            }
+        }
+        assert found != null : "could not find C runtime call named " + name + " in " + stubClass;
+        List<Class<?>> paramList = Arrays.asList(found.getParameterTypes());
+        Class[] cCallTypes = paramList.subList(1, paramList.size()).toArray(new Class[paramList.size() - 1]);
+        return new Descriptor(name, hasSideEffect, found.getReturnType(), cCallTypes);
+    }
+
+    public static void handlePendingException(boolean isObjectResult) {
+        if (clearPendingException(thread())) {
+            if (isObjectResult) {
+                getAndClearObjectResult(thread());
+            }
+            DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
+        }
+    }
+
+    @NodeIntrinsic(CRuntimeCall.class)
+    private static native void vmMessageC(@ConstantNodeParameter Descriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
+
+    /**
+     * Prints a message to the log stream.
+     * <p>
+     * <b>Stubs must use this instead of {@link Log#printf(String, long)} to avoid an object
+     * constant in a RuntimeStub.</b>
+     * 
+     * @param message a message string
+     */
+    public static void printf(String message) {
+        vmMessageC(VM_MESSAGE_C, false, cstring(message), 0L, 0L, 0L);
+    }
+
+    /**
+     * Prints a message to the log stream.
+     * <p>
+     * <b>Stubs must use this instead of {@link Log#printf(String, long)} to avoid an object
+     * constant in a RuntimeStub.</b>
+     * 
+     * @param format a C style printf format value
+     * @param value the value associated with the first conversion specifier in {@code format}
+     */
+    public static void printf(String format, long value) {
+        vmMessageC(VM_MESSAGE_C, false, cstring(format), value, 0L, 0L);
+    }
+
+    /**
+     * Prints a message to the log stream.
+     * <p>
+     * <b>Stubs must use this instead of {@link Log#printf(String, long, long)} to avoid an object
+     * constant in a RuntimeStub.</b>
+     * 
+     * @param format a C style printf format value
+     * @param v1 the value associated with the first conversion specifier in {@code format}
+     * @param v2 the value associated with the second conversion specifier in {@code format}
+     */
+    public static void printf(String format, long v1, long v2) {
+        vmMessageC(VM_MESSAGE_C, false, cstring(format), v1, v2, 0L);
+    }
+
+    /**
+     * Prints a message to the log stream.
+     * <p>
+     * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
+     * object constant in a RuntimeStub.</b>
+     * 
+     * @param format a C style printf format value
+     * @param v1 the value associated with the first conversion specifier in {@code format}
+     * @param v2 the value associated with the second conversion specifier in {@code format}
+     * @param v3 the value associated with the third conversion specifier in {@code format}
+     */
+    public static void printf(String format, long v1, long v2, long v3) {
+        vmMessageC(VM_MESSAGE_C, false, cstring(format), v1, v2, v3);
+    }
+
+    /**
+     * Analyzes a given value and prints information about it to the log stream.
+     */
+    public static void decipher(long value) {
+        vmMessageC(VM_MESSAGE_C, false, Word.zero(), value, 0L, 0L);
+    }
+
+    /**
+     * Exits the VM with a given error message.
+     * <p>
+     * <b>Stubs must use this instead of {@link VMErrorNode#vmError(String, long)} to avoid an
+     * object constant in a RuntimeStub.</b>
+     * 
+     * @param message an error message
+     */
+    public static void fatal(String message) {
+        vmMessageC(VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L);
+    }
+
+    /**
+     * Exits the VM with a given error message.
+     * <p>
+     * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
+     * object constant in a RuntimeStub.</b>
+     * 
+     * @param format a C style printf format value
+     * @param value the value associated with the first conversion specifier in {@code format}
+     */
+    public static void fatal(String format, long value) {
+        vmMessageC(VM_MESSAGE_C, true, cstring(format), value, 0L, 0L);
+    }
+
+    /**
+     * Exits the VM with a given error message.
+     * <p>
+     * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
+     * object constant in a RuntimeStub.</b>
+     * 
+     * @param format a C style printf format value
+     * @param v1 the value associated with the first conversion specifier in {@code format}
+     * @param v2 the value associated with the second conversion specifier in {@code format}
+     */
+    public static void fatal(String format, long v1, long v2) {
+        vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, 0L);
+    }
+
+    /**
+     * Exits the VM with a given error message.
+     * <p>
+     * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
+     * object constant in a RuntimeStub.</b>
+     * 
+     * @param format a C style printf format value
+     * @param v1 the value associated with the first conversion specifier in {@code format}
+     * @param v2 the value associated with the second conversion specifier in {@code format}
+     * @param v3 the value associated with the third conversion specifier in {@code format}
+     */
+    public static void fatal(String format, long v1, long v2, long v3) {
+        vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, v3);
+    }
+
+    /**
+     * Verifies that a given object value is well formed if {@code -XX:+VerifyOops} is enabled.
+     */
+    public static Object verifyObject(Object object) {
+        if (verifyOops()) {
+            Word verifyOopCounter = Word.unsigned(verifyOopCounterAddress());
+            verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1);
+
+            Pointer oop = Word.fromObject(object);
+            if (object != null) {
+                // make sure object is 'reasonable'
+                if (!oop.and(unsigned(verifyOopMask())).equal(unsigned(verifyOopBits()))) {
+                    fatal("oop not in heap: %p", oop.rawValue());
+                }
+
+                Word klass = oop.readWord(hubOffset());
+                if (klass.equal(Word.zero())) {
+                    fatal("klass for oop %p is null", oop.rawValue());
+                }
+            }
+        }
+        return object;
+    }
+
+    @Fold
+    private static long verifyOopCounterAddress() {
+        return config().verifyOopCounterAddress;
+    }
+
+    @Fold
+    private static long verifyOopMask() {
+        return config().verifyOopMask;
+    }
+
+    @Fold
+    private static long verifyOopBits() {
+        return config().verifyOopBits;
+    }
+
+    @Fold
+    private static int hubOffset() {
+        return config().hubOffset;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ThreadIsInterruptedStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ThreadIsInterruptedStub.java	Thu May 09 11:32:08 2013 +0200
@@ -47,11 +47,11 @@
     @Snippet
     private static boolean threadIsInterrupted(Thread receiverThread, boolean clearIsInterrupted) {
         boolean result = threadIsInterruptedC(THREAD_IS_INTERRUPTED_C, thread(), receiverThread, clearIsInterrupted);
-        handlePendingException(false);
+        StubUtil.handlePendingException(false);
         return result;
     }
 
-    public static final Descriptor THREAD_IS_INTERRUPTED_C = descriptorFor(ThreadIsInterruptedStub.class, "threadIsInterruptedC", false);
+    public static final Descriptor THREAD_IS_INTERRUPTED_C = StubUtil.descriptorFor(ThreadIsInterruptedStub.class, "threadIsInterruptedC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native boolean threadIsInterruptedC(@ConstantNodeParameter Descriptor threadIsInterruptedC, Word thread, Thread receiverThread, boolean clearIsInterrupted);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java	Thu May 09 11:32:08 2013 +0200
@@ -63,11 +63,11 @@
     private static void unwindExceptionToCaller(Object exception, Word returnAddress) {
         Pointer exceptionOop = Word.fromObject(exception);
         if (logging()) {
-            printf("unwinding exception %p (", exceptionOop.rawValue());
-            decipher(exceptionOop.rawValue());
-            printf(") at %p (", exceptionOop.rawValue(), returnAddress.rawValue());
-            decipher(returnAddress.rawValue());
-            printf(")\n");
+            StubUtil.printf("unwinding exception %p (", exceptionOop.rawValue());
+            StubUtil.decipher(exceptionOop.rawValue());
+            StubUtil.printf(") at %p (", exceptionOop.rawValue(), returnAddress.rawValue());
+            StubUtil.decipher(returnAddress.rawValue());
+            StubUtil.printf(")\n");
         }
         checkNoExceptionInThread(assertionsEnabled());
         checkExceptionNotNull(assertionsEnabled(), exception);
@@ -75,9 +75,9 @@
         Word handlerInCallerPc = exceptionHandlerForReturnAddress(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, thread(), returnAddress);
 
         if (logging()) {
-            printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue());
-            decipher(handlerInCallerPc.rawValue());
-            printf(")\n");
+            StubUtil.printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue());
+            StubUtil.decipher(handlerInCallerPc.rawValue());
+            StubUtil.printf(")\n");
         }
 
         jumpToExceptionHandlerInCaller(handlerInCallerPc, exception, returnAddress);
@@ -96,7 +96,7 @@
         return enabled || graalRuntime().getConfig().cAssertions;
     }
 
-    public static final Descriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = descriptorFor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", false);
+    public static final Descriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = StubUtil.descriptorFor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", false);
 
     @NodeIntrinsic(value = CRuntimeCall.class, setStampFromReturnType = true)
     public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter Descriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VMErrorStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VMErrorStub.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
         vmErrorC(VM_ERROR_C, thread(), where, format, value);
     }
 
-    public static final Descriptor VM_ERROR_C = descriptorFor(VMErrorStub.class, "vmErrorC", false);
+    public static final Descriptor VM_ERROR_C = StubUtil.descriptorFor(VMErrorStub.class, "vmErrorC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void vmErrorC(@ConstantNodeParameter Descriptor vmErrorC, Word thread, String where, String format, long value);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java	Thu May 09 11:32:08 2013 +0200
@@ -40,6 +40,6 @@
 
     @Snippet
     private static Object verifyOop(Object object) {
-        return verifyObject(object);
+        return StubUtil.verifyObject(object);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/WriteBarrierPostStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/WriteBarrierPostStub.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
         writeBarrierPostC(WRITE_BARRIER_POST_C, thread(), object, card);
     }
 
-    public static final Descriptor WRITE_BARRIER_POST_C = descriptorFor(WriteBarrierPostStub.class, "writeBarrierPostC", false);
+    public static final Descriptor WRITE_BARRIER_POST_C = StubUtil.descriptorFor(WriteBarrierPostStub.class, "writeBarrierPostC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void writeBarrierPostC(@ConstantNodeParameter Descriptor vmErrorC, Word thread, Object object, Word card);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/WriteBarrierPreStub.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/WriteBarrierPreStub.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
         writeBarrierPreC(WRITE_BARRIER_PRE_C, thread(), object);
     }
 
-    public static final Descriptor WRITE_BARRIER_PRE_C = descriptorFor(WriteBarrierPreStub.class, "writeBarrierPreC", false);
+    public static final Descriptor WRITE_BARRIER_PRE_C = StubUtil.descriptorFor(WriteBarrierPreStub.class, "writeBarrierPreC", false);
 
     @NodeIntrinsic(CRuntimeCall.class)
     public static native void writeBarrierPreC(@ConstantNodeParameter Descriptor vmErrorC, Word thread, Object object);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Thu May 09 11:32:08 2013 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
 
 public class TargetMethodAssembler {
 
@@ -88,7 +89,7 @@
         compilationResult.addAnnotation(new CompilationResult.CodeComment(asm.codeBuffer.position(), s));
     }
 
-    public CompilationResult finishTargetMethod(Object name, boolean isStub) {
+    public CompilationResult finishTargetMethod(StructuredGraph graph) {
         // Install code, data and frame size
         compilationResult.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position());
 
@@ -117,7 +118,7 @@
             Debug.metric("DataPatches").add(ldp.size());
             Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size());
         }
-        Debug.log("Finished target method %s, isStub %b", name, isStub);
+        Debug.log("Finished compiling %s", graph);
         return compilationResult;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Thu May 09 11:32:08 2013 +0200
@@ -106,6 +106,11 @@
         return start;
     }
 
+    /**
+     * Gets the method from which this graph was built.
+     * 
+     * @return null if this method was not built from a method or the method is not available
+     */
     public ResolvedJavaMethod method() {
         return method;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Thu May 09 11:32:08 2013 +0200
@@ -47,6 +47,7 @@
         this.method = method;
         assert !Modifier.isAbstract(method.getModifiers()) : "Cannot load abstract method from a hub";
         assert !Modifier.isStatic(method.getModifiers()) : "Cannot load a static method from a hub";
+        assert method.isInVirtualMethodTable();
     }
 
     @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu May 09 11:32:08 2013 +0200
@@ -640,7 +640,6 @@
                 assert concretes.size() > 0;
                 Debug.log("Method check cascade with %d methods", concretes.size());
 
-                LoadMethodNode[] methods = new LoadMethodNode[concretes.size()];
                 ValueNode[] constantMethods = new ValueNode[concretes.size()];
                 double[] probability = new double[concretes.size()];
                 for (int i = 0; i < concretes.size(); ++i) {
@@ -665,8 +664,7 @@
                 FixedNode lastSucc = successors[concretes.size()];
                 for (int i = concretes.size() - 1; i >= 0; --i) {
                     LoadMethodNode method = graph.add(new LoadMethodNode(concretes.get(i), hub, constantMethods[i].kind()));
-                    methods[i] = method;
-                    CompareNode methodCheck = CompareNode.createCompareNode(Condition.EQ, methods[i], constantMethods[i]);
+                    CompareNode methodCheck = CompareNode.createCompareNode(Condition.EQ, method, constantMethods[i]);
                     IfNode ifNode = graph.add(new IfNode(methodCheck, successors[i], lastSucc, probability[i]));
                     method.setNext(ifNode);
                     lastSucc = method;
@@ -698,6 +696,12 @@
         }
 
         private boolean chooseMethodDispatch() {
+            for (ResolvedJavaMethod concrete : concretes) {
+                if (!concrete.isInVirtualMethodTable()) {
+                    return false;
+                }
+            }
+
             if (concretes.size() == 1 && this.notRecordedTypeProbability > 0) {
                 // Always chose method dispatch if there is a single concrete method and the call
                 // site is megamorphic.
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Thu May 09 11:32:08 2013 +0200
@@ -30,6 +30,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.phases.*;
@@ -181,8 +182,8 @@
     private static List<String> getInlineContext() {
         List<String> result = new ArrayList<>();
         for (Object o : Debug.context()) {
-            if (o instanceof ResolvedJavaMethod) {
-                ResolvedJavaMethod method = (ResolvedJavaMethod) o;
+            JavaMethod method = GraalDebugConfig.asJavaMethod(o);
+            if (method != null) {
                 result.add(MetaUtil.format("%H::%n(%p)", method));
             } else if (o instanceof DebugDumpScope) {
                 DebugDumpScope debugDumpScope = (DebugDumpScope) o;
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AbstractTest.java	Wed May 08 18:05:57 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AbstractTest.java	Thu May 09 11:32:08 2013 +0200
@@ -49,7 +49,7 @@
         return result.toString();
     }
 
-    protected void executeSL(String[] input, String[] expectedOutput, boolean useConsole) {
+    protected static void executeSL(String[] input, String[] expectedOutput, boolean useConsole) {
         InputStream in = new ByteArrayInputStream(concat(input).getBytes());
 
         ByteArrayOutputStream out = new ByteArrayOutputStream();
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed May 08 18:05:57 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu May 09 11:32:08 2013 +0200
@@ -1001,6 +1001,7 @@
   Method* method = asMethod(metaspace_method);
   assert(!InstanceKlass::cast(method->method_holder())->is_interface(), "vtableEntryOffset cannot be called for interface methods");
   assert(InstanceKlass::cast(method->method_holder())->is_linked(), "vtableEntryOffset cannot be called is holder is not linked");
+  assert(method->vtable_index() >= 0, "vtable entry offset should not be used");
 
   // get entry offset in words
   int vtable_entry_offset = InstanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size();
@@ -1010,6 +1011,11 @@
   return vtable_entry_offset;
 C2V_END
 
+C2V_VMENTRY(jboolean, hasVtableEntry, (JNIEnv *, jobject, jlong metaspace_method))
+  Method* method = asMethod(metaspace_method);
+  return method->vtable_index() >= 0;
+C2V_END
+
 C2V_VMENTRY(jobject, getDeoptedLeafGraphIds, (JNIEnv *, jobject))
 
   // the contract for this method is as follows:
@@ -1177,6 +1183,7 @@
   {CC"getInvocationCount",            CC"("METASPACE_METHOD")I",                                        FN_PTR(getInvocationCount)},
   {CC"getCompiledCodeSize",           CC"("METASPACE_METHOD")I",                                        FN_PTR(getCompiledCodeSize)},
   {CC"getVtableEntryOffset",          CC"("METASPACE_METHOD")I",                                        FN_PTR(getVtableEntryOffset)},
+  {CC"hasVtableEntry",                CC"("METASPACE_METHOD")Z",                                        FN_PTR(hasVtableEntry)},
   {CC"constantPoolLength",            CC"("HS_RESOLVED_TYPE")I",                                        FN_PTR(constantPoolLength)},
   {CC"lookupType",                    CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE,                             FN_PTR(lookupType)},
   {CC"lookupConstantInPool",          CC"("HS_RESOLVED_TYPE"I)"OBJECT,                                  FN_PTR(lookupConstantInPool)},