changeset 9034:220c9bef97a4

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 12 Apr 2013 10:54:49 +0200
parents 35a52b195f28 (current diff) 9a3e25e270a0 (diff)
children c181a7f6311d
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java
diffstat 82 files changed, 1863 insertions(+), 1423 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Fri Apr 12 10:54:49 2013 +0200
@@ -45,6 +45,40 @@
         private static final long serialVersionUID = -1936652569665112915L;
     }
 
+    public static final class NoFinalizableSubclass extends Assumption {
+
+        private static final long serialVersionUID = 6451169735564055081L;
+
+        private ResolvedJavaType receiverType;
+
+        public NoFinalizableSubclass(ResolvedJavaType receiverType) {
+            this.receiverType = receiverType;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + receiverType.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof NoFinalizableSubclass) {
+                NoFinalizableSubclass other = (NoFinalizableSubclass) obj;
+                return other.receiverType == receiverType;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "NoFinalizableSubclass[receiverType=" + toJavaName(receiverType) + "]";
+        }
+
+    }
+
     /**
      * An assumption about a unique subtype of a given type.
      */
@@ -273,12 +307,10 @@
      * Records an assumption that the specified type has no finalizable subclasses.
      * 
      * @param receiverType the type that is assumed to have no finalizable subclasses
-     * @return {@code true} if the assumption was recorded and can be assumed; {@code false}
-     *         otherwise
      */
-    public boolean recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) {
+    public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) {
         assert useOptimisticAssumptions;
-        return false;
+        record(new NoFinalizableSubclass(receiverType));
     }
 
     /**
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -31,14 +31,6 @@
 public interface InstalledCode {
 
     /**
-     * Exception thrown by the runtime in case an invalidated machine code is called.
-     */
-    public abstract class MethodInvalidatedException extends RuntimeException {
-
-        private static final long serialVersionUID = -3540232440794244844L;
-    }
-
-    /**
      * Returns the method (if any) to which the installed code belongs.
      */
     ResolvedJavaMethod getMethod();
@@ -61,6 +53,12 @@
     boolean isValid();
 
     /**
+     * Invalidates this installed code such that any subsequent invocation will throw an
+     * {@link InvalidInstalledCodeException}.
+     */
+    void invalidate();
+
+    /**
      * Executes the installed code with three object arguments.
      * 
      * @param arg1 the first argument
@@ -68,7 +66,7 @@
      * @param arg3 the third argument
      * @return the value returned by the executed code
      */
-    Object execute(Object arg1, Object arg2, Object arg3);
+    Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException;
 
     /**
      * Executes the installed code with a variable number of arguments.
@@ -76,5 +74,5 @@
      * @param args the array of object arguments
      * @return the value returned by the executed code
      */
-    Object executeVarargs(Object... args);
+    Object executeVarargs(Object... args) throws InvalidInstalledCodeException;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,31 @@
+/*
+ * 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.api.code;
+
+/**
+ * Exception thrown by the runtime in case an invalidated machine code is called.
+ */
+public final class InvalidInstalledCodeException extends Exception {
+
+    private static final long serialVersionUID = -3540232440794244844L;
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Fri Apr 12 10:54:49 2013 +0200
@@ -98,7 +98,9 @@
      * Looks up the appendix at the specified index.
      * 
      * @param cpi the constant pool index
-     * @return the appendix if resolved or {@code null}.
+     * @param opcode the opcode of the instruction for which the lookup is being performed or
+     *            {@code -1}
+     * @return the appendix if it exists and is resolved or {@code null}
      */
-    Object lookupAppendix(int cpi);
+    Object lookupAppendix(int cpi, int opcode);
 }
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Fri Apr 12 10:54:49 2013 +0200
@@ -67,7 +67,11 @@
     protected Object runTest(String methodName, CodeGenTest test, Object... args) {
         Method method = getMethod(methodName);
         InstalledCode code = assembleMethod(method, test);
-        return code.executeVarargs(args);
+        try {
+            return code.executeVarargs(args);
+        } catch (InvalidInstalledCodeException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.ptx.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+public class ArrayTest extends PTXTestBase {
+
+    @Test
+    public void testArray() {
+        compile("testArray1I");
+        compile("testArray1J");
+        compile("testArray1B");
+        compile("testArray1S");
+        compile("testArray1C");
+        compile("testArray1F");
+        compile("testArray1D");
+        compile("testArray1L");
+        compile("testStoreArray1I");
+        compile("testStoreArray1J");
+        compile("testStoreArray1B");
+        compile("testStoreArray1S");
+        compile("testStoreArray1F");
+        compile("testStoreArray1D");
+    }
+
+    public static int testArray1I(int[] array, int i) {
+        return array[i];
+    }
+
+    public static long testArray1J(long[] array, int i) {
+        return array[i];
+    }
+
+    public static byte testArray1B(byte[] array, int i) {
+        return array[i];
+    }
+
+    public static short testArray1S(short[] array, int i) {
+        return array[i];
+    }
+
+    public static char testArray1C(char[] array, int i) {
+        return array[i];
+    }
+
+    public static float testArray1F(float[] array, int i) {
+        return array[i];
+    }
+
+    public static double testArray1D(double[] array, int i) {
+        return array[i];
+    }
+
+    public static Object testArray1L(Object[] array, int i) {
+        return array[i];
+    }
+
+    public static void testStoreArray1I(int[] array, int i, int val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1B(byte[] array, int i, byte val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1S(short[] array, int i, short val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1J(long[] array, int i, long val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1F(float[] array, int i, float val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1D(double[] array, int i, double val) {
+        array[i] = val;
+    }
+
+    public static void main(String[] args) {
+        ArrayTest test = new ArrayTest();
+        for (Method m : ArrayTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Fri Apr 12 10:54:49 2013 +0200
@@ -33,28 +33,19 @@
 
     @Test
     public void testAdd() {
-        compile("testAddSnippet");
-    }
-
-    public static int testAddSnippet(int a) {
-        return a + 1;
+        compile("testAddConst1I");
     }
 
-    @Test
-    public void testArray() {
-        compile("testArraySnippet");
-    }
-
-    public static int testArraySnippet(int[] array) {
-        return array[0];
+    public static int testAddConst1I(int a) {
+        return a + 1;
     }
 
     public static void main(String[] args) {
         BasicPTXTest test = new BasicPTXTest();
         Method[] methods = BasicPTXTest.class.getMethods();
         for (Method m : methods) {
-            if (m.getAnnotation(Test.class) != null) {
-                String name = m.getName() + "Snippet";
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
                 // CheckStyle: stop system..print check
                 System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
                 // CheckStyle: resume system..print check
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Apr 12 10:54:49 2013 +0200
@@ -155,7 +155,7 @@
             baseRegister = asAllocatable(base);
         }
 
-        if (index != Value.ILLEGAL) {
+        if (index != Value.ILLEGAL && scale != 0) {
             if (isConstant(index)) {
                 finalDisp += asConstant(index).asLong() * scale;
             } else {
@@ -169,6 +169,9 @@
                 if (baseRegister == AllocatableValue.UNUSED) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
+                    Variable newBase = newVariable(Kind.Int);
+                    emitMove(newBase, baseRegister);
+                    baseRegister = newBase;
                     baseRegister = emitAdd(baseRegister, indexRegister);
                 }
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Fri Apr 12 10:54:49 2013 +0200
@@ -27,13 +27,10 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.InstalledCode.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.test.*;
 
@@ -75,7 +72,7 @@
         try {
             Object result = compiledMethod.execute("1", "2", "3");
             Assert.assertEquals("1-2-3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
@@ -89,7 +86,7 @@
         try {
             Object result = compiledMethod.executeVarargs("1", "2", "3");
             Assert.assertEquals("1 2 3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
@@ -104,98 +101,8 @@
             f1 = "0";
             Object result = compiledMethod.executeVarargs(this, "1", "2", "3");
             Assert.assertEquals("0 1 2 3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
-
-    @LongTest
-    public void test2() throws NoSuchMethodException, SecurityException {
-        Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class);
-        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
-        StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph);
-        new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph);
-        new DeadCodeEliminationPhase().apply(graph);
-
-        for (Node node : graph.getNodes()) {
-            if (node instanceof ConstantNode) {
-                ConstantNode constant = (ConstantNode) node;
-                if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) {
-                    graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph));
-                }
-            }
-        }
-
-        InstalledCode compiledMethod = getCode(javaMethod, graph);
-        final CompilableObject compilableObject = new CompilableObjectImpl(0);
-
-        Object result;
-        result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3");
-        Assert.assertEquals("1-3", result);
-    }
-
-    public abstract class CompilableObject {
-
-        private CompiledObject compiledObject;
-        private final int compileThreshold;
-        private int counter;
-
-        public CompilableObject(int compileThreshold) {
-            this.compileThreshold = compileThreshold;
-        }
-
-        public final Object execute(ObjectCompiler compiler, String args) {
-            if (counter++ < compileThreshold || compiler == null) {
-                return executeHelper(compiler, args);
-            } else {
-                compiledObject = compiler.compile(this);
-                return compiledObject.execute(compiler, args);
-            }
-        }
-
-        protected abstract Object executeHelper(ObjectCompiler context, String args);
-    }
-
-    private final class CompilableObjectImpl extends CompilableObject {
-
-        private CompilableObjectImpl(int compileThreshold) {
-            super(compileThreshold);
-        }
-
-        @Override
-        protected Object executeHelper(ObjectCompiler compiler, String args) {
-            return "1 " + args;
-        }
-    }
-
-    public interface CompiledObject {
-
-        Object execute(ObjectCompiler context, String args);
-    }
-
-    public interface ObjectCompiler {
-
-        CompiledObject compile(CompilableObject node);
-    }
-
-    private final class ObjectCompilerImpl implements ObjectCompiler {
-
-        private final InstalledCode compiledMethod;
-
-        private ObjectCompilerImpl(InstalledCode compiledMethod) {
-            this.compiledMethod = compiledMethod;
-        }
-
-        @Override
-        public CompiledObject compile(final CompilableObject node) {
-            return new CompiledObject() {
-
-                @Override
-                public Object execute(ObjectCompiler compiler, String args) {
-                    return compiledMethod.execute(node, compiler, args);
-                }
-            };
-        }
-    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java	Fri Apr 12 10:54:49 2013 +0200
@@ -27,7 +27,6 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.InstalledCode.MethodInvalidatedException;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
@@ -59,7 +58,7 @@
         try {
             Object result = compiledMethod.executeVarargs(testString);
             Assert.assertEquals(testString, result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
 
@@ -67,7 +66,7 @@
             Object result = compiledMethod.executeVarargs(new Object[]{null});
             Assert.assertEquals(null, result);
             Assert.assertFalse(compiledMethod.isValid());
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Apr 12 10:54:49 2013 +0200
@@ -335,7 +335,7 @@
                 TTY.println("LIRGen for " + instr);
             }
             FrameState stateAfter = null;
-            if (instr instanceof StateSplit) {
+            if (instr instanceof StateSplit && !(instr instanceof InfopointNode)) {
                 stateAfter = ((StateSplit) instr).stateAfter();
             }
             if (instr instanceof ValueNode) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+
+public class HotSpotInstalledCodeTest extends GraalCompilerTest {
+
+    private static final int ITERATION_COUNT = 100000;
+
+    @Test
+    public void testInstallCodeInvalidation() {
+        final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo"));
+        final StructuredGraph graph = parse("otherFoo");
+        final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph);
+        Assert.assertTrue(installedCode.isValid());
+        Object result;
+        try {
+            result = installedCode.execute("a", "b", "c");
+            assertEquals(43, result);
+        } catch (InvalidInstalledCodeException e) {
+            Assert.fail("Code was invalidated");
+        }
+        Assert.assertTrue(installedCode.isValid());
+        installedCode.invalidate();
+        Assert.assertFalse(installedCode.isValid());
+        try {
+            result = installedCode.execute(null, null, null);
+            Assert.fail("Code was not invalidated");
+        } catch (InvalidInstalledCodeException e) {
+        }
+        Assert.assertFalse(installedCode.isValid());
+    }
+
+    @Test
+    public void testInstalledCodeCalledFromCompiledCode() {
+        final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo"));
+        final StructuredGraph graph = parse("otherFoo");
+        final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph);
+        Assert.assertTrue(installedCode.isValid());
+        try {
+            for (int i = 0; i < ITERATION_COUNT; ++i) {
+                installedCode.execute("a", "b", "c");
+            }
+        } catch (InvalidInstalledCodeException e) {
+            Assert.fail("Code was invalidated");
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static Object foo(Object a1, Object a2, Object a3) {
+        return 42;
+    }
+
+    @SuppressWarnings("unused")
+    public static Object otherFoo(Object a1, Object a2, Object a3) {
+        return 43;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Fri Apr 12 10:54:49 2013 +0200
@@ -24,6 +24,7 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.test.*;
@@ -36,7 +37,7 @@
 
     // TODO this is not a test, move it somewhere else
     // CheckStyle: stop system..print check
-    public void test1() throws NoSuchMethodException, SecurityException {
+    public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
 
         final Method benchrMethod = InstalledCodeExecuteHelperTest.class.getMethod("bench", long.class, long.class);
         final ResolvedJavaMethod benchJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(benchrMethod);
@@ -63,7 +64,7 @@
 
     // CheckStyle: resume system..print check
 
-    public static Long bench(long nmethod, long metaspacemethod) {
+    public static Long bench(long nmethod, long metaspacemethod) throws InvalidInstalledCodeException {
         long start = System.currentTimeMillis();
 
         for (int i = 0; i < ITERATIONS; i++) {
@@ -78,7 +79,7 @@
         return 42;
     }
 
-    public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) {
+    public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException {
         return HotSpotInstalledCode.executeHelper(nmethod, metaspaceMethod, arg1, arg2, arg3);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Fri Apr 12 10:54:49 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.*;
 
 /**
@@ -62,4 +63,24 @@
         }
         return super.registerMethodSubstitution(originalMethod, substituteMethod);
     }
+
+    @Override
+    public Class<? extends FixedWithNextNode> getMacroSubstitution(ResolvedJavaMethod method) {
+        HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
+        int intrinsicId = hsMethod.intrinsicId();
+        if (intrinsicId != 0) {
+            if (intrinsicId == config.vmIntrinsicInvokeBasic) {
+                return MethodHandleInvokeBasicNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToInterface) {
+                return MethodHandleLinkToInterfaceNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) {
+                return MethodHandleLinkToSpecialNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToStatic) {
+                return MethodHandleLinkToStaticNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) {
+                return MethodHandleLinkToVirtualNode.class;
+            }
+        }
+        return super.getMacroSubstitution(method);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Apr 12 10:54:49 2013 +0200
@@ -187,6 +187,11 @@
     public int methodAccessFlagsOffset;
 
     /**
+     * Offset of _intrinsic_id in a metaspace Method object.
+     */
+    public int methodIntrinsicIdOffset;
+
+    /**
      * Offset of _max_locals in a metaspace Method object.
      */
     public int methodMaxLocalsOffset;
@@ -378,6 +383,12 @@
     public int deoptActionMakeNotEntrant;
     public int deoptActionMakeNotCompilable;
 
+    public int vmIntrinsicInvokeBasic;
+    public int vmIntrinsicLinkToVirtual;
+    public int vmIntrinsicLinkToStatic;
+    public int vmIntrinsicLinkToSpecial;
+    public int vmIntrinsicLinkToInterface;
+
     public void check() {
         assert codeEntryAlignment > 0;
         assert stackShadowPages > 0;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Apr 12 10:54:49 2013 +0200
@@ -138,6 +138,8 @@
 
     void lookupReferencedTypeInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
 
+    Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
+
     // Must be kept in sync with enum in graalEnv.hpp
     public enum CodeInstallResult {
         OK, DEPENDENCIES_FAILED, CACHE_FULL
@@ -199,9 +201,9 @@
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
-    Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3);
+    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException;
 
-    Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args);
+    Object executeCompiledMethodVarargs(Object[] args, long nativeMethod) throws InvalidInstalledCodeException;
 
     int getVtableEntryOffset(long metaspaceMethod);
 
@@ -222,5 +224,7 @@
      */
     void reprofile(long metaspaceMethod);
 
-    Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi);
+    void invalidateInstalledCode(long nativeMethod);
+
+    boolean isInstalledCodeValid(long nativeMethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 12 10:54:49 2013 +0200
@@ -133,10 +133,7 @@
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
     @Override
-    public native Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3);
-
-    @Override
-    public native Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args);
+    public native Object executeCompiledMethodVarargs(Object[] args, long nativeMethod);
 
     @Override
     public native int getVtableEntryOffset(long metaspaceMethod);
@@ -160,5 +157,18 @@
     public native void reprofile(long metaspaceMethod);
 
     @Override
-    public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi);
+    public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
+
+    @Override
+    public native void invalidateInstalledCode(long nativeMethod);
+
+    @Override
+    public native boolean isInstalledCodeValid(long nativeMethod);
+
+    @Override
+    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException {
+        return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod);
+    }
+
+    private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Apr 12 10:54:49 2013 +0200
@@ -153,7 +153,8 @@
 
                 @Override
                 public void run() {
-                    for (ReplacementsProvider provider : ServiceLoader.loadInstalled(ReplacementsProvider.class)) {
+                    ServiceLoader<ReplacementsProvider> serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class);
+                    for (ReplacementsProvider provider : serviceLoader) {
                         provider.registerReplacements(replacements);
                     }
                     runtime.registerReplacements(replacements);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Fri Apr 12 10:54:49 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.meta;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.bytecode.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -51,10 +52,9 @@
     }
 
     @Override
-    public Object lookupAppendix(int cpi) {
-        assert cpi != 0;
-        Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi);
-        return constant;
+    public Object lookupAppendix(int cpi, int opcode) {
+        assert Bytecodes.isInvoke(opcode);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi, (byte) opcode);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -39,10 +39,11 @@
 
     private final HotSpotResolvedJavaMethod method;
     private final boolean isDefault;
-    long nmethod;
+    private final long nmethod; // This field is set by the runtime upon code installation.
     long start;
 
     public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) {
+        this.nmethod = 0;
         this.method = method;
         this.isDefault = isDefault;
     }
@@ -62,7 +63,12 @@
 
     @Override
     public boolean isValid() {
-        return nmethod != 0;
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().isInstalledCodeValid(nmethod);
+    }
+
+    @Override
+    public void invalidate() {
+        HotSpotGraalRuntime.getInstance().getCompilerToVM().invalidateInstalledCode(nmethod);
     }
 
     @Override
@@ -71,12 +77,12 @@
     }
 
     @Override
-    public Object execute(Object arg1, Object arg2, Object arg3) {
+    public Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException {
         assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3;
         assert method.getSignature().getParameterKind(0) == Kind.Object;
         assert method.getSignature().getParameterKind(1) == Kind.Object;
         assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object;
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(method.metaspaceMethod, nmethod, arg1, arg2, arg3);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod);
     }
 
     private boolean checkArgs(Object... args) {
@@ -94,9 +100,9 @@
     }
 
     @Override
-    public Object executeVarargs(Object... args) {
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
         assert checkArgs(args);
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(method.metaspaceMethod, nmethod, args);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(args, nmethod);
     }
 
     @Override
@@ -109,7 +115,8 @@
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod);
     }
 
-    public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) {
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(metaspaceMethod, nmethod, arg1, arg2, arg3);
+    @SuppressWarnings("unused")
+    public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException {
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri Apr 12 10:54:49 2013 +0200
@@ -362,4 +362,9 @@
         }
         return speculationLog;
     }
+
+    public int intrinsicId() {
+        HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig();
+        return unsafe.getByte(metaspaceMethod + config.methodIntrinsicIdOffset) & 0xff;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Apr 12 10:54:49 2013 +0200
@@ -327,17 +327,6 @@
             replacements.registerSubstitutions(AESCryptSubstitutions.class);
             replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyArrayCopy) {
-            replacements.registerSnippets(ArrayCopySnippets.class);
-        }
-        if (GraalOptions.IntrinsifyObjectClone) {
-            replacements.registerSnippets(ObjectCloneSnippets.class);
-        }
-
-        replacements.registerSnippets(BoxingSnippets.class);
-        for (Class<?> clazz : BoxingSubstitutions.getClasses()) {
-            replacements.registerSubstitutions(clazz);
-        }
 
         checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget());
         instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget());
@@ -710,7 +699,7 @@
         } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
             // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
             // zero and the MIN_VALUE / -1 cases.
-        } else if (n instanceof UnwindNode) {
+        } else if (n instanceof UnwindNode || n instanceof DeoptimizeNode) {
             // Nothing to do, using direct LIR lowering for these nodes.
         } else if (n instanceof BoxNode) {
             boxingSnippets.lower((BoxNode) n);
@@ -905,7 +894,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long nmethod = ((HotSpotInstalledCode) code).nmethod;
+            long nmethod = ((HotSpotInstalledCode) code).getnmethod();
             return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod);
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -37,7 +37,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -75,7 +74,7 @@
     private static final Kind VECTOR_KIND = Kind.Long;
     private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
 
-    public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) {
+    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
         checkNonNull(src);
         checkNonNull(dest);
         checkLimits(src, srcPos, dest, destPos, length);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.replacements;
-
-import static com.oracle.graal.replacements.SnippetTemplate.*;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.Fold;
-import com.oracle.graal.replacements.Snippet.Parameter;
-import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
-import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
-import com.oracle.graal.replacements.SnippetTemplate.Arguments;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
-import com.oracle.graal.word.*;
-
-public class BoxingSnippets implements Snippets {
-
-    /**
-     * This snippet inlining policy differs from the default one in that it does normal inlining of
-     * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution).
-     */
-    public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy {
-
-        @Override
-        public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
-            if (Modifier.isNative(method.getModifiers())) {
-                return false;
-            }
-            if (method.getAnnotation(Fold.class) != null) {
-                return false;
-            }
-            if (method.getAnnotation(NodeIntrinsic.class) != null) {
-                return false;
-            }
-            if (method.getAnnotation(Word.Operation.class) != null) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) {
-            return false;
-        }
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static Boolean valueOf(@Parameter("value") boolean value) {
-        valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic());
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static Byte valueOf(@Parameter("value") byte value) {
-        valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic());
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static Character valueOf(@Parameter("value") char value) {
-        valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic());
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static Double valueOf(@Parameter("value") double value) {
-        valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic());
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static Float valueOf(@Parameter("value") float value) {
-        valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic());
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static Integer valueOf(@Parameter("value") int value) {
-        valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic());
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static Long valueOf(@Parameter("value") long value) {
-        valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic());
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static Short valueOf(@Parameter("value") short value) {
-        valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic());
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static boolean booleanValue(@Parameter("value") Boolean value) {
-        valueOfCounter.inc();
-        return value.booleanValue();
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static byte byteValue(@Parameter("value") Byte value) {
-        valueOfCounter.inc();
-        return value.byteValue();
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static char charValue(@Parameter("value") Character value) {
-        valueOfCounter.inc();
-        return value.charValue();
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static double doubleValue(@Parameter("value") Double value) {
-        valueOfCounter.inc();
-        return value.doubleValue();
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static float floatValue(@Parameter("value") Float value) {
-        valueOfCounter.inc();
-        return value.floatValue();
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static int intValue(@Parameter("value") Integer value) {
-        valueOfCounter.inc();
-        return value.intValue();
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static long longValue(@Parameter("value") Long value) {
-        valueOfCounter.inc();
-        return value.longValue();
-    }
-
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
-    public static short shortValue(@Parameter("value") Short value) {
-        valueOfCounter.inc();
-        return value.shortValue();
-    }
-
-    public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) {
-        ValueNode value = box.getValue();
-        if (value.isConstant()) {
-            Constant sourceConstant = value.asConstant();
-            switch (box.getBoxingKind()) {
-                case Boolean:
-                    return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph());
-                case Byte:
-                    return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph());
-                case Char:
-                    return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph());
-                case Short:
-                    return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph());
-                case Int:
-                    return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph());
-                case Long:
-                    return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph());
-                case Float:
-                    return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph());
-                case Double:
-                    return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph());
-                default:
-                    assert false : "Unexpected source kind for boxing";
-                    break;
-            }
-        }
-        return null;
-    }
-
-    public static class Templates extends AbstractTemplates<BoxingSnippets> {
-
-        private final ResolvedJavaMethod[] valueOfMethods = new ResolvedJavaMethod[Kind.values().length];
-        private final ResolvedJavaMethod[] unboxMethods = new ResolvedJavaMethod[Kind.values().length];
-
-        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, BoxingSnippets.class);
-            for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) {
-                valueOfMethods[kind.ordinal()] = snippet("valueOf", kind.toJavaClass());
-                unboxMethods[kind.ordinal()] = snippet(kind.getJavaName() + "Value", kind.toBoxedJavaClass());
-            }
-        }
-
-        private ResolvedJavaMethod getValueOf(Kind kind) {
-            assert valueOfMethods[kind.ordinal()] != null;
-            return valueOfMethods[kind.ordinal()];
-        }
-
-        private ResolvedJavaMethod getUnbox(Kind kind) {
-            assert unboxMethods[kind.ordinal()] != null;
-            return unboxMethods[kind.ordinal()];
-        }
-
-        public void lower(BoxNode box) {
-            FloatingNode canonical = canonicalizeBoxing(box, runtime);
-            if (canonical != null) {
-                ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical);
-            } else {
-                Key key = new Key(getValueOf(box.getBoxingKind()));
-                Arguments arguments = new Arguments().add("value", box.getValue());
-                SnippetTemplate template = cache.get(key);
-                Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, arguments);
-                template.instantiate(runtime, box, DEFAULT_REPLACER, arguments);
-            }
-        }
-
-        public void lower(UnboxNode unbox) {
-            Key key = new Key(getUnbox(unbox.getBoxingKind()));
-            Arguments arguments = new Arguments().add("value", unbox.getValue());
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, arguments);
-            template.instantiate(runtime, unbox, DEFAULT_REPLACER, arguments);
-        }
-    }
-
-    private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null;
-    private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification");
-
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java	Fri Apr 12 10:53:37 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.replacements;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.extended.*;
-
-public class BoxingSubstitutions {
-
-    @ClassSubstitution(Boolean.class)
-    private static class BooleanSubstitutions {
-
-        @MethodSubstitution(forced = true)
-        public static Boolean valueOf(boolean value) {
-            return BoxNode.box(value, Boolean.class, Kind.Boolean);
-        }
-
-        @MethodSubstitution(isStatic = false, forced = true)
-        public static boolean booleanValue(Boolean value) {
-            return UnboxNode.unbox(value, Kind.Boolean);
-        }
-    }
-
-    @ClassSubstitution(Byte.class)
-    private static class ByteSubstitutions {
-
-        @MethodSubstitution(forced = true)
-        public static Byte valueOf(byte value) {
-            return BoxNode.box(value, Byte.class, Kind.Byte);
-        }
-
-        @MethodSubstitution(isStatic = false, forced = true)
-        public static byte byteValue(Byte value) {
-            return UnboxNode.unbox(value, Kind.Byte);
-        }
-    }
-
-    @ClassSubstitution(Character.class)
-    private static class CharacterSubstitutions {
-
-        @MethodSubstitution(forced = true)
-        public static Character valueOf(char value) {
-            return BoxNode.box(value, Character.class, Kind.Char);
-        }
-
-        @MethodSubstitution(isStatic = false, forced = true)
-        public static char charValue(Character value) {
-            return UnboxNode.unbox(value, Kind.Char);
-        }
-    }
-
-    @ClassSubstitution(Double.class)
-    private static class DoubleSubstitutions {
-
-        @MethodSubstitution(forced = true)
-        public static Double valueOf(double value) {
-            return BoxNode.box(value, Double.class, Kind.Double);
-        }
-
-        @MethodSubstitution(isStatic = false, forced = true)
-        public static double doubleValue(Double value) {
-            return UnboxNode.unbox(value, Kind.Double);
-        }
-    }
-
-    @ClassSubstitution(Float.class)
-    private static class FloatSubstitutions {
-
-        @MethodSubstitution(forced = true)
-        public static Float valueOf(float value) {
-            return BoxNode.box(value, Float.class, Kind.Float);
-        }
-
-        @MethodSubstitution(isStatic = false, forced = true)
-        public static float floatValue(Float value) {
-            return UnboxNode.unbox(value, Kind.Float);
-        }
-    }
-
-    @ClassSubstitution(Integer.class)
-    private static class IntegerSubstitutions {
-
-        @MethodSubstitution(forced = true)
-        public static Integer valueOf(int value) {
-            return BoxNode.box(value, Integer.class, Kind.Int);
-        }
-
-        @MethodSubstitution(isStatic = false, forced = true)
-        public static int intValue(Integer value) {
-            return UnboxNode.unbox(value, Kind.Int);
-        }
-    }
-
-    @ClassSubstitution(Long.class)
-    private static class LongSubstitutions {
-
-        @MethodSubstitution(forced = true)
-        public static Long valueOf(long value) {
-            return BoxNode.box(value, Long.class, Kind.Long);
-        }
-
-        @MethodSubstitution(isStatic = false, forced = true)
-        public static long longValue(Long value) {
-            return UnboxNode.unbox(value, Kind.Long);
-        }
-    }
-
-    @ClassSubstitution(Short.class)
-    private static class ShortSubstitutions {
-
-        @MethodSubstitution(forced = true)
-        public static Short valueOf(short value) {
-            return BoxNode.box(value, Short.class, Kind.Short);
-        }
-
-        @MethodSubstitution(isStatic = false, forced = true)
-        public static short shortValue(Short value) {
-            return UnboxNode.unbox(value, Kind.Short);
-        }
-    }
-
-    public static Class<?>[] getClasses() {
-        return new Class<?>[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class,
-                        LongSubstitutions.class, ShortSubstitutions.class};
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Fri Apr 12 10:54:49 2013 +0200
@@ -40,25 +40,25 @@
             replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
         }
     }
-}
+
+    @ClassSubstitution(ConstantCallSite.class)
+    private static class ConstantCallSiteSubstitutions {
 
-@ClassSubstitution(ConstantCallSite.class)
-class ConstantCallSiteSubstitutions {
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(ConstantCallSite callSite);
+    }
 
-    @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
-    public static native MethodHandle getTarget(ConstantCallSite callSite);
-}
+    @ClassSubstitution(MutableCallSite.class)
+    private static class MutableCallSiteSubstitutions {
 
-@ClassSubstitution(MutableCallSite.class)
-class MutableCallSiteSubstitutions {
-
-    @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
-    public static native MethodHandle getTarget(MutableCallSite callSite);
-}
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(MutableCallSite callSite);
+    }
 
-@ClassSubstitution(VolatileCallSite.class)
-class VolatileCallSiteSubstitutions {
+    @ClassSubstitution(VolatileCallSite.class)
+    private static class VolatileCallSiteSubstitutions {
 
-    @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
-    public static native MethodHandle getTarget(VolatileCallSite callSite);
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(VolatileCallSite callSite);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -28,11 +28,9 @@
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.meta.*;
@@ -42,7 +40,11 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+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.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -58,16 +60,11 @@
     @NodeIntrinsic(BreakpointNode.class)
     static native void bkpt(Object object, Word hub, Word objectHub);
 
-    // @formatter:off
-
     /**
      * Type test used when the type being tested against is a final type.
      */
     @Snippet
-    public static Object checkcastExact(
-                    @Parameter("object") Object object,
-                    @Parameter("exactHub") Word exactHub,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -76,30 +73,25 @@
             if (objectHub.notEqual(exactHub)) {
                 probability(DEOPT_PATH_PROBABILITY);
                 exactMiss.inc();
-                //bkpt(object, exactHub, objectHub);
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
             }
             exactHit.inc();
         }
-        /* make sure that the unsafeCast is done *after* the check above,
-         * cf. ReadAfterCheckCast */
+        /*
+         * make sure that the unsafeCast is done *after* the check above, cf. ReadAfterCheckCast
+         */
         BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
         return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     /**
      * Type test used when the type being tested against is a restricted primary type.
-     *
-     * This test ignores use of hints altogether as the display-based type check only
-     * involves one extra load where the second load should hit the same cache line as the
-     * first.
+     * 
+     * This test ignores use of hints altogether as the display-based type check only involves one
+     * extra load where the second load should hit the same cache line as the first.
      */
     @Snippet
-    public static Object checkcastPrimary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @ConstantParameter("checkNull") boolean checkNull,
-                    @ConstantParameter("superCheckOffset") int superCheckOffset) {
+    public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -120,11 +112,7 @@
      * Type test used when the type being tested against is a restricted secondary type.
      */
     @Snippet
-    public static Object checkcastSecondary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @VarargsParameter("hints") Word[] hints,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -149,14 +137,11 @@
     }
 
     /**
-     * Type test used when the type being tested against is not known at compile time (e.g. the type test
-     * in an object array store check).
+     * Type test used when the type being tested against is not known at compile time (e.g. the type
+     * test in an object array store check).
      */
     @Snippet
-    public static Object checkcastDynamic(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -170,21 +155,15 @@
         return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
-    // @formatter:on
-
-    public static class Templates extends AbstractTemplates<CheckCastSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod exact;
-        private final ResolvedJavaMethod primary;
-        private final ResolvedJavaMethod secondary;
-        private final ResolvedJavaMethod dynamic;
+        private final SnippetInfo exact = snippet(CheckCastSnippets.class, "checkcastExact");
+        private final SnippetInfo primary = snippet(CheckCastSnippets.class, "checkcastPrimary");
+        private final SnippetInfo secondary = snippet(CheckCastSnippets.class, "checkcastSecondary");
+        private final SnippetInfo dynamic = snippet(CheckCastSnippets.class, "checkcastDynamic");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, CheckCastSnippets.class);
-            exact = snippet("checkcastExact", Object.class, Word.class, boolean.class);
-            primary = snippet("checkcastPrimary", Word.class, Object.class, boolean.class, int.class);
-            secondary = snippet("checkcastSecondary", Word.class, Object.class, Word[].class, boolean.class);
-            dynamic = snippet("checkcastDynamic", Word.class, Object.class, boolean.class);
+            super(runtime, replacements, target);
         }
 
         /**
@@ -193,31 +172,34 @@
         public void lower(CheckCastNode checkcast, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) checkcast.graph();
             ValueNode object = checkcast.object();
-            final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type();
+            HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type();
             TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
             ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph());
-            boolean checkNull = !object.stamp().nonNull();
-            Arguments arguments;
-            Key key;
 
-            assert type != null;
+            Arguments args;
             if (hintInfo.exact) {
                 ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
                 assert hints.length == 1;
-                key = new Key(exact).add("checkNull", checkNull);
-                arguments = arguments("object", object).add("exactHub", hints[0]);
+                args = new Arguments(exact);
+                args.add("object", object);
+                args.add("exactHub", hints[0]);
             } else if (type.isPrimaryType()) {
-                key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
-                arguments = arguments("hub", hub).add("object", object);
+                args = new Arguments(primary);
+                args.add("hub", hub);
+                args.add("object", object);
+                args.addConst("superCheckOffset", type.superCheckOffset());
             } else {
                 ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
-                key = new Key(secondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
-                arguments = arguments("hub", hub).add("object", object).add("hints", hints);
+                args = new Arguments(secondary);
+                args.add("hub", hub);
+                args.add("object", object);
+                args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints);
             }
+            args.addConst("checkNull", !object.stamp().nonNull());
 
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments);
-            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments);
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args);
+            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args);
         }
 
         /**
@@ -225,16 +207,16 @@
          */
         public void lower(CheckCastDynamicNode checkcast) {
             StructuredGraph graph = (StructuredGraph) checkcast.graph();
-            ValueNode hub = checkcast.type();
             ValueNode object = checkcast.object();
-            boolean checkNull = !object.stamp().nonNull();
 
-            Key key = new Key(dynamic).add("checkNull", checkNull);
-            Arguments arguments = arguments("hub", hub).add("object", object);
+            Arguments args = new Arguments(dynamic);
+            args.add("hub", checkcast.type());
+            args.add("object", object);
+            args.addConst("checkNull", !object.stamp().nonNull());
 
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments);
-            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments);
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args);
+            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -24,21 +24,22 @@
 
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
-import static com.oracle.graal.replacements.Snippet.Varargs.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -52,18 +53,11 @@
  */
 public class InstanceOfSnippets implements Snippets {
 
-    // @formatter:off
-
     /**
      * A test against a final type.
      */
     @Snippet
-    public static Object instanceofExact(
-                    @Parameter("object") Object object,
-                    @Parameter("exactHub") Word exactHub,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -83,13 +77,7 @@
      * A test against a primary type.
      */
     @Snippet
-    public static Object instanceofPrimary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull,
-                    @ConstantParameter("superCheckOffset") int superCheckOffset) {
+    public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -109,14 +97,8 @@
      * A test against a restricted secondary type type.
      */
     @Snippet
-    public static Object instanceofSecondary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @VarargsParameter("hints") Word[] hints,
-                    @VarargsParameter("hintIsPositive") boolean[] hintIsPositive,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue,
+                    @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -144,12 +126,7 @@
      * Type test used when the type being tested against is not known at compile time.
      */
     @Snippet
-    public static Object instanceofDynamic(
-                    @Parameter("mirror") Class mirror,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -164,65 +141,63 @@
         return trueValue;
     }
 
-    // @formatter:on
-
-    public static class Templates extends InstanceOfSnippetsTemplates<InstanceOfSnippets> {
+    public static class Templates extends InstanceOfSnippetsTemplates {
 
-        private final ResolvedJavaMethod instanceofExact;
-        private final ResolvedJavaMethod instanceofPrimary;
-        private final ResolvedJavaMethod instanceofSecondary;
-        private final ResolvedJavaMethod instanceofDynamic;
+        private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact");
+        private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary");
+        private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary");
+        private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, InstanceOfSnippets.class);
-            instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class);
-            instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class);
-            instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean[].class, boolean.class);
-            instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class);
+            super(runtime, replacements, target);
         }
 
         @Override
-        protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
+        protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
             if (replacer.instanceOf instanceof InstanceOfNode) {
                 InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf;
-                ValueNode trueValue = replacer.trueValue;
-                ValueNode falseValue = replacer.falseValue;
                 ValueNode object = instanceOf.object();
                 TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
                 final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
                 ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph());
-                boolean checkNull = !object.stamp().nonNull();
-                Arguments arguments;
-                Key key;
+
+                Arguments args;
                 if (hintInfo.exact) {
                     ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs;
                     assert hints.length == 1;
-                    key = new Key(instanceofExact).add("checkNull", checkNull);
-                    arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue);
+                    args = new Arguments(instanceofExact);
+                    args.add("object", object);
+                    args.add("exactHub", hints[0]);
                 } else if (type.isPrimaryType()) {
-                    key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
-                    arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
+                    args = new Arguments(instanceofPrimary);
+                    args.add("hub", hub);
+                    args.add("object", object);
+                    args.addConst("superCheckOffset", type.superCheckOffset());
                 } else {
                     Hints hints = createHints(hintInfo, runtime, false, hub.graph());
-                    ConstantNode[] hintHubs = hints.hubs;
-                    boolean[] hintIsPositive = hints.isPositive;
-                    Varargs hintsParam = vargargs(new Word[hintHubs.length], StampFactory.forKind(wordKind()));
-                    Varargs hintIsPositiveParam = vargargs(new boolean[hintIsPositive.length], StampFactory.forKind(Kind.Boolean));
-                    key = new Key(instanceofSecondary).add("hints", hintsParam).add("hintIsPositive", hintIsPositiveParam).add("checkNull", checkNull);
-                    arguments = arguments("hub", hub).add("object", object).add("hints", hintHubs).add("hintIsPositive", hintIsPositive).add("trueValue", trueValue).add("falseValue", falseValue);
+                    args = new Arguments(instanceofSecondary);
+                    args.add("hub", hub);
+                    args.add("object", object);
+                    args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs);
+                    args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive);
                 }
-                return new KeyAndArguments(key, arguments);
+                args.add("trueValue", replacer.trueValue);
+                args.add("falseValue", replacer.falseValue);
+                args.addConst("checkNull", !object.stamp().nonNull());
+                return args;
+
             } else {
                 assert replacer.instanceOf instanceof InstanceOfDynamicNode;
                 InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf;
-                ValueNode trueValue = replacer.trueValue;
-                ValueNode falseValue = replacer.falseValue;
                 ValueNode object = instanceOf.object();
-                ValueNode mirror = instanceOf.mirror();
-                boolean checkNull = !object.stamp().nonNull();
-                Key key = new Key(instanceofDynamic).add("checkNull", checkNull);
-                Arguments arguments = arguments("mirror", mirror).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
-                return new KeyAndArguments(key, arguments);
+
+                Arguments args = new Arguments(instanceofDynamic);
+                args.add("mirror", instanceOf.mirror());
+                args.add("object", object);
+                args.add("trueValue", replacer.trueValue);
+                args.add("falseValue", replacer.falseValue);
+                args.addConst("checkNull", !object.stamp().nonNull());
+                return args;
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -27,16 +27,13 @@
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 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.Key;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -53,23 +50,17 @@
         return unsafeCast(exception, StampFactory.forNodeIntrinsic());
     }
 
-    public static class Templates extends AbstractTemplates<LoadExceptionObjectSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod loadException;
+        private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, LoadExceptionObjectSnippets.class);
-            loadException = snippet("loadException");
+            super(runtime, replacements, target);
         }
 
         public void lower(LoadExceptionObjectNode loadExceptionObject) {
-            StructuredGraph graph = (StructuredGraph) loadExceptionObject.graph();
-            Arguments arguments = new Arguments();
-
-            Key key = new Key(loadException);
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering exception object in %s: node=%s, template=%s, arguments=%s", graph, loadExceptionObject, template, arguments);
-            template.instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, arguments);
+            Arguments args = new Arguments(loadException);
+            template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}.
+ */
+public class MethodHandleInvokeBasicNode extends MacroNode {
+
+    public MethodHandleInvokeBasicNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    @Override
+    protected StructuredGraph getSnippetGraph(LoweringTool tool) {
+        return super.getSnippetGraph(tool);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}.
+ */
+public class MethodHandleLinkToInterfaceNode extends MacroNode {
+
+    public MethodHandleLinkToInterfaceNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}.
+ */
+public class MethodHandleLinkToSpecialNode extends MacroNode {
+
+    public MethodHandleLinkToSpecialNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}.
+ */
+public class MethodHandleLinkToStaticNode extends MacroNode {
+
+    public MethodHandleLinkToStaticNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}.
+ */
+public class MethodHandleLinkToVirtualNode extends MacroNode {
+
+    public MethodHandleLinkToVirtualNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -46,7 +46,10 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+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.*;
 
 /**
@@ -73,7 +76,7 @@
     public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced");
 
     @Snippet
-    public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) {
+    public static void monitorenter(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) {
         verifyOop(object);
 
         if (checkNull && object == null) {
@@ -262,7 +265,7 @@
      * Calls straight out to the monitorenter stub.
      */
     @Snippet
-    public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) {
+    public static void monitorenterStub(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) {
         verifyOop(object);
         incCounter();
         if (checkNull && object == null) {
@@ -276,7 +279,7 @@
     }
 
     @Snippet
-    public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
+    public static void monitorexit(Object object, @ConstantParameter boolean trace) {
         trace(trace, "           object: 0x%016lx\n", Word.fromObject(object));
         if (useBiasedLocking()) {
             // Check for biased locking unlock case, which is a no-op
@@ -328,7 +331,7 @@
      * Calls straight out to the monitorexit stub.
      */
     @Snippet
-    public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
+    public static void monitorexitStub(Object object, @ConstantParameter boolean trace) {
         verifyOop(object);
         traceObject(trace, "-lock{stub}", object);
         MonitorExitStubCall.call(object);
@@ -398,54 +401,45 @@
         }
     }
 
-    public static class Templates extends AbstractTemplates<MonitorSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod monitorenter;
-        private final ResolvedJavaMethod monitorexit;
-        private final ResolvedJavaMethod monitorenterStub;
-        private final ResolvedJavaMethod monitorexitStub;
-        private final ResolvedJavaMethod monitorenterEliminated;
-        private final ResolvedJavaMethod monitorexitEliminated;
-        private final ResolvedJavaMethod initCounter;
-        private final ResolvedJavaMethod checkCounter;
+        private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter");
+        private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit");
+        private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub");
+        private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub");
+        private final SnippetInfo monitorenterEliminated = snippet(MonitorSnippets.class, "monitorenterEliminated");
+        private final SnippetInfo monitorexitEliminated = snippet(MonitorSnippets.class, "monitorexitEliminated");
+        private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter");
+        private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter");
+
         private final boolean useFastLocking;
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useFastLocking) {
-            super(runtime, replacements, target, MonitorSnippets.class);
-            monitorenter = snippet("monitorenter", Object.class, boolean.class, boolean.class);
-            monitorexit = snippet("monitorexit", Object.class, boolean.class);
-            monitorenterStub = snippet("monitorenterStub", Object.class, boolean.class, boolean.class);
-            monitorexitStub = snippet("monitorexitStub", Object.class, boolean.class);
-            monitorenterEliminated = snippet("monitorenterEliminated");
-            monitorexitEliminated = snippet("monitorexitEliminated");
-            initCounter = snippet("initCounter");
-            checkCounter = snippet("checkCounter", String.class);
+            super(runtime, replacements, target);
             this.useFastLocking = useFastLocking;
         }
 
         public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) monitorenterNode.graph();
-
             checkBalancedMonitors(graph);
-
             FrameState stateAfter = monitorenterNode.stateAfter();
-            boolean eliminated = monitorenterNode.eliminated();
-            ResolvedJavaMethod method = eliminated ? monitorenterEliminated : useFastLocking ? monitorenter : monitorenterStub;
-            boolean checkNull = !monitorenterNode.object().stamp().nonNull();
-            Key key = new Key(method);
-            if (method != monitorenterEliminated) {
-                key.add("checkNull", checkNull);
-            }
-            if (!eliminated) {
-                key.add("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
+
+            Arguments args;
+            if (monitorenterNode.eliminated()) {
+                args = new Arguments(monitorenterEliminated);
+            } else {
+                if (useFastLocking) {
+                    args = new Arguments(monitorenter);
+                } else {
+                    args = new Arguments(monitorenterStub);
+                }
+                args.add("object", monitorenterNode.object());
+                args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull());
+                args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
             }
 
-            Arguments arguments = new Arguments();
-            if (!eliminated) {
-                arguments.add("object", monitorenterNode.object());
-            }
-            SnippetTemplate template = cache.get(key);
-            Map<Node, Node> nodes = template.instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, arguments);
+            Map<Node, Node> nodes = template(args).instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, args);
+
             for (Node n : nodes.values()) {
                 if (n instanceof BeginLockScopeNode) {
                     BeginLockScopeNode begin = (BeginLockScopeNode) n;
@@ -460,18 +454,22 @@
         public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) monitorexitNode.graph();
             FrameState stateAfter = monitorexitNode.stateAfter();
-            boolean eliminated = monitorexitNode.eliminated();
-            ResolvedJavaMethod method = eliminated ? monitorexitEliminated : useFastLocking ? monitorexit : monitorexitStub;
-            Key key = new Key(method);
-            if (!eliminated) {
-                key.add("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
+
+            Arguments args;
+            if (monitorexitNode.eliminated()) {
+                args = new Arguments(monitorexitEliminated);
+            } else {
+                if (useFastLocking) {
+                    args = new Arguments(monitorexit);
+                } else {
+                    args = new Arguments(monitorexitStub);
+                }
+                args.add("object", monitorexitNode.object());
+                args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
             }
-            Arguments arguments = new Arguments();
-            if (!eliminated) {
-                arguments.add("object", monitorexitNode.object());
-            }
-            SnippetTemplate template = cache.get(key);
-            Map<Node, Node> nodes = template.instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, arguments);
+
+            Map<Node, Node> nodes = template(args).instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, args);
+
             for (Node n : nodes.values()) {
                 if (n instanceof EndLockScopeNode) {
                     EndLockScopeNode end = (EndLockScopeNode) n;
@@ -521,27 +519,27 @@
                 NodeIterable<MonitorCounterNode> nodes = graph.getNodes().filter(MonitorCounterNode.class);
                 if (nodes.isEmpty()) {
                     // Only insert the nodes if this is the first monitorenter being lowered.
-                    JavaType returnType = initCounter.getSignature().getReturnType(initCounter.getDeclaringClass());
-                    MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter, new ValueNode[0], returnType));
+                    JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass());
+                    MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType));
                     InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0));
                     invoke.setStateAfter(graph.start().stateAfter());
                     graph.addAfterFixed(graph.start(), invoke);
 
-                    StructuredGraph inlineeGraph = replacements.getSnippet(initCounter);
+                    StructuredGraph inlineeGraph = replacements.getSnippet(initCounter.getMethod());
                     InliningUtil.inline(invoke, inlineeGraph, false);
 
                     List<ReturnNode> rets = graph.getNodes().filter(ReturnNode.class).snapshot();
                     for (ReturnNode ret : rets) {
-                        returnType = checkCounter.getSignature().getReturnType(checkCounter.getDeclaringClass());
+                        returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass());
                         Object msg = ((HotSpotRuntime) runtime).registerGCRoot("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d");
                         ConstantNode errMsg = ConstantNode.forObject(msg, runtime, graph);
-                        callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[]{errMsg}, returnType));
+                        callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType));
                         invoke = graph.add(new InvokeNode(callTarget, 0));
                         List<ValueNode> stack = Collections.emptyList();
                         FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false);
                         invoke.setStateAfter(graph.add(stateAfter));
                         graph.addBeforeFixed(ret, invoke);
-                        inlineeGraph = replacements.getSnippet(checkCounter);
+                        inlineeGraph = replacements.getSnippet(checkCounter.getMethod());
                         InliningUtil.inline(invoke, inlineeGraph, false);
                     }
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -26,9 +26,7 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
-import static com.oracle.graal.replacements.Snippet.Varargs.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*;
 
@@ -43,7 +41,11 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+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.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -52,15 +54,16 @@
  */
 public class NewObjectSnippets implements Snippets {
 
-    // @formatter:off
-
     @Snippet
-    public static Word allocate(@Parameter("size") int size) {
+    public static Word allocate(int size) {
         Word thread = thread();
         Word top = readTlabTop(thread);
         Word end = readTlabEnd(thread);
         Word newTop = top.add(size);
-        // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code)
+        /*
+         * this check might lead to problems if the TLAB is within 16GB of the address space end
+         * (checked in c++ code)
+         */
         if (newTop.belowOrEqual(end)) {
             probability(FAST_PATH_PROBABILITY);
             writeTlabTop(thread, newTop);
@@ -70,13 +73,7 @@
     }
 
     @Snippet
-    public static Object initializeObject(
-                    @Parameter("memory") Word memory,
-                    @Parameter("hub") Word hub,
-                    @Parameter("prototypeMarkWord") Word prototypeMarkWord,
-                    @ConstantParameter("size") int size,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("locked") boolean locked) {
+    public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) {
 
         Object result;
         if (memory.equal(0)) {
@@ -91,22 +88,17 @@
             }
             result = memory.toObject();
         }
-        /* make sure that the unsafeCast is anchored after initialization,
-         * see ReadAfterCheckCast and CheckCastSnippets */
+        /*
+         * make sure that the unsafeCast is anchored after initialization, see ReadAfterCheckCast
+         * and CheckCastSnippets
+         */
         BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
         return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     @Snippet
-    public static Object initializeArray(
-                    @Parameter("memory") Word memory,
-                    @Parameter("hub") Word hub,
-                    @Parameter("length") int length,
-                    @Parameter("allocationSize") int allocationSize,
-                    @Parameter("prototypeMarkWord") Word prototypeMarkWord,
-                    @ConstantParameter("headerSize") int headerSize,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("locked") boolean locked) {
+    public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean locked) {
         if (locked) {
             return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents);
         } else {
@@ -135,13 +127,8 @@
     public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF;
 
     @Snippet
-    public static Object allocateArrayAndInitialize(
-                    @Parameter("length") int length,
-                    @ConstantParameter("alignment") int alignment,
-                    @ConstantParameter("headerSize") int headerSize,
-                    @ConstantParameter("log2ElementSize") int log2ElementSize,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("type") ResolvedJavaType type) {
+    public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
+                    @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) {
         if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
             probability(DEOPT_PATH_PROBABILITY);
             // This handles both negative array sizes and very large array sizes
@@ -153,9 +140,10 @@
     }
 
     /**
-     * Computes the size of the memory chunk allocated for an array. This size accounts for the array
-     * header size, boy size and any padding after the last element to satisfy object alignment requirements.
-     *
+     * Computes the size of the memory chunk allocated for an array. This size accounts for the
+     * array header size, boy size and any padding after the last element to satisfy object
+     * alignment requirements.
+     * 
      * @param length the number of elements in the array
      * @param alignment the object alignment requirement
      * @param headerSize the size of the array header
@@ -171,10 +159,7 @@
      * Calls the runtime stub for implementing MULTIANEWARRAY.
      */
     @Snippet
-    public static Object newmultiarray(
-                    @Parameter("hub") Word hub,
-                    @ConstantParameter("rank") int rank,
-                    @VarargsParameter("dimensions") int[] dimensions) {
+    public static Object newmultiarray(Word hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) {
         Word dims = DimensionsNode.allocaDimsArray(rank);
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < rank; i++) {
@@ -184,9 +169,8 @@
     }
 
     /**
-     * Maximum size of an object whose body is initialized by a sequence of
-     * zero-stores to its fields. Larger objects have their bodies initialized
-     * in a loop.
+     * Maximum size of an object whose body is initialized by a sequence of zero-stores to its
+     * fields. Larger objects have their bodies initialized in a loop.
      */
     private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize();
 
@@ -217,7 +201,10 @@
      */
     public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
         memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION);
-        // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null
+        /*
+         * store hub last as the concurrent garbage collectors assume length is valid if hub field
+         * is not null
+         */
         initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
             for (int offset = headerSize; offset < allocationSize; offset += wordSize()) {
@@ -226,27 +213,19 @@
         }
     }
 
-    // @formatter:on
-
-    public static class Templates extends AbstractTemplates<NewObjectSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod allocate;
-        private final ResolvedJavaMethod initializeObject;
-        private final ResolvedJavaMethod initializeArray;
-        private final ResolvedJavaMethod allocateArrayAndInitialize;
-        private final ResolvedJavaMethod newmultiarray;
-        private final TargetDescription target;
+        private final SnippetInfo allocate = snippet(NewObjectSnippets.class, "allocate");
+        private final SnippetInfo initializeObject = snippet(NewObjectSnippets.class, "initializeObject");
+        private final SnippetInfo initializeArray = snippet(NewObjectSnippets.class, "initializeArray");
+        private final SnippetInfo allocateArrayAndInitialize = snippet(NewObjectSnippets.class, "allocateArrayAndInitialize");
+        private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray");
+
         private final boolean useTLAB;
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useTLAB) {
-            super(runtime, replacements, target, NewObjectSnippets.class);
-            this.target = target;
+            super(runtime, replacements, target);
             this.useTLAB = useTLAB;
-            allocate = snippet("allocate", int.class);
-            initializeObject = snippet("initializeObject", Word.class, Word.class, Word.class, int.class, boolean.class, boolean.class);
-            initializeArray = snippet("initializeArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class);
-            allocateArrayAndInitialize = snippet("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, boolean.class, ResolvedJavaType.class);
-            newmultiarray = snippet("newmultiarray", Word.class, int.class, int[].class);
         }
 
         /**
@@ -289,9 +268,10 @@
             int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind));
             if (!useTLAB) {
                 ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph);
-                // value for 'size' doesn't matter as it isn't used since a stub call will be made
-                // anyway
-                // for both allocation and initialization - it just needs to be non-null
+                /*
+                 * value for 'size' doesn't matter as it isn't used since a stub call will be made
+                 * anyway for both allocation and initialization - it just needs to be non-null
+                 */
                 ConstantNode size = ConstantNode.forInt(-1, graph);
                 InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents(), newArrayNode.locked()));
                 graph.replaceFixedWithFixed(newArrayNode, initializeNode);
@@ -304,12 +284,17 @@
                 InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents(), newArrayNode.locked()));
                 graph.replaceFixedWithFixed(newArrayNode, initializeNode);
             } else {
-                Key key = new Key(allocateArrayAndInitialize).add("alignment", alignment).add("headerSize", headerSize).add("log2ElementSize", log2ElementSize).add("fillContents",
-                                newArrayNode.fillContents()).add("type", arrayType);
-                Arguments arguments = new Arguments().add("length", lengthNode);
-                SnippetTemplate template = cache.get(key);
-                Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments);
-                template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, arguments);
+                Arguments args = new Arguments(allocateArrayAndInitialize);
+                args.add("length", lengthNode);
+                args.addConst("alignment", alignment);
+                args.addConst("headerSize", headerSize);
+                args.addConst("log2ElementSize", log2ElementSize);
+                args.addConst("fillContents", newArrayNode.fillContents());
+                args.addConst("type", arrayType);
+
+                SnippetTemplate template = template(args);
+                Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
+                template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args);
             }
         }
 
@@ -317,11 +302,11 @@
         public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph();
             ValueNode size = tlabAllocateNode.size();
-            Key key = new Key(allocate);
-            Arguments arguments = arguments("size", size);
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments);
-            template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, arguments);
+            Arguments args = new Arguments(allocate).add("size", size);
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, args);
+            template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -331,12 +316,18 @@
             assert !type.isArray();
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
             int size = instanceSize(type);
-            Key key = new Key(initializeObject).add("size", size).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked());
             ValueNode memory = initializeNode.memory();
-            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord());
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
-            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(initializeObject);
+            args.add("memory", memory);
+            args.add("hub", hub);
+            args.add("prototypeMarkWord", type.prototypeMarkWord());
+            args.addConst("size", size).addConst("fillContents", initializeNode.fillContents());
+            args.addConst("locked", initializeNode.locked());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args);
+            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -348,13 +339,21 @@
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
             Kind elementKind = elementType.getKind();
             final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind);
-            Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked());
             ValueNode memory = initializeNode.memory();
-            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length",
-                            initializeNode.length());
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
-            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(initializeArray);
+            args.add("memory", memory);
+            args.add("hub", hub);
+            args.add("length", initializeNode.length());
+            args.add("allocationSize", initializeNode.allocationSize());
+            args.add("prototypeMarkWord", type.prototypeMarkWord());
+            args.addConst("headerSize", headerSize);
+            args.addConst("fillContents", initializeNode.fillContents());
+            args.addConst("locked", initializeNode.locked());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args);
+            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -367,10 +366,12 @@
             }
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type();
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
-            Key key = new Key(newmultiarray).add("dimensions", vargargs(new int[rank], StampFactory.forKind(Kind.Int))).add("rank", rank);
-            Arguments arguments = arguments("dimensions", dims).add("hub", hub);
-            SnippetTemplate template = cache.get(key);
-            template.instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(newmultiarray);
+            args.add("hub", hub);
+            args.addConst("rank", rank);
+            args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims);
+            template(args).instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, args);
         }
 
         private static int instanceSize(HotSpotResolvedObjectType type) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -31,18 +31,17 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
-import com.oracle.graal.replacements.Snippet.Parameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
 public class WriteBarrierSnippets implements Snippets {
 
     @Snippet
-    public static void serialArrayWriteBarrier(@Parameter("object") Object obj, @Parameter("location") Object location, @ConstantParameter("usePrecise") boolean usePrecise) {
+    public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) {
         Object object = FixedValueAnchorNode.getObject(obj);
         Pointer oop;
         if (usePrecise) {
@@ -62,7 +61,7 @@
     }
 
     @Snippet
-    public static void serialArrayRangeWriteBarrier(@Parameter("object") Object object, @Parameter("startIndex") int startIndex, @Parameter("length") int length) {
+    public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) {
         Object dest = FixedValueAnchorNode.getObject(object);
         int cardShift = cardTableShift();
         long cardStart = cardTableStart();
@@ -77,37 +76,29 @@
         }
     }
 
-    public static class Templates extends AbstractTemplates<WriteBarrierSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod serialArrayWriteBarrier;
-        private final ResolvedJavaMethod serialArrayRangeWriteBarrier;
+        private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier");
+        private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, WriteBarrierSnippets.class);
-            serialArrayWriteBarrier = snippet("serialArrayWriteBarrier", Object.class, Object.class, boolean.class);
-            serialArrayRangeWriteBarrier = snippet("serialArrayRangeWriteBarrier", Object.class, int.class, int.class);
+            super(runtime, replacements, target);
         }
 
         public void lower(SerialWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = serialArrayWriteBarrier;
-            Key key = new Key(method);
-            key.add("usePrecise", arrayWriteBarrier.usePrecise());
-            Arguments arguments = new Arguments();
-            arguments.add("object", arrayWriteBarrier.getObject());
-            arguments.add("location", arrayWriteBarrier.getLocation());
-            SnippetTemplate template = cache.get(key);
-            template.instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, arguments);
+            Arguments args = new Arguments(serialArrayWriteBarrier);
+            args.add("obj", arrayWriteBarrier.getObject());
+            args.add("location", arrayWriteBarrier.getLocation());
+            args.addConst("usePrecise", arrayWriteBarrier.usePrecise());
+            template(args).instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, args);
         }
 
         public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = serialArrayRangeWriteBarrier;
-            Key key = new Key(method);
-            Arguments arguments = new Arguments();
-            arguments.add("object", arrayRangeWriteBarrier.getObject());
-            arguments.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
-            arguments.add("length", arrayRangeWriteBarrier.getLength());
-            SnippetTemplate template = cache.get(key);
-            template.instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, arguments);
+            Arguments args = new Arguments(serialArrayRangeWriteBarrier);
+            args.add("object", arrayRangeWriteBarrier.getObject());
+            args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
+            args.add("length", arrayRangeWriteBarrier.getLength());
+            template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Apr 12 10:54:49 2013 +0200
@@ -27,15 +27,15 @@
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
 
 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.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -47,14 +47,19 @@
 public class NewArrayStub extends Stub {
 
     public NewArrayStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target, linkage);
+        super(runtime, replacements, target, linkage, "newArray");
     }
 
     @Override
-    protected void populateKey(Key key) {
+    protected Arguments makeArguments(SnippetInfo stub) {
         HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class);
-        Constant intArrayHub = intArrayType.klass();
-        key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewArrayStub"));
+
+        Arguments args = new Arguments(stub);
+        args.add("hub", null);
+        args.add("length", null);
+        args.addConst("intArrayHub", intArrayType.klass());
+        args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub"));
+        return args;
     }
 
     /**
@@ -67,7 +72,7 @@
      * @param log specifies if logging is enabled
      */
     @Snippet
-    private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
+    private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) {
         int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri Apr 12 10:54:49 2013 +0200
@@ -36,8 +36,8 @@
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.Fold;
-import com.oracle.graal.replacements.Snippet.Parameter;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -49,14 +49,18 @@
 public class NewInstanceStub extends Stub {
 
     public NewInstanceStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target, linkage);
+        super(runtime, replacements, target, linkage, "newInstance");
     }
 
     @Override
-    protected void populateKey(Key key) {
+    protected Arguments makeArguments(SnippetInfo stub) {
         HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class);
-        Constant intArrayHub = intArrayType.klass();
-        key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewInstanceStub"));
+
+        Arguments args = new Arguments(stub);
+        args.add("hub", null);
+        args.addConst("intArrayHub", intArrayType.klass());
+        args.addConst("log", Boolean.getBoolean("graal.logNewInstanceStub"));
+        return args;
     }
 
     /**
@@ -67,7 +71,7 @@
      * @param intArrayHub the hub for {@code int[].class}
      */
     @Snippet
-    private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
+    private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) {
         int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION);
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
             if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Apr 12 10:54:49 2013 +0200
@@ -22,9 +22,6 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
-import static java.lang.reflect.Modifier.*;
-
-import java.lang.reflect.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
@@ -42,7 +39,8 @@
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 
 /**
  * Base class for implementing some low level code providing the out-of-line slow path for a
@@ -56,7 +54,7 @@
     /**
      * The method implementing the stub.
      */
-    protected final HotSpotResolvedJavaMethod stubMethod;
+    protected final SnippetInfo stubInfo;
 
     /**
      * The linkage information for the stub.
@@ -69,15 +67,14 @@
     protected InstalledCode stubCode;
 
     /**
-     * Creates a new stub container. The new stub still needs to be {@linkplain #getAddress(Backend)
-     * installed}.
+     * Creates a new stub container. The new stub still needs to be
+     * {@linkplain #getAddress(Backend) installed}.
      * 
      * @param linkage linkage details for a call to the stub
      */
-    @SuppressWarnings("unchecked")
-    public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target, null);
-        stubMethod = findStubMethod(runtime, getClass());
+    public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage, String methodName) {
+        super(runtime, replacements, target);
+        this.stubInfo = snippet(getClass(), methodName);
         this.linkage = linkage;
 
     }
@@ -85,7 +82,7 @@
     /**
      * Adds the {@linkplain ConstantParameter constant} arguments of this stub.
      */
-    protected abstract void populateKey(Key key);
+    protected abstract Arguments makeArguments(SnippetInfo stub);
 
     protected HotSpotRuntime runtime() {
         return (HotSpotRuntime) runtime;
@@ -95,7 +92,7 @@
      * Gets the method implementing this stub.
      */
     public ResolvedJavaMethod getMethod() {
-        return stubMethod;
+        return stubInfo.getMethod();
     }
 
     public HotSpotRuntimeCallTarget getLinkage() {
@@ -109,25 +106,22 @@
      */
     public synchronized long getAddress(Backend backend) {
         if (stubCode == null) {
-            StructuredGraph graph = replacements.getSnippet(stubMethod);
-
-            Key key = new Key(stubMethod);
-            populateKey(key);
-            SnippetTemplate template = cache.get(key);
-            graph = template.copySpecializedGraph();
+            Arguments args = makeArguments(stubInfo);
+            SnippetTemplate template = template(args);
+            StructuredGraph graph = template.copySpecializedGraph();
 
             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(), stubMethod, graph, null, phasePlan,
-                            OptimisticOptimizations.ALL, new SpeculationLog());
+            final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL,
+                            new SpeculationLog());
 
-            stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable<InstalledCode>() {
+            stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable<InstalledCode>() {
 
                 @Override
                 public InstalledCode call() {
-                    InstalledCode installedCode = runtime().addMethod(stubMethod, compResult);
-                    assert installedCode != null : "error installing stub " + stubMethod;
+                    InstalledCode installedCode = runtime().addMethod(getMethod(), compResult);
+                    assert installedCode != null : "error installing stub " + getMethod();
                     if (Debug.isDumpEnabled()) {
                         Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                     }
@@ -135,24 +129,8 @@
                 }
             });
 
-            assert stubCode != null : "error installing stub " + stubMethod;
+            assert stubCode != null : "error installing stub " + getMethod();
         }
         return stubCode.getStart();
     }
-
-    /**
-     * Finds the static method annotated with {@link Snippet} in a given class of which there must
-     * be exactly one.
-     */
-    private static HotSpotResolvedJavaMethod findStubMethod(HotSpotRuntime runtime, Class<?> stubClass) {
-        HotSpotResolvedJavaMethod m = null;
-        for (Method candidate : stubClass.getDeclaredMethods()) {
-            if (isStatic(candidate.getModifiers()) && candidate.getAnnotation(Snippet.class) != null) {
-                assert m == null : "more than one method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass;
-                m = (HotSpotResolvedJavaMethod) runtime.lookupJavaMethod(candidate);
-            }
-        }
-        assert m != null : "no static method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass;
-        return m;
-    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Apr 12 10:54:49 2013 +0200
@@ -1071,7 +1071,7 @@
 
     private void genInvokeDynamic(JavaMethod target) {
         if (target instanceof ResolvedJavaMethod) {
-            Object appendix = constantPool.lookupAppendix(stream.readCPI4());
+            Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC);
             if (appendix != null) {
                 frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph));
             }
@@ -1084,8 +1084,20 @@
 
     private void genInvokeVirtual(JavaMethod target) {
         if (target instanceof ResolvedJavaMethod) {
-            ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
-            genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
+            // Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...)
+            // or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see
+            // https://wikis.oracle.com/display/HotSpotInternals/Method+handles+and+invokedynamic
+            boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers());
+            Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL);
+            if (appendix != null) {
+                frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph));
+            }
+            ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver));
+            if (hasReceiver) {
+                genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
+            } else {
+                appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args);
+            }
         } else {
             handleUnresolvedInvoke(target, InvokeKind.Virtual);
         }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Fri Apr 12 10:54:49 2013 +0200
@@ -133,9 +133,27 @@
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
             PTXAddress addr = address.toAddress();
             switch (address.getKind()) {
+                case Byte:
+                    masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Short:
+                    masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Char:
+                    masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
                 case Int:
                     masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement());
                     break;
+                case Long:
+                    masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Float:
+                    masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Double:
+                    masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
                 case Object:
                     masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement());
                     break;
@@ -162,11 +180,23 @@
             assert isRegister(input);
             PTXAddress addr = address.toAddress();
             switch (address.getKind()) {
+                case Byte:
+                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Short:
+                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
                 case Int:
                     masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
                     break;
-                case Byte:
-                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                case Long:
+                    masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Float:
+                    masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Double:
+                    masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input));
                     break;
                 case Object:
                     masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable, DeoptimizingNode {
+public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode {
 
     @Input private FrameState deoptState;
 
@@ -51,6 +51,11 @@
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.emitDeoptimize(action, this);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -147,6 +147,9 @@
     @Override
     public FrameState stateDuring() {
         FrameState stateAfter = stateAfter();
+        if (stateAfter == null) {
+            return null;
+        }
         FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), kind());
         stateDuring.setDuringCall(true);
         return stateDuring;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -51,5 +51,5 @@
     }
 
     @NodeIntrinsic
-    public static native <T> T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, ValueNode anchor);
+    public static native <T> T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -84,7 +84,7 @@
     }
 
     @NodeIntrinsic
-    public static native void writeMemory(Object object, Object value, Object location);
+    public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter boolean usePreciseWriteBarriers);
 
     @Override
     public Object[] getLocationIdentities() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Fri Apr 12 10:54:49 2013 +0200
@@ -65,7 +65,8 @@
         } else if (stamp.type() != null && !stamp.type().hasFinalizableSubclass()) {
             // if either the declared type of receiver or the holder
             // can be assumed to have no finalizers
-            if (tool.assumptions().useOptimisticAssumptions() && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) {
+            if (tool.assumptions().useOptimisticAssumptions()) {
+                tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type());
                 needsCheck = false;
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Fri Apr 12 10:54:49 2013 +0200
@@ -63,11 +63,6 @@
     Assumptions getAssumptions();
 
     /**
-     * Registers all the snippet methods defined by a given class.
-     */
-    void registerSnippets(Class<?> snippets);
-
-    /**
      * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution
      * macro} substitutions defined by a given class.
      */
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -23,18 +23,20 @@
 package com.oracle.graal.replacements.amd64;
 
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.ConvertNode.Op;
 import com.oracle.graal.nodes.spi.*;
 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;
 
 /**
  * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match
@@ -54,7 +56,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static int f2i(@Parameter("input") float input, @Parameter("result") int result) {
+    public static int f2i(float input, int result) {
         if (result == Integer.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Float.isNaN(input)) {
@@ -80,7 +82,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static long f2l(@Parameter("input") float input, @Parameter("result") long result) {
+    public static long f2l(float input, long result) {
         if (result == Long.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Float.isNaN(input)) {
@@ -106,7 +108,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static int d2i(@Parameter("input") double input, @Parameter("result") int result) {
+    public static int d2i(double input, int result) {
         if (result == Integer.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Double.isNaN(input)) {
@@ -132,7 +134,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static long d2l(@Parameter("input") double input, @Parameter("result") long result) {
+    public static long d2l(double input, long result) {
         if (result == Long.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Double.isNaN(input)) {
@@ -146,34 +148,26 @@
         return result;
     }
 
-    public static class Templates extends AbstractTemplates<AMD64ConvertSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod f2i;
-        private final ResolvedJavaMethod f2l;
-        private final ResolvedJavaMethod d2i;
-        private final ResolvedJavaMethod d2l;
+        private final EnumMap<Op, SnippetInfo> snippets;
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, AMD64ConvertSnippets.class);
-            f2i = snippet("f2i", float.class, int.class);
-            f2l = snippet("f2l", float.class, long.class);
-            d2i = snippet("d2i", double.class, int.class);
-            d2l = snippet("d2l", double.class, long.class);
+            super(runtime, replacements, target);
+
+            snippets = new EnumMap<>(Op.class);
+            snippets.put(Op.F2I, snippet(AMD64ConvertSnippets.class, "f2i"));
+            snippets.put(Op.F2L, snippet(AMD64ConvertSnippets.class, "f2l"));
+            snippets.put(Op.D2I, snippet(AMD64ConvertSnippets.class, "d2i"));
+            snippets.put(Op.D2L, snippet(AMD64ConvertSnippets.class, "d2l"));
         }
 
         public void lower(ConvertNode convert, LoweringTool tool) {
-            if (convert.opcode == Op.F2I) {
-                lower0(convert, tool, f2i);
-            } else if (convert.opcode == Op.F2L) {
-                lower0(convert, tool, f2l);
-            } else if (convert.opcode == Op.D2I) {
-                lower0(convert, tool, d2i);
-            } else if (convert.opcode == Op.D2L) {
-                lower0(convert, tool, d2l);
+            SnippetInfo key = snippets.get(convert.opcode);
+            if (key == null) {
+                return;
             }
-        }
 
-        private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) {
             StructuredGraph graph = (StructuredGraph) convert.graph();
 
             // Insert a unique placeholder node in place of the Convert node so that the
@@ -183,11 +177,13 @@
 
             LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp()));
             convert.replaceAtUsages(replacee);
-            Key key = new Key(snippet);
-            Arguments arguments = arguments("input", convert.value()).add("result", convert);
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments);
-            template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments);
+            Arguments args = new Arguments(key);
+            args.add("input", convert.value());
+            args.add("result", convert);
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args);
+            template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, args);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,243 @@
+/*
+ * 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.replacements;
+
+import static com.oracle.graal.replacements.SnippetTemplate.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.replacements.Snippet.Fold;
+import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
+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.*;
+
+public class BoxingSnippets implements Snippets {
+
+    /**
+     * This snippet inlining policy differs from the default one in that it does normal inlining of
+     * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution).
+     */
+    public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy {
+
+        @Override
+        public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
+            if (Modifier.isNative(method.getModifiers())) {
+                return false;
+            }
+            if (method.getAnnotation(Fold.class) != null) {
+                return false;
+            }
+            if (method.getAnnotation(NodeIntrinsic.class) != null) {
+                return false;
+            }
+            if (method.getAnnotation(Word.Operation.class) != null) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) {
+            return false;
+        }
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Boolean booleanValueOf(boolean value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Byte byteValueOf(byte value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Character charValueOf(char value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Double doubleValueOf(double value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Float floatValueOf(float value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Integer intValueOf(int value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Long longValueOf(long value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Short shortValueOf(short value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static boolean booleanValue(Boolean value) {
+        valueOfCounter.inc();
+        return value.booleanValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static byte byteValue(Byte value) {
+        valueOfCounter.inc();
+        return value.byteValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static char charValue(Character value) {
+        valueOfCounter.inc();
+        return value.charValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static double doubleValue(Double value) {
+        valueOfCounter.inc();
+        return value.doubleValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static float floatValue(Float value) {
+        valueOfCounter.inc();
+        return value.floatValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static int intValue(Integer value) {
+        valueOfCounter.inc();
+        return value.intValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static long longValue(Long value) {
+        valueOfCounter.inc();
+        return value.longValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static short shortValue(Short value) {
+        valueOfCounter.inc();
+        return value.shortValue();
+    }
+
+    public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) {
+        ValueNode value = box.getValue();
+        if (value.isConstant()) {
+            Constant sourceConstant = value.asConstant();
+            switch (box.getBoxingKind()) {
+                case Boolean:
+                    return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph());
+                case Byte:
+                    return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph());
+                case Char:
+                    return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph());
+                case Short:
+                    return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph());
+                case Int:
+                    return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph());
+                case Long:
+                    return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph());
+                case Float:
+                    return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph());
+                case Double:
+                    return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph());
+                default:
+                    assert false : "Unexpected source kind for boxing";
+                    break;
+            }
+        }
+        return null;
+    }
+
+    public static class Templates extends AbstractTemplates {
+
+        private final EnumMap<Kind, SnippetInfo> boxSnippets = new EnumMap<>(Kind.class);
+        private final EnumMap<Kind, SnippetInfo> unboxSnippets = new EnumMap<>(Kind.class);
+
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
+            for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) {
+                boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf"));
+                unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value"));
+            }
+        }
+
+        public void lower(BoxNode box) {
+            FloatingNode canonical = canonicalizeBoxing(box, runtime);
+            if (canonical != null) {
+                ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical);
+            } else {
+                Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()));
+                args.add("value", box.getValue());
+
+                SnippetTemplate template = template(args);
+                Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args);
+                template.instantiate(runtime, box, DEFAULT_REPLACER, args);
+            }
+        }
+
+        public void lower(UnboxNode unbox) {
+            Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()));
+            args.add("value", unbox.getValue());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args);
+            template.instantiate(runtime, unbox, DEFAULT_REPLACER, args);
+        }
+    }
+
+    private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null;
+    private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification");
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java	Fri Apr 12 10:54:49 2013 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.extended.*;
+
+public class BoxingSubstitutions {
+
+    @ClassSubstitution(Boolean.class)
+    private static class BooleanSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Boolean valueOf(boolean value) {
+            return BoxNode.box(value, Boolean.class, Kind.Boolean);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static boolean booleanValue(Boolean value) {
+            return UnboxNode.unbox(value, Kind.Boolean);
+        }
+    }
+
+    @ClassSubstitution(Byte.class)
+    private static class ByteSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Byte valueOf(byte value) {
+            return BoxNode.box(value, Byte.class, Kind.Byte);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static byte byteValue(Byte value) {
+            return UnboxNode.unbox(value, Kind.Byte);
+        }
+    }
+
+    @ClassSubstitution(Character.class)
+    private static class CharacterSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Character valueOf(char value) {
+            return BoxNode.box(value, Character.class, Kind.Char);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static char charValue(Character value) {
+            return UnboxNode.unbox(value, Kind.Char);
+        }
+    }
+
+    @ClassSubstitution(Double.class)
+    private static class DoubleSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Double valueOf(double value) {
+            return BoxNode.box(value, Double.class, Kind.Double);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static double doubleValue(Double value) {
+            return UnboxNode.unbox(value, Kind.Double);
+        }
+    }
+
+    @ClassSubstitution(Float.class)
+    private static class FloatSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Float valueOf(float value) {
+            return BoxNode.box(value, Float.class, Kind.Float);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static float floatValue(Float value) {
+            return UnboxNode.unbox(value, Kind.Float);
+        }
+    }
+
+    @ClassSubstitution(Integer.class)
+    private static class IntegerSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Integer valueOf(int value) {
+            return BoxNode.box(value, Integer.class, Kind.Int);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static int intValue(Integer value) {
+            return UnboxNode.unbox(value, Kind.Int);
+        }
+    }
+
+    @ClassSubstitution(Long.class)
+    private static class LongSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Long valueOf(long value) {
+            return BoxNode.box(value, Long.class, Kind.Long);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static long longValue(Long value) {
+            return UnboxNode.unbox(value, Kind.Long);
+        }
+    }
+
+    @ClassSubstitution(Short.class)
+    private static class ShortSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Short valueOf(short value) {
+            return BoxNode.box(value, Short.class, Kind.Short);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static short shortValue(Short value) {
+            return UnboxNode.unbox(value, Kind.Short);
+        }
+    }
+
+    public static Class<?>[] getClasses() {
+        return new Class<?>[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class,
+                        LongSubstitutions.class, ShortSubstitutions.class};
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Fri Apr 12 10:54:49 2013 +0200
@@ -33,6 +33,10 @@
 public class GraalMethodSubstitutions implements ReplacementsProvider {
 
     public void registerReplacements(Replacements replacements) {
+        for (Class<?> clazz : BoxingSubstitutions.getClasses()) {
+            replacements.registerSubstitutions(clazz);
+        }
+
         if (GraalOptions.Intrinsify) {
             replacements.registerSubstitutions(MathSubstitutionsX86.class);
             replacements.registerSubstitutions(DoubleSubstitutions.class);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Fri Apr 12 10:54:49 2013 +0200
@@ -34,7 +34,9 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.UsageReplacer;
 
 /**
  * Helper class for lowering {@link InstanceOfNode}s with snippets. The majority of the complexity
@@ -49,31 +51,16 @@
  * {@link IfNode}. This avoids materializing the instanceof test as a boolean which is then retested
  * by the {@link IfNode}.
  */
-public abstract class InstanceOfSnippetsTemplates<T extends Snippets> extends AbstractTemplates<T> {
+public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates {
 
-    public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class<T> snippetsClass) {
-        super(runtime, replacements, target, snippetsClass);
+    public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+        super(runtime, replacements, target);
     }
 
     /**
-     * The key and arguments used to retrieve and instantiate an instanceof snippet template.
+     * Gets the arguments used to retrieve and instantiate an instanceof snippet template.
      */
-    public static class KeyAndArguments {
-
-        public final Key key;
-        public final Arguments arguments;
-
-        public KeyAndArguments(Key key, Arguments arguments) {
-            this.key = key;
-            this.arguments = arguments;
-        }
-
-    }
-
-    /**
-     * Gets the key and arguments used to retrieve and instantiate an instanceof snippet template.
-     */
-    protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool);
+    protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool);
 
     public void lower(FloatingNode instanceOf, LoweringTool tool) {
         assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode;
@@ -90,9 +77,8 @@
                 // No need to re-instantiate the snippet - just re-use its result
                 replacer.replaceUsingInstantiation();
             } else {
-                KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool);
-                SnippetTemplate template = cache.get(keyAndArguments.key);
-                template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments);
+                Arguments args = makeArguments(replacer, tool);
+                template(args).instantiate(runtime, instanceOf, replacer, tool, args);
             }
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Apr 12 10:54:49 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,6 @@
     // These data structures are all fully initialized during single-threaded
     // compiler startup and so do not need to be concurrent.
     private final Map<ResolvedJavaMethod, ResolvedJavaMethod> registeredMethodSubstitutions;
-    private final Set<ResolvedJavaMethod> registeredSnippets;
     private final Map<ResolvedJavaMethod, Class<? extends FixedWithNextNode>> registerMacroSubstitutions;
     private final Set<ResolvedJavaMethod> forcedSubstitutions;
 
@@ -70,36 +69,20 @@
         this.assumptions = assumptions;
         this.graphs = new ConcurrentHashMap<>();
         this.registeredMethodSubstitutions = new HashMap<>();
-        this.registeredSnippets = new HashSet<>();
         this.registerMacroSubstitutions = new HashMap<>();
         this.forcedSubstitutions = new HashSet<>();
     }
 
-    public void registerSnippets(Class<?> snippets) {
-        assert Snippets.class.isAssignableFrom(snippets);
-        for (Method method : snippets.getDeclaredMethods()) {
-            if (method.getAnnotation(Snippet.class) != null) {
-                int modifiers = method.getModifiers();
-                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
-                    throw new RuntimeException("Snippet must not be abstract or native");
-                }
-                ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method);
-                registeredSnippets.add(snippet);
-            }
-        }
-    }
+    public StructuredGraph getSnippet(ResolvedJavaMethod method) {
+        assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName();
+        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native";
 
-    public StructuredGraph getSnippet(ResolvedJavaMethod method) {
-        if (!registeredSnippets.contains(method)) {
-            return null;
-        }
         StructuredGraph graph = graphs.get(method);
         if (graph == null) {
             graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method)));
             graph = graphs.get(method);
         }
         return graph;
-
     }
 
     public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) {
@@ -488,7 +471,6 @@
     @Override
     public Collection<ResolvedJavaMethod> getAllReplacements() {
         HashSet<ResolvedJavaMethod> result = new HashSet<>();
-        result.addAll(registeredSnippets);
         result.addAll(registeredMethodSubstitutions.keySet());
         result.addAll(registerMacroSubstitutions.keySet());
         return result;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Fri Apr 12 10:54:49 2013 +0200
@@ -27,7 +27,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -122,20 +121,6 @@
     }
 
     /**
-     * Denotes a snippet parameter that will be bound during snippet template
-     * {@linkplain SnippetTemplate#instantiate instantiation}.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.PARAMETER)
-    public @interface Parameter {
-
-        /**
-         * The name of this parameter.
-         */
-        String value();
-    }
-
-    /**
      * Denotes a snippet parameter representing 0 or more arguments that will be bound during
      * snippet template {@linkplain SnippetTemplate#instantiate instantiation}. During snippet
      * template creation, its value must be an array whose length specifies the number of arguments
@@ -149,11 +134,6 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.PARAMETER)
     public @interface VarargsParameter {
-
-        /**
-         * The name of this parameter.
-         */
-        String value();
     }
 
     /**
@@ -163,61 +143,5 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.PARAMETER)
     public @interface ConstantParameter {
-
-        /**
-         * The name of this constant.
-         */
-        String value();
-    }
-
-    /**
-     * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter.
-     */
-    public static class Varargs {
-
-        private final Object args;
-        private final Class argType;
-        private final int length;
-        private final Stamp argStamp;
-
-        public static Varargs vargargs(Object array, Stamp argStamp) {
-            return new Varargs(array, argStamp);
-        }
-
-        public Varargs(Object array, Stamp argStamp) {
-            assert array != null;
-            this.argType = array.getClass().getComponentType();
-            this.argStamp = argStamp;
-            assert this.argType != null;
-            this.length = java.lang.reflect.Array.getLength(array);
-            this.args = array;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Varargs) {
-                Varargs other = (Varargs) obj;
-                return other.argType == argType && other.length == length;
-            }
-            return false;
-        }
-
-        public Object getArray() {
-            return args;
-        }
-
-        public Stamp getArgStamp() {
-            return argStamp;
-        }
-
-        @Override
-        public int hashCode() {
-            return argType.hashCode() ^ length;
-        }
-
-        @Override
-        public String toString() {
-            return argType.getName() + "[" + length + "]";
-        }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Apr 12 10:53:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Apr 12 10:54:49 2013 +0200
@@ -22,11 +22,8 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.Map.Entry;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
@@ -42,8 +39,6 @@
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
-import com.oracle.graal.replacements.Snippet.Parameter;
-import com.oracle.graal.replacements.Snippet.Varargs;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
@@ -53,173 +48,274 @@
  * A snippet template is a graph created by parsing a snippet method and then specialized by binding
  * constants to the snippet's {@link ConstantParameter} parameters.
  * 
- * Snippet templates can be managed in a {@link Cache}.
+ * Snippet templates can be managed in a cache maintained by {@link AbstractTemplates}.
  */
 public class SnippetTemplate {
 
     /**
-     * A snippet template key encapsulates the method from which a snippet was built and the
-     * arguments used to specialize the snippet.
-     * 
-     * @see Cache
+     * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the
+     * method that needs to be computed only once. The {@link SnippetInfo} should be created once
+     * per snippet an then cached.
      */
-    public static class Key implements Iterable<Map.Entry<String, Object>> {
+    public static class SnippetInfo {
+
+        protected final ResolvedJavaMethod method;
+        protected final ConstantParameter[] constantParameters;
+        protected final VarargsParameter[] varargsParameters;
+
+        /**
+         * The parameter names, taken from the local variables table. Only used for assertion
+         * checking, so use only within an assert statement.
+         */
+        protected final String[] names;
+
+        protected SnippetInfo(ResolvedJavaMethod method) {
+            this.method = method;
 
-        public final ResolvedJavaMethod method;
-        private final HashMap<String, Object> map = new HashMap<>();
-        private int hash;
+            assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
+            int count = method.getSignature().getParameterCount(false);
+            constantParameters = new ConstantParameter[count];
+            varargsParameters = new VarargsParameter[count];
+            for (int i = 0; i < count; i++) {
+                constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
+                varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method);
+
+                assert !isConstantParameter(i) || !isVarargsParameter(i) : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" +
+                                VarargsParameter.class.getSimpleName();
+            }
 
-        public Key(ResolvedJavaMethod method) {
-            this.method = method;
-            this.hash = method.hashCode();
+            names = new String[count];
+            // Retrieve the names only when assertions are turned on.
+            assert initNames();
+        }
+
+        private boolean initNames() {
+            int slotIdx = 0;
+            for (int i = 0; i < names.length; i++) {
+                names[i] = method.getLocalVariableTable().getLocal(slotIdx, 0).getName();
+
+                Kind kind = method.getSignature().getParameterKind(i);
+                slotIdx += kind == Kind.Long || kind == Kind.Double ? 2 : 1;
+            }
+            return true;
         }
 
-        public Key add(String name, Object value) {
-            assert !map.containsKey(name);
-            map.put(name, value);
-            hash = hash ^ name.hashCode();
-            if (value != null) {
-                hash *= (value.hashCode() + 1);
-            }
+        public ResolvedJavaMethod getMethod() {
+            return method;
+        }
+
+        public int getParameterCount() {
+            return constantParameters.length;
+        }
+
+        public boolean isConstantParameter(int paramIdx) {
+            return constantParameters[paramIdx] != null;
+        }
+
+        public boolean isVarargsParameter(int paramIdx) {
+            return varargsParameters[paramIdx] != null;
+        }
+    }
+
+    /**
+     * Values that are bound to the snippet method parameters. The methods {@link #add},
+     * {@link #addConst}, and {@link #addVarargs} must be called in the same order as in the
+     * signature of the snippet method. The parameter name is passed to the add methods for
+     * assertion checking, i.e., to enforce that the order matches. Which method needs to be called
+     * depends on the annotation of the snippet method parameter:
+     * <ul>
+     * <li>Use {@link #add} for a parameter without an annotation. The value is bound when the
+     * {@link SnippetTemplate} is {@link SnippetTemplate#instantiate instantiated}.
+     * <li>Use {@link #addConst} for a parameter annotated with {@link ConstantParameter}. The value
+     * is bound when the {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created}.
+     * <li>Use {@link #addVarargs} for an array parameter annotated with {@link VarargsParameter}. A
+     * separate {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created} for every
+     * distinct array length. The actual values are bound when the {@link SnippetTemplate} is
+     * {@link SnippetTemplate#instantiate instantiated}
+     * </ul>
+     */
+    public static class Arguments {
+
+        protected final SnippetInfo info;
+        protected final CacheKey cacheKey;
+        protected final Object[] values;
+
+        protected int nextParamIdx;
+
+        public Arguments(SnippetInfo info) {
+            this.info = info;
+            this.cacheKey = new CacheKey(info);
+            this.values = new Object[info.getParameterCount()];
+        }
+
+        public Arguments add(String name, Object value) {
+            assert check(name, false, false);
+            values[nextParamIdx] = value;
+            nextParamIdx++;
             return this;
         }
 
-        public int length() {
-            return map.size();
+        public Arguments addConst(String name, Object value) {
+            assert check(name, true, false);
+            values[nextParamIdx] = value;
+            cacheKey.setParam(nextParamIdx, value);
+            nextParamIdx++;
+            return this;
         }
 
-        public Object get(String name) {
-            return map.get(name);
+        public Arguments addVarargs(String name, Class componentType, Stamp argStamp, Object value) {
+            assert check(name, false, true);
+            Varargs varargs = new Varargs(componentType, argStamp, value);
+            values[nextParamIdx] = varargs;
+            // A separate template is necessary for every distinct array length
+            cacheKey.setParam(nextParamIdx, varargs.length);
+            nextParamIdx++;
+            return this;
+        }
+
+        private boolean check(String name, boolean constParam, boolean varargsParam) {
+            assert nextParamIdx < info.getParameterCount() : "too many parameters: " + name + "  " + this;
+            assert info.names[nextParamIdx].equals(name) : "wrong parameter name: " + name + "  " + this;
+            assert constParam == info.isConstantParameter(nextParamIdx) : "Parameter " + (constParam ? "not " : "") + "annotated with @" + ConstantParameter.class.getSimpleName() + ": " + name +
+                            "  " + this;
+            assert varargsParam == info.isVarargsParameter(nextParamIdx) : "Parameter " + (varargsParam ? "not " : "") + "annotated with @" + VarargsParameter.class.getSimpleName() + ": " + name +
+                            "  " + this;
+            return true;
         }
 
         @Override
-        public Iterator<Entry<String, Object>> iterator() {
-            return map.entrySet().iterator();
+        public String toString() {
+            StringBuilder result = new StringBuilder();
+            result.append("Parameters<").append(MetaUtil.format("%H.%n", info.method)).append(" [");
+            String sep = "";
+            for (int i = 0; i < info.getParameterCount(); i++) {
+                result.append(sep);
+                if (info.isConstantParameter(i)) {
+                    result.append("const ");
+                } else if (info.isVarargsParameter(i)) {
+                    result.append("varargs ");
+                }
+                result.append(info.names[i]).append(" = ").append(values[i]);
+                sep = ", ";
+            }
+            result.append(">");
+            return result.toString();
+        }
+    }
+
+    /**
+     * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter.
+     */
+    static class Varargs {
+
+        protected final Class componentType;
+        protected final Stamp stamp;
+        protected final Object value;
+        protected final int length;
+
+        protected Varargs(Class componentType, Stamp stamp, Object value) {
+            this.componentType = componentType;
+            this.stamp = stamp;
+            this.value = value;
+            if (value instanceof List) {
+                this.length = ((List) value).size();
+            } else {
+                this.length = Array.getLength(value);
+            }
+        }
+    }
+
+    static class CacheKey {
+
+        private final ResolvedJavaMethod method;
+        private final Object[] values;
+        private int hash;
+
+        protected CacheKey(SnippetInfo info) {
+            this.method = info.method;
+            this.values = new Object[info.getParameterCount()];
+            this.hash = info.method.hashCode();
+        }
+
+        protected void setParam(int paramIdx, Object value) {
+            values[paramIdx] = value;
+            hash = (hash * 31) ^ (value == null ? 0 : value.hashCode());
         }
 
         @Override
         public boolean equals(Object obj) {
-            if (obj instanceof Key) {
-                Key other = (Key) obj;
-                return other.method == method && other.map.equals(map);
+            if (!(obj instanceof CacheKey)) {
+                return false;
+            }
+            CacheKey other = (CacheKey) obj;
+            if (method != other.method) {
+                return false;
             }
-            return false;
+            for (int i = 0; i < values.length; i++) {
+                if (values[i] != null && !values[i].equals(other.values[i])) {
+                    return false;
+                }
+            }
+            return true;
         }
 
         @Override
         public int hashCode() {
             return hash;
         }
-
-        @Override
-        public String toString() {
-            return MetaUtil.format("%h.%n", method) + map.toString();
-        }
-
-        public Set<String> names() {
-            return map.keySet();
-        }
     }
 
     /**
-     * Arguments used to instantiate a template.
+     * Base class for snippet classes. It provides a cache for {@link SnippetTemplate}s.
      */
-    public static class Arguments implements Iterable<Map.Entry<String, Object>> {
-
-        private final HashMap<String, Object> map = new HashMap<>();
-
-        public static Arguments arguments(String name, Object value) {
-            return new Arguments().add(name, value);
-        }
-
-        public Arguments add(String name, Object value) {
-            assert !map.containsKey(name);
-            map.put(name, value);
-            return this;
-        }
-
-        public int length() {
-            return map.size();
-        }
+    public abstract static class AbstractTemplates {
 
-        @Override
-        public Iterator<Entry<String, Object>> iterator() {
-            return map.entrySet().iterator();
-        }
-
-        @Override
-        public String toString() {
-            return map.toString();
-        }
-    }
+        protected final MetaAccessProvider runtime;
+        protected final Replacements replacements;
+        protected final TargetDescription target;
+        private final ConcurrentHashMap<CacheKey, SnippetTemplate> templates;
 
-    /**
-     * A collection of snippet templates accessed by a {@link Key} instance.
-     */
-    public static class Cache {
-
-        private final ConcurrentHashMap<SnippetTemplate.Key, SnippetTemplate> templates = new ConcurrentHashMap<>();
-        private final MetaAccessProvider runtime;
-        private final TargetDescription target;
-        private final Replacements replacements;
-
-        public Cache(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+        protected AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
             this.runtime = runtime;
             this.replacements = replacements;
             this.target = target;
+            this.templates = new ConcurrentHashMap<>();
+        }
+
+        protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName) {
+            Method found = null;
+            for (Method method : declaringClass.getDeclaredMethods()) {
+                if (method.getAnnotation(Snippet.class) != null && method.getName().equals(methodName)) {
+                    assert found == null : "found more than one @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass;
+                    found = method;
+                }
+            }
+            assert found != null : "did not find @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass;
+
+            return new SnippetInfo(runtime.lookupJavaMethod(found));
         }
 
         /**
          * Gets a template for a given key, creating it first if necessary.
          */
-        public SnippetTemplate get(final SnippetTemplate.Key key) {
-            SnippetTemplate template = templates.get(key);
+        protected SnippetTemplate template(final Arguments args) {
+            SnippetTemplate template = templates.get(args.cacheKey);
             if (template == null) {
-                template = Debug.scope("SnippetSpecialization", key.method, new Callable<SnippetTemplate>() {
+                template = Debug.scope("SnippetSpecialization", args.info.method, new Callable<SnippetTemplate>() {
 
                     @Override
                     public SnippetTemplate call() throws Exception {
-                        return new SnippetTemplate(runtime, replacements, target, key);
+                        return new SnippetTemplate(runtime, replacements, target, args);
                     }
                 });
-                templates.put(key, template);
+                templates.put(args.cacheKey, template);
             }
             return template;
         }
     }
 
-    public abstract static class AbstractTemplates<T extends Snippets> {
-
-        protected final Cache cache;
-        protected final MetaAccessProvider runtime;
-        protected final Replacements replacements;
-        protected Class<?> snippetsClass;
-
-        public AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class<T> snippetsClass) {
-            this.runtime = runtime;
-            this.replacements = replacements;
-            if (snippetsClass == null) {
-                assert this instanceof Snippets;
-                this.snippetsClass = getClass();
-            } else {
-                this.snippetsClass = snippetsClass;
-            }
-            this.cache = new Cache(runtime, replacements, target);
-            replacements.registerSnippets(this.snippetsClass);
-        }
-
-        protected ResolvedJavaMethod snippet(String name, Class<?>... parameterTypes) {
-            try {
-                ResolvedJavaMethod snippet = runtime.lookupJavaMethod(snippetsClass.getDeclaredMethod(name, parameterTypes));
-                assert snippet.getAnnotation(Snippet.class) != null : "snippet is not annotated with @" + Snippet.class.getSimpleName();
-                return snippet;
-            } catch (NoSuchMethodException e) {
-                throw new GraalInternalError(e);
-            }
-        }
-    }
-
     private static final Object UNUSED_PARAMETER = "DEAD PARAMETER";
+    private static final Object CONSTANT_PARAMETER = "CONSTANT";
 
     /**
      * Determines if any parameter of a given method is annotated with {@link ConstantParameter}.
@@ -236,31 +332,25 @@
     /**
      * Creates a snippet template.
      */
-    public SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, SnippetTemplate.Key key) {
-        ResolvedJavaMethod method = key.method;
-        assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + method;
+    protected SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Arguments args) {
+        StructuredGraph snippetGraph = replacements.getSnippet(args.info.method);
+
+        ResolvedJavaMethod method = snippetGraph.method();
         Signature signature = method.getSignature();
 
         // Copy snippet graph, replacing constant parameters with given arguments
-        StructuredGraph snippetGraph = replacements.getSnippet(method);
-        if (snippetGraph == null) {
-            throw new GraalInternalError("Snippet has not been registered: %s", format("%H.%n(%p)", method));
-        }
         StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method());
         IdentityHashMap<Node, Node> nodeReplacements = new IdentityHashMap<>();
         nodeReplacements.put(snippetGraph.start(), snippetCopy.start());
 
-        int parameterCount = signature.getParameterCount(false);
-        assert checkTemplate(runtime, key, parameterCount, method, signature);
+        assert checkTemplate(runtime, args, method, signature);
 
-        Parameter[] parameterAnnotations = new Parameter[parameterCount];
-        VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount];
+        int parameterCount = args.info.getParameterCount();
         ConstantNode[] placeholders = new ConstantNode[parameterCount];
+
         for (int i = 0; i < parameterCount; i++) {
-            ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
-            if (c != null) {
-                String name = c.value();
-                Object arg = key.get(name);
+            if (args.info.isConstantParameter(i)) {
+                Object arg = args.values[i];
                 Kind kind = signature.getParameterKind(i);
                 Constant constantArg;
                 if (arg instanceof Constant) {
@@ -269,19 +359,12 @@
                     constantArg = Constant.forBoxed(kind, arg);
                 }
                 nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy));
-            } else {
-                VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method);
-                if (vp != null) {
-                    String name = vp.value();
-                    Varargs varargs = (Varargs) key.get(name);
-                    Object array = varargs.getArray();
-                    ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy);
-                    nodeReplacements.put(snippetGraph.getLocal(i), placeholder);
-                    placeholders[i] = placeholder;
-                    varargsParameterAnnotations[i] = vp;
-                } else {
-                    parameterAnnotations[i] = MetaUtil.getParameterAnnotation(Parameter.class, i, method);
-                }
+            } else if (args.info.isVarargsParameter(i)) {
+                Varargs varargs = (Varargs) args.values[i];
+                Object array = Array.newInstance(varargs.componentType, varargs.length);
+                ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy);
+                nodeReplacements.put(snippetGraph.getLocal(i), placeholder);
+                placeholders[i] = placeholder;
             }
         }
         snippetCopy.addDuplicates(snippetGraph.getNodes(), nodeReplacements);
@@ -297,23 +380,23 @@
         assert NodeIntrinsificationVerificationPhase.verify(snippetCopy);
 
         // Gather the template parameters
-        parameters = new HashMap<>();
+        parameters = new Object[parameterCount];
         for (int i = 0; i < parameterCount; i++) {
-            VarargsParameter vp = varargsParameterAnnotations[i];
-            if (vp != null) {
+            if (args.info.isConstantParameter(i)) {
+                parameters[i] = CONSTANT_PARAMETER;
+            } else if (args.info.isVarargsParameter(i)) {
                 assert snippetCopy.getLocal(i) == null;
-                Varargs varargs = (Varargs) key.get(vp.value());
-                Object array = varargs.getArray();
-                int length = Array.getLength(array);
+                Varargs varargs = (Varargs) args.values[i];
+                int length = varargs.length;
                 LocalNode[] locals = new LocalNode[length];
-                Stamp stamp = varargs.getArgStamp();
+                Stamp stamp = varargs.stamp;
                 for (int j = 0; j < length; j++) {
                     assert (parameterCount & 0xFFFF) == parameterCount;
                     int idx = i << 16 | j;
                     LocalNode local = snippetCopy.unique(new LocalNode(idx, stamp));
                     locals[j] = local;
                 }
-                parameters.put(vp.value(), locals);
+                parameters[i] = locals;
 
                 ConstantNode placeholder = placeholders[i];
                 assert placeholder != null;
@@ -327,15 +410,12 @@
                     }
                 }
             } else {
-                Parameter p = parameterAnnotations[i];
-                if (p != null) {
-                    LocalNode local = snippetCopy.getLocal(i);
-                    if (local == null) {
-                        // Parameter value was eliminated
-                        parameters.put(p.value(), UNUSED_PARAMETER);
-                    } else {
-                        parameters.put(p.value(), local);
-                    }
+                LocalNode local = snippetCopy.getLocal(i);
+                if (local == null) {
+                    // Parameter value was eliminated
+                    parameters[i] = UNUSED_PARAMETER;
+                } else {
+                    parameters[i] = local;
                 }
             }
         }
@@ -434,11 +514,11 @@
         return true;
     }
 
-    private static boolean checkVarargs(final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) {
-        Object arg = varargs.getArray();
+    private static boolean checkVarargs(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) {
         ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass());
         assert type.isArray() : "varargs parameter must be an array type";
-        assert type.isInstance(Constant.forObject(arg)) : "value for " + name + " is not a " + MetaUtil.toJavaName(type) + " instance: " + arg;
+        assert type.getComponentType().isAssignableFrom(runtime.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + MetaUtil.toJavaName(type) + " instance: " +
+                        varargs.componentType;
         return true;
     }
 
@@ -453,7 +533,7 @@
      * {@link LocalNode} instance or a {@link LocalNode} array. For an eliminated parameter, the
      * value is identical to the key.
      */
-    private final Map<String, Object> parameters;
+    private final Object[] parameters;
 
     /**
      * The return node (if any) of the snippet.
@@ -481,33 +561,33 @@
      * 
      * @return the map that will be used to bind arguments to parameters when inlining this template
      */
-    private IdentityHashMap<Node, Node> bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, SnippetTemplate.Arguments args) {
+    private IdentityHashMap<Node, Node> bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, Arguments args) {
         IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
-        assert args.length() == parameters.size() : "number of args (" + args.length() + ") != number of parameters (" + parameters.size() + ")";
-        for (Map.Entry<String, Object> e : args) {
-            String name = e.getKey();
-            Object parameter = parameters.get(name);
-            assert parameter != null : this + " has no parameter named " + name;
-            Object argument = e.getValue();
+        assert args.info.getParameterCount() == parameters.length : "number of args (" + args.info.getParameterCount() + ") != number of parameters (" + parameters.length + ")";
+        for (int i = 0; i < parameters.length; i++) {
+            Object parameter = parameters[i];
+            assert parameter != null : this + " has no parameter named " + args.info.names[i];
+            Object argument = args.values[i];
             if (parameter instanceof LocalNode) {
                 if (argument instanceof ValueNode) {
                     replacements.put((LocalNode) parameter, (ValueNode) argument);
                 } else {
                     Kind kind = ((LocalNode) parameter).kind();
-                    assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + name;
+                    assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.names[i];
                     Constant constant = forBoxed(argument, kind);
                     replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph));
                 }
             } else if (parameter instanceof LocalNode[]) {
                 LocalNode[] locals = (LocalNode[]) parameter;
+                Varargs varargs = (Varargs) argument;
                 int length = locals.length;
                 List list = null;
                 Object array = null;
-                if (argument instanceof List) {
-                    list = (List) argument;
+                if (varargs.value instanceof List) {
+                    list = (List) varargs.value;
                     assert list.size() == length : length + " != " + list.size();
                 } else {
-                    array = argument;
+                    array = varargs.value;
                     assert array != null && array.getClass().isArray();
                     assert Array.getLength(array) == length : length + " != " + Array.getLength(array);
                 }
@@ -525,7 +605,7 @@
                     }
                 }
             } else {
-                assert parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + name + " -> " + parameter;
+                assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.names[i] + " -> " + parameter;
             }
         }
         return replacements;
@@ -592,7 +672,7 @@
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      * @return the map of duplicated nodes (original -> duplicate)
      */
-    public Map<Node, Node> instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) {
+    public Map<Node, Node> instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
         String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
@@ -668,7 +748,7 @@
      * @param replacer object that replaces the usages of {@code replacee}
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      */
-    public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) {
+    public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
         String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
@@ -727,12 +807,14 @@
     public String toString() {
         StringBuilder buf = new StringBuilder(snippet.toString()).append('(');
         String sep = "";
-        for (Map.Entry<String, Object> e : parameters.entrySet()) {
-            String name = e.getKey();
-            Object value = e.getValue();
+        for (int i = 0; i < parameters.length; i++) {
+            String name = "[" + i + "]";
+            Object value = parameters[i];
             buf.append(sep);
             sep = ", ";
-            if (value == UNUSED_PARAMETER) {
+            if (value == null) {
+                buf.append("<null> ").append(name);
+            } else if (value == UNUSED_PARAMETER) {
                 buf.append("<unused> ").append(name);
             } else if (value instanceof LocalNode) {
                 LocalNode local = (LocalNode) value;
@@ -746,42 +828,18 @@
         return buf.append(')').toString();
     }
 
-    private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) {
-        Set<String> expected = new HashSet<>();
-        for (int i = 0; i < parameterCount; i++) {
-            ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
-            VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method);
-            Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method);
-            if (c != null) {
-                assert vp == null && p == null;
-                String name = c.value();
-                expected.add(name);
+    private static boolean checkTemplate(MetaAccessProvider runtime, Arguments args, ResolvedJavaMethod method, Signature signature) {
+        for (int i = 0; i < args.info.getParameterCount(); i++) {
+            if (args.info.isConstantParameter(i)) {
                 Kind kind = signature.getParameterKind(i);
-                assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key;
-                assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind);
-            } else if (vp != null) {
-                assert p == null;
-                String name = vp.value();
-                expected.add(name);
-                assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key;
-                assert key.get(name) instanceof Varargs;
-                Varargs varargs = (Varargs) key.get(name);
-                assert checkVarargs(method, signature, i, name, varargs);
-            } else {
-                assert p != null : method + ": parameter " + i + " must be annotated with exactly one of " + "@" + ConstantParameter.class.getSimpleName() + " or " + "@" +
-                                VarargsParameter.class.getSimpleName() + " or " + "@" + Parameter.class.getSimpleName();
+                assert checkConstantArgument(runtime, method, signature, i, args.info.names[i], args.values[i], kind);
+
+            } else if (args.info.isVarargsParameter(i)) {
+                assert args.values[i] instanceof Varargs;
+                Varargs varargs = (Varargs) args.values[i];
+                assert checkVarargs(runtime, method, signature, i, args.info.names[i], varargs);
             }
         }
-        if (!key.names().containsAll(expected)) {
-            expected.removeAll(key.names());
-            assert false : expected + " missing from key " + key;
-        }
-        if (!expected.containsAll(key.names())) {
-            Set<String> namesCopy = new HashSet<>(key.names());
-            namesCopy.removeAll(expected);
-            assert false : "parameter(s) " + namesCopy + " should be annotated with @" + ConstantParameter.class.getSimpleName() + " or @" + VarargsParameter.class.getSimpleName() + " in " +
-                            MetaUtil.format("%H.%n(%p)", method);
-        }
         return true;
     }
 }
--- a/mx/commands.py	Fri Apr 12 10:53:37 2013 +0200
+++ b/mx/commands.py	Fri Apr 12 10:54:49 2013 +0200
@@ -777,7 +777,9 @@
     name = 'JUnitWrapper'
     javaSource = join(mxdir, name + '.java')
     javaClass = join(mxdir, name + '.class')
-    (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
+    testfile = os.environ.get('MX_TESTFILE', None)
+    if testfile is None:
+        (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
 
     def harness(projectscp, vmArgs):
         if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
@@ -791,7 +793,8 @@
     try:
         _run_tests(args, harness, annotations, testfile)
     finally:
-        os.remove(testfile)
+        if os.environ.get('MX_TESTFILE') is None:
+            os.remove(testfile)
 
 def unittest(args):
     """run the JUnit tests (all testcases)
--- a/mxtool/mx.py	Fri Apr 12 10:53:37 2013 +0200
+++ b/mxtool/mx.py	Fri Apr 12 10:54:49 2013 +0200
@@ -3018,9 +3018,10 @@
         if exists(tmpbase):
             shutil.rmtree(tmpbase)
 
-def findclass(args):
+def findclass(args, logToConsole=True):
     """find all classes matching a given substring"""
 
+    matches = []
     for entry, filename in classpath_walk(includeBootClasspath=True):
         if filename.endswith('.class'):
             if isinstance(entry, zipfile.ZipFile):
@@ -3030,20 +3031,19 @@
             classname = classname[:-len('.class')]
             for a in args:
                 if a in classname:
-                    log(classname)
+                    matches.append(classname)
+                    if logToConsole:
+                        log(classname)
+    return matches
 
 def javap(args):
-    """launch javap with a -classpath option denoting all available classes
-
-    Run the JDK javap class file disassembler with the following prepended options:
-
-        -private -verbose -classpath <path to project classes>"""
+    """disassemble classes matching given pattern with javap"""
 
     javap = java().javap
     if not exists(javap):
         abort('The javap executable does not exists: ' + javap)
     else:
-        run([javap, '-private', '-verbose', '-classpath', classpath()] + args)
+        run([javap, '-private', '-verbose', '-classpath', classpath()] + findclass(args, logToConsole=False))
 
 def show_projects(args):
     """show all loaded projects"""
@@ -3081,7 +3081,7 @@
     'ideinit': [ideinit, ''],
     'archive': [archive, '[options]'],
     'projectgraph': [projectgraph, ''],
-    'javap': [javap, ''],
+    'javap': [javap, '<class name patterns>'],
     'javadoc': [javadoc, '[options]'],
     'site': [site, '[options]'],
     'netbeansinit': [netbeansinit, ''],
--- a/src/cpu/sparc/vm/interpreter_sparc.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/cpu/sparc/vm/interpreter_sparc.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -381,6 +381,7 @@
     case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
     case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false);  break;
     case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);   break;
+    case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry();   break;
     case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();        break;
     case Interpreter::accessor               : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry();     break;
     case Interpreter::abstract               : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry();     break;
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -1917,6 +1917,7 @@
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
                                                 BasicType ret_type) {
+  assert (method->intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "not yet ported");
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
     intptr_t start = (intptr_t)__ pc();
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -36,6 +36,7 @@
 
   address generate_normal_entry(bool synchronized);
   address generate_native_entry(bool synchronized);
+  address generate_execute_compiled_method_entry();
   address generate_abstract_entry(void);
   address generate_math_entry(AbstractInterpreter::MethodKind kind);
   address generate_empty_entry(void);
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -1670,6 +1670,11 @@
   verify_oop_args(masm, method, sig_bt, regs);
   vmIntrinsics::ID iid = method->intrinsic_id();
 
+  if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+    return;
+  }
+
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
   Register receiver_reg   = noreg;
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -873,6 +873,31 @@
   return generate_accessor_entry();
 }
 
+// Interpreter stub for calling a compiled method with 3 object arguments
+address InterpreterGenerator::generate_execute_compiled_method_entry() {
+  address entry_point = __ pc();
+
+  // Pick up the return address
+  __ movptr(rax, Address(rsp, 0));
+
+  // Must preserve original SP for loading incoming arguments because
+  // we need to align the outgoing SP for compiled code.
+  __ movptr(r11, rsp);
+
+  // Ensure compiled code always sees stack at proper alignment
+  __ andptr(rsp, -16);
+
+  // push the return address and misalign the stack that youngest frame always sees
+  // as far as the placement of the call instruction
+  __ push(rax);
+
+  __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5));
+  __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4));
+  __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3));
+  __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize));
+  __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+  return entry_point;
+}
 
 // Interpreter stub for calling a native method. (asm interpreter)
 // This sets up a somewhat different looking stack for calling the
@@ -1561,6 +1586,7 @@
   switch (kind) {
   case Interpreter::zerolocals             :                                                                             break;
   case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
+  case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break;
   case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break;
   case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);  break;
   case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();       break;
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -199,6 +199,7 @@
   /* graal.api.code */                                                                                               \
   do_klass(Assumptions_klass,                     com_oracle_graal_api_code_Assumptions,                        Opt) \
   do_klass(Assumptions_ConcreteMethod_klass,      com_oracle_graal_api_code_Assumptions_ConcreteMethod,         Opt) \
+  do_klass(Assumptions_NoFinalizableSubclass_klass, com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, Opt) \
   do_klass(Assumptions_ConcreteSubtype_klass,     com_oracle_graal_api_code_Assumptions_ConcreteSubtype,        Opt) \
   do_klass(Assumptions_MethodContents_klass,      com_oracle_graal_api_code_Assumptions_MethodContents,         Opt) \
   do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,    Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -299,6 +299,7 @@
   template(com_oracle_graal_hotspot_HotSpotCompilationResult,        "com/oracle/graal/hotspot/HotSpotCompilationResult")             \
   template(com_oracle_graal_hotspot_HotSpotRuntimeCallTarget,        "com/oracle/graal/hotspot/HotSpotRuntimeCallTarget")             \
   template(com_oracle_graal_hotspot_bridge_VMToCompiler,             "com/oracle/graal/hotspot/bridge/VMToCompiler")                  \
+  template(com_oracle_graal_hotspot_bridge_CompilerToVMImpl,         "com/oracle/graal/hotspot/bridge/CompilerToVMImpl")              \
   template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo,            "com/oracle/graal/hotspot/meta/HotSpotCodeInfo")                 \
   template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode,       "com/oracle/graal/hotspot/meta/HotSpotInstalledCode")            \
   template(com_oracle_graal_hotspot_meta_HotSpotJavaType,            "com/oracle/graal/hotspot/meta/HotSpotJavaType")                 \
@@ -322,6 +323,7 @@
   template(com_oracle_graal_api_code_Assumptions,                    "com/oracle/graal/api/code/Assumptions")                         \
   template(com_oracle_graal_api_code_Assumptions_MethodContents,     "com/oracle/graal/api/code/Assumptions$MethodContents")          \
   template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype,    "com/oracle/graal/api/code/Assumptions$ConcreteSubtype")         \
+  template(com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/code/Assumptions$NoFinalizableSubclass") \
   template(com_oracle_graal_api_code_Assumptions_ConcreteMethod,     "com/oracle/graal/api/code/Assumptions$ConcreteMethod")          \
   template(com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,"com/oracle/graal/api/code/Assumptions$CallSiteTargetValue")     \
   template(com_oracle_graal_api_code_CompilationResult,              "com/oracle/graal/api/code/CompilationResult")                   \
@@ -339,6 +341,7 @@
   template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue")                       \
   template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot")                           \
   template(com_oracle_graal_api_code_VirtualObject,                  "com/oracle/graal/api/code/VirtualObject")                       \
+  template(com_oracle_graal_api_code_InvalidInstalledCodeException,  "com/oracle/graal/api/code/InvalidInstalledCodeException")       \
   template(startCompiler_name,                    "startCompiler")                                                                    \
   template(bootstrap_name,                        "bootstrap")                                                                        \
   template(shutdownCompiler_name,                 "shutdownCompiler")                                                                 \
@@ -379,7 +382,6 @@
   template(forObject_name,                        "forObject")                                                                        \
   template(callbackInternal_name,                 "callbackInternal")                                                                 \
   template(callback_signature,                    "(Ljava/lang/Object;)Ljava/lang/Object;")                                           \
-  template(MethodInvalidatedException,            "com/oracle/graal/api/code/InstalledCode$MethodInvalidatedException")               \
   /* graal.api.interpreter */                                                                                                         \
   template(com_oracle_graal_api_interpreter_Interpreter,             "com/oracle/graal/api/interpreter/Interpreter")                  \
   template(interpreter_execute_name,              "execute")                                                                          \
@@ -1128,6 +1130,9 @@
   do_intrinsic(_Double_valueOf,           java_lang_Double,       valueOf_name, Double_valueOf_signature, F_S)          \
    do_name(     Double_valueOf_signature,                        "(D)Ljava/lang/Double;")                               \
                                                                                                                         \
+  do_intrinsic(_CompilerToVMImpl_executeCompiledMethod,           com_oracle_graal_hotspot_bridge_CompilerToVMImpl, executeCompiledMethod_name, CompilerToVMImpl_executeCompiledMethod_signature, F_SN)\
+   do_name(     CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;J)Ljava/lang/Object;")                               \
+   do_name(     executeCompiledMethod_name,                       "executeCompiledMethodIntrinsic")                     \
     /*end*/
 
 
--- a/src/share/vm/code/dependencies.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/code/dependencies.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -144,6 +144,11 @@
   assert_common_1(evol_method, DepValue(_oop_recorder, m));
 }
 
+void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) {
+  check_ctxk(ctxk);
+  assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk));
+}
+
 void Dependencies::assert_leaf_type(Klass* ctxk) {
   if (ctxk->oop_is_array()) {
     // As a special case, support this assertion on an array type,
--- a/src/share/vm/code/dependencies.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/code/dependencies.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -360,6 +360,7 @@
 
  public:
   void assert_evol_method(Method* m);
+  void assert_has_no_finalizable_subclasses(Klass* ctxk);
   void assert_leaf_type(Klass* ctxk);
   void assert_unique_concrete_method(Klass* ctxk, Method* uniqm);
   void assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck);
--- a/src/share/vm/code/nmethod.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/code/nmethod.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -1308,7 +1308,6 @@
 
 #ifdef GRAAL
     if (_graal_installed_code != NULL) {
-      HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0);
       _graal_installed_code = NULL;
     }
 #endif
@@ -1394,18 +1393,17 @@
       return false;
     }
 
-#ifdef GRAAL
-    if (_graal_installed_code != NULL) {
-      HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0);
-      _graal_installed_code = NULL;
-    }
-#endif
-
     // The caller can be calling the method statically or through an inline
     // cache call.
     if (!is_osr_method() && !is_not_entrant()) {
-      NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
-                  SharedRuntime::get_handle_wrong_method_stub());
+      if (_graal_installed_code != NULL && !HotSpotInstalledCode::isDefault(_graal_installed_code)) {
+        // This was manually installed machine code. Patch entry with stub that throws an exception.
+        NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
+                    SharedRuntime::get_deoptimized_installed_code_stub());
+      } else {
+        NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
+                    SharedRuntime::get_handle_wrong_method_stub());
+      }
     }
 
     if (is_in_use()) {
--- a/src/share/vm/compiler/compileBroker.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -1225,7 +1225,7 @@
   assert(method->method_holder()->oop_is_instance(), "not an instance method");
   assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
   assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods");
-  assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
+  assert(!method->method_holder()->is_not_initialized() || method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "method holder must be initialized");
 
   if (!TieredCompilation) {
     comp_level = CompLevel_highest_tier;
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -294,6 +294,8 @@
       if (!assumption.is_null()) {
         if (assumption->klass() == Assumptions_MethodContents::klass()) {
           assumption_MethodContents(assumption);
+        } else if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) {
+          assumption_NoFinalizableSubclass(assumption);
         } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) {
           assumption_ConcreteSubtype(assumption);
         } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) {
@@ -447,6 +449,12 @@
   _dependencies->assert_evol_method(method());
 }
 
+void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) {
+  Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption());
+  Klass* receiverType = asKlass(HotSpotResolvedObjectType::metaspaceKlass(receiverType_handle));
+  _dependencies->assert_has_no_finalizable_subclasses(receiverType);
+}
+
 void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) {
   Handle context_handle = Assumptions_ConcreteSubtype::context(assumption());
   Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption());
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -93,6 +93,7 @@
   void initialize_buffer(CodeBuffer& buffer);
 
   void assumption_MethodContents(Handle assumption);
+  void assumption_NoFinalizableSubclass(Handle assumption);
   void assumption_ConcreteSubtype(Handle assumption);
   void assumption_ConcreteMethod(Handle assumption);
   void assumption_CallSiteTargetValue(Handle assumption);
--- a/src/share/vm/graal/graalCompiler.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -98,6 +98,21 @@
     return ((index & 0xFF) << 24) | ((index & 0xFF00) << 8) | ((index & 0xFF0000) >> 8) | ((index & 0xFF000000) >> 24);
   }
 
+  static int to_cp_index(int raw_index, Bytecodes::Code bc) {
+    int cp_index;
+    if (bc == Bytecodes::_invokedynamic) {
+      cp_index = to_index_u4(raw_index);
+      assert(ConstantPool::is_invokedynamic_index(raw_index), "not an invokedynamic constant pool index");
+    } else {
+      assert(bc == Bytecodes::_getfield        || bc == Bytecodes::_putfield  ||
+             bc == Bytecodes::_getstatic       || bc == Bytecodes::_putstatic ||
+             bc == Bytecodes::_invokeinterface || bc == Bytecodes::_invokevirtual ||
+             bc == Bytecodes::_invokespecial   || bc == Bytecodes::_invokestatic, err_msg("unexpected invoke opcode: %d %s", bc, Bytecodes::name(bc)));
+      cp_index = to_cp_index_u2(raw_index);
+    }
+    return cp_index;
+  }
+
   static void initialize_buffer_blob();
 };
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -416,10 +416,11 @@
   return JNIHandles::make_local(THREAD, result);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index))
-  assert(GraalCompiler::to_index_u4(index) < 0, "not an invokedynamic constant pool index");
+C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode))
+  Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
+  index = GraalCompiler::to_cp_index(index, bc);
   constantPoolHandle cpool(InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants());
-  oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, GraalCompiler::to_index_u4(index));
+  oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, index);
 
   return JNIHandles::make_local(THREAD, appendix_oop);
 C2V_END
@@ -429,7 +430,7 @@
   instanceKlassHandle pool_holder(cp->pool_holder());
 
   Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
-  index = (bc == Bytecodes::_invokedynamic) ? GraalCompiler::to_index_u4(index) : GraalCompiler::to_cp_index_u2(index);
+  index = GraalCompiler::to_cp_index(index, bc);
 
   methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder);
   if (!method.is_null()) {
@@ -459,11 +460,11 @@
 
 C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op))
   ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants();
-  int opcode = (op & 0xFF);
-  if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray
-      && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w)
+  Bytecodes::Code bc = (Bytecodes::Code) (((int) op) & 0xFF);
+  if (bc != Bytecodes::_checkcast && bc != Bytecodes::_instanceof && bc != Bytecodes::_new && bc != Bytecodes::_anewarray
+      && bc != Bytecodes::_multianewarray && bc != Bytecodes::_ldc && bc != Bytecodes::_ldc_w && bc != Bytecodes::_ldc2_w)
   {
-    index = cp->remap_instruction_operand_from_cache((opcode == Bytecodes::_invokedynamic) ? GraalCompiler::to_index_u4(index) : GraalCompiler::to_cp_index_u2(index));
+    index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index(index, bc));
   }
   constantTag tag = cp->tag_at(index);
   if (tag.is_field_or_method()) {
@@ -656,6 +657,7 @@
   set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset()));
   set_int("extraStackEntries", Method::extra_stack_entries());
   set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset()));
+  set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes());
   set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER);
   set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset()));
   set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
@@ -779,6 +781,13 @@
   set_int("deoptActionReinterpret", Deoptimization::Action_reinterpret);
   set_int("deoptActionMakeNotEntrant", Deoptimization::Action_make_not_entrant);
   set_int("deoptActionMakeNotCompilable", Deoptimization::Action_make_not_compilable);
+
+  set_int("vmIntrinsicInvokeBasic", vmIntrinsics::_invokeBasic);
+  set_int("vmIntrinsicLinkToVirtual", vmIntrinsics::_linkToVirtual);
+  set_int("vmIntrinsicLinkToStatic", vmIntrinsics::_linkToStatic);
+  set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial);
+  set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface);
+
   set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()));
   set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()));
   set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes);
@@ -898,23 +907,17 @@
   return JNIHandles::make_local(element);
 C2V_END
 
-C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject args))
+C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nativeMethod))
   ResourceMark rm;
   HandleMark hm;
 
-  assert(metaspace_method != 0, "just checking");
-  methodHandle mh = asMethod(metaspace_method);
+  nmethod* nm = (nmethod*) (address) nativeMethod;
+  methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
   JavaCallArguments jca(mh->size_of_parameters());
 
   JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
   JavaValue result(jap.get_ret_type());
-
-  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
-  if (nm == NULL || !nm->is_alive()) {
-    THROW_0(vmSymbols::MethodInvalidatedException());
-  }
-
   jca.set_alternative_target(nm);
   JavaCalls::call(&result, mh, &jca, CHECK_NULL);
 
@@ -928,29 +931,6 @@
   }
 C2V_END
 
-C2V_VMENTRY(jobject, executeCompiledMethod, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject arg1, jobject arg2, jobject arg3))
-  ResourceMark rm;
-  HandleMark hm;
-
-  methodHandle method = asMethod(metaspace_method);
-  assert(!method.is_null(), "just checking");
-  JavaValue result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_oop(JNIHandles::resolve(arg1));
-  args.push_oop(JNIHandles::resolve(arg2));
-  args.push_oop(JNIHandles::resolve(arg3));
-
-  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
-  if (nm == NULL || !nm->is_alive()) {
-    THROW_0(vmSymbols::MethodInvalidatedException());
-  }
-
-  args.set_alternative_target(nm);
-  JavaCalls::call(&result, method, &args, CHECK_NULL);
-
-  return JNIHandles::make_local((oop) result.get_jobject());
-C2V_END
-
 C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method))
 
   Method* method = asMethod(metaspace_method);
@@ -1021,10 +1001,10 @@
     u2 typeCPIdx = table[i].descriptor_cp_index;
     u2 slot = table[i].slot;
 
-    char* name = method->constants()->string_at_noresolve(nameCPIdx);
+    char* name = method->constants()->symbol_at(nameCPIdx)->as_C_string();
     Handle nameHandle = java_lang_String::create_from_str(name, CHECK_NULL);
 
-    char* typeInfo = method->constants()->string_at_noresolve(typeCPIdx);
+    char* typeInfo = method->constants()->symbol_at(typeCPIdx)->as_C_string();
     Handle typeHandle = java_lang_String::create_from_str(typeInfo, CHECK_NULL);
 
     Handle holderHandle = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0);
@@ -1069,6 +1049,20 @@
 C2V_END
 
 
+C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jlong nativeMethod))
+  nmethod* m = (nmethod*)nativeMethod;
+  if (!m->is_not_entrant()) {
+    m->mark_for_deoptimization();
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+C2V_END
+
+
+C2V_VMENTRY(jboolean, isInstalledCodeValid, (JNIEnv *env, jobject, jlong nativeMethod))
+  nmethod* m = (nmethod*)nativeMethod;
+  return m->is_alive() && !m->is_not_entrant();
+C2V_END
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@@ -1120,7 +1114,7 @@
   {CC"getVtableEntryOffset",          CC"("METASPACE_METHOD")I",                                        FN_PTR(getVtableEntryOffset)},
   {CC"lookupType",                    CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE,                             FN_PTR(lookupType)},
   {CC"lookupConstantInPool",          CC"("HS_RESOLVED_TYPE"I)"OBJECT,                                  FN_PTR(lookupConstantInPool)},
-  {CC"lookupAppendixInPool",          CC"("HS_RESOLVED_TYPE"I)"OBJECT,                                  FN_PTR(lookupAppendixInPool)},
+  {CC"lookupAppendixInPool",          CC"("HS_RESOLVED_TYPE"IB)"OBJECT,                                 FN_PTR(lookupAppendixInPool)},
   {CC"lookupMethodInPool",            CC"("HS_RESOLVED_TYPE"IB)"METHOD,                                 FN_PTR(lookupMethodInPool)},
   {CC"lookupTypeInPool",              CC"("HS_RESOLVED_TYPE"I)"TYPE,                                    FN_PTR(lookupTypeInPool)},
   {CC"lookupReferencedTypeInPool",    CC"("HS_RESOLVED_TYPE"IB)V",                                      FN_PTR(lookupReferencedTypeInPool)},
@@ -1138,14 +1132,15 @@
   {CC"installCode0",                  CC"("HS_COMP_RESULT HS_INSTALLED_CODE"[Z)I",                      FN_PTR(installCode0)},
   {CC"getCode",                       CC"(J)[B",                                                        FN_PTR(getCode)},
   {CC"disassembleNMethod",            CC"(J)"STRING,                                                    FN_PTR(disassembleNMethod)},
-  {CC"executeCompiledMethod",         CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT,      FN_PTR(executeCompiledMethod)},
-  {CC"executeCompiledMethodVarargs",  CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT,                 FN_PTR(executeCompiledMethodVarargs)},
+  {CC"executeCompiledMethodVarargs",  CC"(["OBJECT NMETHOD")"OBJECT,                                    FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
   {CC"getLineNumberTable",            CC"("HS_RESOLVED_METHOD")[J",                                     FN_PTR(getLineNumberTable)},
   {CC"getLocalVariableTable",         CC"("HS_RESOLVED_METHOD")["LOCAL,                                 FN_PTR(getLocalVariableTable)},
   {CC"getFileName",                   CC"("HS_RESOLVED_JAVA_TYPE")"STRING,                              FN_PTR(getFileName)},
   {CC"clearQueuedForCompilation",     CC"("HS_RESOLVED_METHOD")V",                                      FN_PTR(clearQueuedForCompilation)},
   {CC"reprofile",                     CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
+  {CC"invalidateInstalledCode",       CC"(J)V",                                                         FN_PTR(invalidateInstalledCode)},
+  {CC"isInstalledCodeValid",          CC"(J)Z",                                                         FN_PTR(isInstalledCodeValid)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalEnv.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/graal/graalEnv.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -340,6 +340,27 @@
   Symbol* name_sym = cpool->name_ref_at(index);
   Symbol* sig_sym  = cpool->signature_ref_at(index);
 
+  if (cpool->has_preresolution()
+      || (holder() == SystemDictionary::MethodHandle_klass() &&
+          MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) {
+    // Short-circuit lookups for JSR 292-related call sites.
+    // That is, do not rely only on name-based lookups, because they may fail
+    // if the names are not resolvable in the boot class loader (7056328).
+    switch (bc) {
+    case Bytecodes::_invokevirtual:
+    case Bytecodes::_invokeinterface:
+    case Bytecodes::_invokespecial:
+    case Bytecodes::_invokestatic:
+      {
+        Method* m = ConstantPool::method_at_if_loaded(cpool, index);
+        if (m != NULL) {
+          return m;
+        }
+      }
+      break;
+    }
+  }
+
   if (holder_is_accessible) { // Our declared holder is loaded.
     instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder);
     methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc);
--- a/src/share/vm/graal/graalJavaAccess.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -110,6 +110,9 @@
   start_class(Assumptions_MethodContents)                                                                                                                      \
     oop_field(Assumptions_MethodContents, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")                                                            \
   end_class                                                                                                                                                    \
+  start_class(Assumptions_NoFinalizableSubclass)                                                                                                               \
+    oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                 \
+  end_class                                                                                                                                                    \
   start_class(Assumptions_ConcreteSubtype)                                                                                                                     \
     oop_field(Assumptions_ConcreteSubtype, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                            \
     oop_field(Assumptions_ConcreteSubtype, subtype, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                            \
--- a/src/share/vm/interpreter/abstractInterpreter.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -85,6 +85,7 @@
     zerolocals_synchronized,                                    // method needs locals initialization & is synchronized
     native,                                                     // native method
     native_synchronized,                                        // native method & is synchronized
+    execute_compiled_method,                                    // direct call to compiled method address
     empty,                                                      // empty method (code: _return)
     accessor,                                                   // accessor method (code: _aload_0, _getfield, _(a|i)return)
     abstract,                                                   // abstract method (throws an AbstractMethodException)
--- a/src/share/vm/interpreter/interpreter.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/interpreter/interpreter.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -188,6 +188,9 @@
   // Method handle primitive?
   if (m->is_method_handle_intrinsic()) {
     vmIntrinsics::ID id = m->intrinsic_id();
+    if (id == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+      return AbstractInterpreter::execute_compiled_method;
+    }
     assert(MethodHandles::is_signature_polymorphic(id), "must match an intrinsic");
     MethodKind kind = (MethodKind)( method_handle_invoke_FIRST +
                                     ((int)id - vmIntrinsics::FIRST_MH_SIG_POLY) );
@@ -287,6 +290,7 @@
     case zerolocals_synchronized: tty->print("zerolocals_synchronized"); break;
     case native                 : tty->print("native"                 ); break;
     case native_synchronized    : tty->print("native_synchronized"    ); break;
+    case execute_compiled_method: tty->print("execute_compiled_method"); break;
     case empty                  : tty->print("empty"                  ); break;
     case accessor               : tty->print("accessor"               ); break;
     case abstract               : tty->print("abstract"               ); break;
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -360,6 +360,7 @@
   method_entry(zerolocals)
   method_entry(zerolocals_synchronized)
   method_entry(empty)
+  method_entry(execute_compiled_method)
   method_entry(accessor)
   method_entry(abstract)
   method_entry(java_lang_math_sin  )
--- a/src/share/vm/oops/method.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/oops/method.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -722,7 +722,7 @@
   if (number_of_breakpoints() > 0)
     return true;
   if (is_method_handle_intrinsic())
-    return !is_synthetic();  // the generated adapters must be compiled
+    return !is_synthetic() && intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod;  // the generated adapters must be compiled
   if (comp_level == CompLevel_any)
     return is_not_c1_compilable() || is_not_c2_compilable();
   if (is_c1_compile(comp_level))
@@ -850,7 +850,10 @@
   (void) make_adapters(h_method, CHECK);
 
   // ONLY USE the h_method now as make_adapter may have blocked
-
+  if (h_method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    CompileBroker::compile_method(h_method, InvocationEntryBci, CompLevel_highest_tier,
+                                  methodHandle(), CompileThreshold, "executeCompiledMethod", CHECK);
+  }
 }
 
 address Method::make_adapters(methodHandle mh, TRAPS) {
@@ -1014,8 +1017,8 @@
 // Test if this method is an internal MH primitive method.
 bool Method::is_method_handle_intrinsic() const {
   vmIntrinsics::ID iid = intrinsic_id();
-  return (MethodHandles::is_signature_polymorphic(iid) &&
-          MethodHandles::is_signature_polymorphic_intrinsic(iid));
+  return ((MethodHandles::is_signature_polymorphic(iid) &&
+          MethodHandles::is_signature_polymorphic_intrinsic(iid))) || iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod;
 }
 
 bool Method::has_member_arg() const {
--- a/src/share/vm/runtime/javaCalls.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -412,7 +412,7 @@
       ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point());
       entry_point = method->adapter()->get_i2c_entry();
     } else {
-      THROW(vmSymbols::MethodInvalidatedException());
+      THROW(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException());
     }
   }
 #endif
--- a/src/share/vm/runtime/sharedRuntime.cpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Fri Apr 12 10:54:49 2013 +0200
@@ -83,6 +83,7 @@
 #endif
 
 // Shared stub locations
+RuntimeStub*        SharedRuntime::_deoptimized_installed_code_blob;
 RuntimeStub*        SharedRuntime::_wrong_method_blob;
 RuntimeStub*        SharedRuntime::_ic_miss_blob;
 RuntimeStub*        SharedRuntime::_resolve_opt_virtual_call_blob;
@@ -101,6 +102,7 @@
 
 //----------------------------generate_stubs-----------------------------------
 void SharedRuntime::generate_stubs() {
+  _deoptimized_installed_code_blob     = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_deoptimized_installed_code), "deoptimized_installed_code");
   _wrong_method_blob                   = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method),         "wrong_method_stub");
   _ic_miss_blob                        = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub");
   _resolve_opt_virtual_call_blob       = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C),  "resolve_opt_virtual_call");
@@ -1350,6 +1352,12 @@
   return callee_method->verified_code_entry();
 JRT_END
 
+// Installed code has been deoptimized
+JRT_BLOCK_ENTRY(address, SharedRuntime::handle_deoptimized_installed_code(JavaThread* thread))
+  JavaThread* THREAD = thread;
+  ThreadInVMfromJava tiv(THREAD);
+  THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
+JRT_END
 
 // Handle call site that has been made non-entrant
 JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* thread))
--- a/src/share/vm/runtime/sharedRuntime.hpp	Fri Apr 12 10:53:37 2013 +0200
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Fri Apr 12 10:54:49 2013 +0200
@@ -55,6 +55,7 @@
 
   // Shared stub locations
 
+  static RuntimeStub*        _deoptimized_installed_code_blob;
   static RuntimeStub*        _wrong_method_blob;
   static RuntimeStub*        _ic_miss_blob;
   static RuntimeStub*        _resolve_opt_virtual_call_blob;
@@ -209,6 +210,11 @@
     return _wrong_method_blob->entry_point();
   }
 
+  static address get_deoptimized_installed_code_stub() {
+    assert(_deoptimized_installed_code_blob!= NULL, "oops");
+    return _deoptimized_installed_code_blob->entry_point();
+  }
+
 #ifdef COMPILER2
   static void generate_uncommon_trap_blob(void);
   static UncommonTrapBlob* uncommon_trap_blob()                  { return _uncommon_trap_blob; }
@@ -486,6 +492,9 @@
   static address handle_wrong_method(JavaThread* thread);
   static address handle_wrong_method_ic_miss(JavaThread* thread);
 
+  // handle deoptimized installed code
+  static address handle_deoptimized_installed_code(JavaThread* thread);
+
 #ifndef PRODUCT
 
   // Collect and print inline cache miss statistics