changeset 19998:7072d9d4aa13

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 23 Mar 2015 00:26:47 +0100
parents 58f2aad37d0e (current diff) aaf5039e56d7 (diff)
children 43661c648060 d22307a9a025
files
diffstat 23 files changed, 575 insertions(+), 555 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Mon Mar 23 00:26:47 2015 +0100
@@ -335,8 +335,12 @@
 
     @Override
     @SuppressWarnings("unchecked")
-    public <A> A[] toArray(A[] template) {
-        return (A[]) Arrays.copyOf(nodes, size, template.getClass());
+    public <A> A[] toArray(A[] a) {
+        if (a.length >= size) {
+            System.arraycopy(nodes, 0, a, 0, size);
+            return a;
+        }
+        return (A[]) Arrays.copyOf(nodes, size, a.getClass());
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Mon Mar 23 00:26:47 2015 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.test;
 
-import static com.oracle.graal.nodes.spi.Replacements.*;
-
 import java.io.*;
 import java.lang.reflect.*;
 import java.security.*;
@@ -34,10 +32,16 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext;
+import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Tests the intrinsification of certain crypto methods.
@@ -58,44 +62,51 @@
         return installedCode;
     }
 
-    @Test
-    public void testEncryptSubstitution() throws Exception {
-        Assume.assumeTrue(SELF_RECURSIVE_INTRINSICS_ENABLED);
+    SecretKey aesKey;
+    SecretKey desKey;
+    byte[] input;
+    ByteArrayOutputStream aesExpected = new ByteArrayOutputStream();
+    ByteArrayOutputStream desExpected = new ByteArrayOutputStream();
 
+    public HotSpotCryptoSubstitutionTest() throws Exception {
         byte[] seed = {0x4, 0x7, 0x1, 0x1};
         SecureRandom random = new SecureRandom(seed);
         KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES");
         KeyGenerator desKeyGen = KeyGenerator.getInstance("DESede");
         aesKeyGen.init(128, random);
         desKeyGen.init(168, random);
-        SecretKey aesKey = aesKeyGen.generateKey();
-        SecretKey desKey = desKeyGen.generateKey();
-        byte[] input = readClassfile16(getClass());
+        aesKey = aesKeyGen.generateKey();
+        desKey = desKeyGen.generateKey();
+        input = readClassfile16(getClass());
+
+        aesExpected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding"));
+        aesExpected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding"));
 
-        ByteArrayOutputStream aesExpected = new ByteArrayOutputStream();
-        aesExpected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
-        aesExpected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+        desExpected.write(runEncryptDecrypt(desKey, "DESede/CBC/NoPadding"));
+        desExpected.write(runEncryptDecrypt(desKey, "DESede/CBC/PKCS5Padding"));
+    }
 
+    @Test
+    public void testAESCryptIntrinsics() throws Exception {
         if (compileAndInstall("com.sun.crypto.provider.AESCrypt", "encryptBlock", "decryptBlock")) {
             ByteArrayOutputStream actual = new ByteArrayOutputStream();
-            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
-            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding"));
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding"));
             Assert.assertArrayEquals(aesExpected.toByteArray(), actual.toByteArray());
         }
+    }
 
-        ByteArrayOutputStream desExpected = new ByteArrayOutputStream();
-        desExpected.write(runEncryptDecrypt(desKey, "DESede/CBC/NoPadding", input));
-        desExpected.write(runEncryptDecrypt(desKey, "DESede/CBC/PKCS5Padding", input));
-
+    @Test
+    public void testCipherBlockChainingIntrinsics() throws Exception {
         if (compileAndInstall("com.sun.crypto.provider.CipherBlockChaining", "encrypt", "decrypt")) {
             ByteArrayOutputStream actual = new ByteArrayOutputStream();
-            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
-            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding"));
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding"));
             Assert.assertArrayEquals(aesExpected.toByteArray(), actual.toByteArray());
 
             actual.reset();
-            actual.write(runEncryptDecrypt(desKey, "DESede/CBC/NoPadding", input));
-            actual.write(runEncryptDecrypt(desKey, "DESede/CBC/PKCS5Padding", input));
+            actual.write(runEncryptDecrypt(desKey, "DESede/CBC/NoPadding"));
+            actual.write(runEncryptDecrypt(desKey, "DESede/CBC/PKCS5Padding"));
             Assert.assertArrayEquals(desExpected.toByteArray(), actual.toByteArray());
         }
     }
@@ -114,9 +125,13 @@
             Method method = lookup(className, methodName);
             if (method != null) {
                 ResolvedJavaMethod installedCodeOwner = getMetaAccess().lookupJavaMethod(method);
-                StructuredGraph subst = getReplacements().getMethodSubstitution(installedCodeOwner);
-                if (subst != null) {
-                    StructuredGraph graph = subst.copy();
+                ResolvedJavaMethod substMethod = getReplacements().getMethodSubstitutionMethod(installedCodeOwner);
+                if (substMethod != null) {
+                    StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES);
+                    Plugins plugins = new Plugins(((HotSpotProviders) getProviders()).getGraphBuilderPlugins());
+                    GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
+                    IntrinsicContext initialReplacementContext = new IntrinsicContext(installedCodeOwner, substMethod, null, -2);
+                    new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getConstantReflection(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph);
                     Assert.assertNotNull(getCode(installedCodeOwner, graph, true));
                     atLeastOneCompiled = true;
                 } else {
@@ -191,7 +206,7 @@
         return classFile;
     }
 
-    public byte[] runEncryptDecrypt(SecretKey key, String algorithm, byte[] input) throws Exception {
+    public byte[] runEncryptDecrypt(SecretKey key, String algorithm) throws Exception {
         byte[] indata = input.clone();
         byte[] cipher = encrypt(indata, key, algorithm);
         byte[] plain = decrypt(cipher, key, algorithm);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Mon Mar 23 00:26:47 2015 +0100
@@ -33,17 +33,14 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing;
-import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 
 /**
  * HotSpot implementation of {@link ConstantReflectionProvider}.
  */
-@SuppressWarnings("unused")
 public class HotSpotConstantReflectionProvider implements ConstantReflectionProvider, HotSpotProxified {
     private static final String SystemClassName = "Ljava/lang/System;";
 
@@ -317,7 +314,7 @@
         ResolvedJavaMethod initMethod = null;
         try {
             Class<?> rjm = ResolvedJavaMethod.class;
-            makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, Object[].class, rjm, SnippetInliningPolicy.class, FrameStateProcessing.class));
+            makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, Object[].class, rjm, FrameStateProcessing.class));
             initMethod = metaAccess.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class));
         } catch (NoSuchMethodException | SecurityException e) {
             throw new GraalInternalError(e);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java	Mon Mar 23 00:26:47 2015 +0100
@@ -27,6 +27,7 @@
 import static java.lang.String.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.graphbuilderconf.*;
 import com.oracle.graal.graphbuilderconf.GraphBuilderContext.Replacement;
@@ -44,6 +45,8 @@
         this.replacements = replacements;
     }
 
+    private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough
+
     public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) {
         ResolvedJavaMethod subst = replacements.getMethodSubstitutionMethod(method);
         if (subst != null) {
@@ -56,6 +59,13 @@
             assert nodeIntrinsification.getIntrinsic(method) == null && method.getAnnotation(Word.Operation.class) == null && method.getAnnotation(HotSpotOperation.class) == null &&
                             !nodeIntrinsification.isFoldable(method) : format("%s should have been handled by %s", method.format("%H.%n(%p)"), DefaultGenericInvocationPlugin.class.getName());
 
+            assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded";
+
+            if (method.getName().startsWith("$jacoco")) {
+                throw new GraalInternalError("Found call to JaCoCo instrumentation method " + method.format("%H.%n(%p)") + ". Placing \"//JaCoCo Exclude\" anywhere in " +
+                                b.getMethod().getDeclaringClass().getSourceFileName() + " should fix this.");
+            }
+
             // Force inlining when parsing replacements
             return new InlineInfo(method, true, true);
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Mon Mar 23 00:26:47 2015 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.nodes.spi.Replacements.*;
-
 import java.lang.reflect.*;
 import java.util.zip.*;
 
@@ -64,9 +62,7 @@
         replacements.registerSubstitutions(CRC32.class, CRC32Substitutions.class);
         replacements.registerSubstitutions(Reflection.class, ReflectionSubstitutions.class);
         replacements.registerSubstitutions(CompilerToVMImpl.class, CompilerToVMImplSubstitutions.class);
-        if (SELF_RECURSIVE_INTRINSICS_ENABLED) {
-            replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.AESCrypt"), AESCryptSubstitutions.class);
-            replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.CipherBlockChaining"), CipherBlockChainingSubstitutions.class);
-        }
+        replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.AESCrypt"), AESCryptSubstitutions.class);
+        replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.CipherBlockChaining"), CipherBlockChainingSubstitutions.class);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Mon Mar 23 00:26:47 2015 +0100
@@ -192,7 +192,7 @@
         StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO);
         graph.disableInlinedMethodRecording();
 
-        GraphKit kit = new GraphKit(graph, providers, wordTypes);
+        GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins());
         ParameterNode[] params = createParameters(kit, args);
 
         ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java	Mon Mar 23 00:26:47 2015 +0100
@@ -29,9 +29,10 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graphbuilderconf.*;
-import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.java.AbstractBytecodeParser.ReplacementContext;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
@@ -94,7 +95,8 @@
 
         assert SnippetGraphUnderConstruction.get() == null;
         SnippetGraphUnderConstruction.set(graph);
-        new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, method).apply(graph);
+        ReplacementContext initialReplacementContext = new ReplacementContext(method, method);
+        new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph);
         SnippetGraphUnderConstruction.set(null);
 
         graph.setGuardsStage(GuardsStage.FLOATING_GUARDS);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Mar 23 00:26:47 2015 +0100
@@ -27,6 +27,7 @@
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
+import static com.oracle.graal.java.HIRFrameStateBuilder.*;
 
 import java.util.*;
 
@@ -42,6 +43,7 @@
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
@@ -82,7 +84,7 @@
      * happen when a call to a {@link MethodSubstitution} is encountered or the root of compilation
      * is a {@link MethodSubstitution} or a snippet.
      */
-    static class ReplacementContext implements Replacement {
+    public static class ReplacementContext implements Replacement {
         /**
          * The method being replaced.
          */
@@ -121,6 +123,11 @@
         IntrinsicContext asIntrinsic() {
             return null;
         }
+
+        @Override
+        public String toString() {
+            return "Replacement{original: " + method.format("%H.%n(%p)") + ", replacement: " + replacement.format("%H.%n(%p)") + "}";
+        }
     }
 
     /**
@@ -129,25 +136,37 @@
      * information required to build a frame state denoting the JVM state just before the
      * intrinsified call.
      */
-    static class IntrinsicContext extends ReplacementContext {
+    public static class IntrinsicContext extends ReplacementContext {
 
         /**
-         * The arguments to the intrinsified invocation.
+         * BCI denoting an intrinsic is being parsed for inlining after the caller has been parsed.
          */
-        private final ValueNode[] invokeArgs;
+        public static final int POST_PARSE_INLINE_BCI = -1;
+
+        /**
+         * BCI denoting an intrinsic is the compilation root.
+         */
+        public static final int ROOT_COMPILATION_BCI = -2;
 
         /**
-         * The BCI of the intrinsified invocation.
+         * The arguments to the intrinsic.
          */
-        private final int invokeBci;
+        ValueNode[] args;
 
-        private FrameState invokeStateBefore;
-        private FrameState invokeStateDuring;
+        /**
+         * The BCI of the intrinsified invocation, {@link #POST_PARSE_INLINE_BCI} or
+         * {@link #ROOT_COMPILATION_BCI}.
+         */
+        final int bci;
 
-        public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod substitute, ValueNode[] invokeArgs, int invokeBci) {
+        private FrameState stateBeforeCache;
+
+        public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod substitute, ValueNode[] args, int bci) {
             super(method, substitute);
-            this.invokeArgs = invokeArgs;
-            this.invokeBci = invokeBci;
+            assert bci != POST_PARSE_INLINE_BCI || args == null;
+            this.args = args;
+            this.bci = bci;
+            assert !isCompilationRoot() || method.hasBytecodes() : "Cannot intrinsic for native or abstract method " + method.format("%H.%n(%p)");
         }
 
         @Override
@@ -155,34 +174,56 @@
             return true;
         }
 
-        /**
-         * Gets the frame state that will restart the interpreter just before the intrinsified
-         * invocation.
-         */
-        public FrameState getInvokeStateBefore(BytecodeParser parent) {
-            assert !parent.parsingReplacement() || parent.replacementContext instanceof IntrinsicContext;
-            if (invokeStateDuring == null) {
-                assert invokeStateBefore == null;
-                // Find the ancestor calling the replaced method
-                BytecodeParser ancestor = parent;
-                while (ancestor.parsingReplacement()) {
-                    ancestor = ancestor.getParent();
-                }
-                invokeStateDuring = ancestor.getFrameState().create(ancestor.bci(), ancestor.getParent(), true);
-                invokeStateBefore = invokeStateDuring.duplicateModifiedBeforeCall(invokeBci, Kind.Void, invokeArgs);
-            }
-            return invokeStateBefore;
+        public boolean isPostParseInlined() {
+            return bci == POST_PARSE_INLINE_BCI;
+        }
+
+        public boolean isCompilationRoot() {
+            return bci == ROOT_COMPILATION_BCI;
         }
 
-        public FrameState getInvokeStateDuring() {
-            assert invokeStateDuring != null : "must only be called after getInvokeStateBefore()";
-            return invokeStateDuring;
+        public FrameState getInvokeStateBefore(StructuredGraph graph, BytecodeParser parent) {
+            if (isCompilationRoot()) {
+                int maxLocals = method.getMaxLocals();
+                // The 'args' were initialized based on the intrinsic method but a
+                // frame state's 'locals' needs to have the same length as the frame
+                // state method's 'max_locals'.
+                ValueNode[] locals = maxLocals == args.length ? args : Arrays.copyOf(args, maxLocals);
+                ValueNode[] stack = EMPTY_ARRAY;
+                int stackSize = 0;
+                ValueNode[] locks = EMPTY_ARRAY;
+                List<MonitorIdNode> monitorIds = Collections.emptyList();
+                return graph.add(new FrameState(null, method, 0, locals, stack, stackSize, locks, monitorIds, false, false));
+            } else if (isPostParseInlined()) {
+                return graph.add(new FrameState(BytecodeFrame.BEFORE_BCI));
+            } else {
+                assert !parent.parsingReplacement() || parent.replacementContext instanceof IntrinsicContext;
+                if (stateBeforeCache == null) {
+                    assert stateBeforeCache == null;
+
+                    // Find the non-intrinsic ancestor calling the intrinsified method
+                    BytecodeParser ancestor = parent;
+                    while (ancestor.parsingReplacement()) {
+                        assert ancestor.replacementContext instanceof IntrinsicContext;
+                        ancestor = ancestor.getParent();
+                    }
+                    FrameState stateDuring = ancestor.getFrameState().create(ancestor.bci(), ancestor.getParent(), true);
+                    stateBeforeCache = stateDuring.duplicateModifiedBeforeCall(bci, Kind.Void, args);
+                }
+                return stateBeforeCache;
+            }
         }
 
         @Override
         IntrinsicContext asIntrinsic() {
             return this;
         }
+
+        @Override
+        public String toString() {
+            return "Intrinsic{original: " + method.format("%H.%n(%p)") + ", replacement: " + replacement.format("%H.%n(%p)") + ", bci: " + bci +
+                            (args == null ? "" : ", args: " + Arrays.toString(args)) + (stateBeforeCache == null ? "" : ", stateBefore: " + stateBeforeCache) + "}";
+        }
     }
 
     /**
@@ -1104,214 +1145,214 @@
 
         // Checkstyle: stop
         // @formatter:off
-    switch (opcode) {
-        case NOP            : /* nothing to do */ break;
-        case ACONST_NULL    : frameState.apush(appendConstant(JavaConstant.NULL_POINTER)); break;
-        case ICONST_M1      : // fall through
-        case ICONST_0       : // fall through
-        case ICONST_1       : // fall through
-        case ICONST_2       : // fall through
-        case ICONST_3       : // fall through
-        case ICONST_4       : // fall through
-        case ICONST_5       : frameState.ipush(appendConstant(JavaConstant.forInt(opcode - ICONST_0))); break;
-        case LCONST_0       : // fall through
-        case LCONST_1       : frameState.lpush(appendConstant(JavaConstant.forLong(opcode - LCONST_0))); break;
-        case FCONST_0       : // fall through
-        case FCONST_1       : // fall through
-        case FCONST_2       : frameState.fpush(appendConstant(JavaConstant.forFloat(opcode - FCONST_0))); break;
-        case DCONST_0       : // fall through
-        case DCONST_1       : frameState.dpush(appendConstant(JavaConstant.forDouble(opcode - DCONST_0))); break;
-        case BIPUSH         : frameState.ipush(appendConstant(JavaConstant.forInt(stream.readByte()))); break;
-        case SIPUSH         : frameState.ipush(appendConstant(JavaConstant.forInt(stream.readShort()))); break;
-        case LDC            : // fall through
-        case LDC_W          : // fall through
-        case LDC2_W         : genLoadConstant(stream.readCPI(), opcode); break;
-        case ILOAD          : loadLocal(stream.readLocalIndex(), Kind.Int); break;
-        case LLOAD          : loadLocal(stream.readLocalIndex(), Kind.Long); break;
-        case FLOAD          : loadLocal(stream.readLocalIndex(), Kind.Float); break;
-        case DLOAD          : loadLocal(stream.readLocalIndex(), Kind.Double); break;
-        case ALOAD          : loadLocal(stream.readLocalIndex(), Kind.Object); break;
-        case ILOAD_0        : // fall through
-        case ILOAD_1        : // fall through
-        case ILOAD_2        : // fall through
-        case ILOAD_3        : loadLocal(opcode - ILOAD_0, Kind.Int); break;
-        case LLOAD_0        : // fall through
-        case LLOAD_1        : // fall through
-        case LLOAD_2        : // fall through
-        case LLOAD_3        : loadLocal(opcode - LLOAD_0, Kind.Long); break;
-        case FLOAD_0        : // fall through
-        case FLOAD_1        : // fall through
-        case FLOAD_2        : // fall through
-        case FLOAD_3        : loadLocal(opcode - FLOAD_0, Kind.Float); break;
-        case DLOAD_0        : // fall through
-        case DLOAD_1        : // fall through
-        case DLOAD_2        : // fall through
-        case DLOAD_3        : loadLocal(opcode - DLOAD_0, Kind.Double); break;
-        case ALOAD_0        : // fall through
-        case ALOAD_1        : // fall through
-        case ALOAD_2        : // fall through
-        case ALOAD_3        : loadLocal(opcode - ALOAD_0, Kind.Object); break;
-        case IALOAD         : genLoadIndexed(Kind.Int   ); break;
-        case LALOAD         : genLoadIndexed(Kind.Long  ); break;
-        case FALOAD         : genLoadIndexed(Kind.Float ); break;
-        case DALOAD         : genLoadIndexed(Kind.Double); break;
-        case AALOAD         : genLoadIndexed(Kind.Object); break;
-        case BALOAD         : genLoadIndexed(Kind.Byte  ); break;
-        case CALOAD         : genLoadIndexed(Kind.Char  ); break;
-        case SALOAD         : genLoadIndexed(Kind.Short ); break;
-        case ISTORE         : storeLocal(Kind.Int, stream.readLocalIndex()); break;
-        case LSTORE         : storeLocal(Kind.Long, stream.readLocalIndex()); break;
-        case FSTORE         : storeLocal(Kind.Float, stream.readLocalIndex()); break;
-        case DSTORE         : storeLocal(Kind.Double, stream.readLocalIndex()); break;
-        case ASTORE         : storeLocal(Kind.Object, stream.readLocalIndex()); break;
-        case ISTORE_0       : // fall through
-        case ISTORE_1       : // fall through
-        case ISTORE_2       : // fall through
-        case ISTORE_3       : storeLocal(Kind.Int, opcode - ISTORE_0); break;
-        case LSTORE_0       : // fall through
-        case LSTORE_1       : // fall through
-        case LSTORE_2       : // fall through
-        case LSTORE_3       : storeLocal(Kind.Long, opcode - LSTORE_0); break;
-        case FSTORE_0       : // fall through
-        case FSTORE_1       : // fall through
-        case FSTORE_2       : // fall through
-        case FSTORE_3       : storeLocal(Kind.Float, opcode - FSTORE_0); break;
-        case DSTORE_0       : // fall through
-        case DSTORE_1       : // fall through
-        case DSTORE_2       : // fall through
-        case DSTORE_3       : storeLocal(Kind.Double, opcode - DSTORE_0); break;
-        case ASTORE_0       : // fall through
-        case ASTORE_1       : // fall through
-        case ASTORE_2       : // fall through
-        case ASTORE_3       : storeLocal(Kind.Object, opcode - ASTORE_0); break;
-        case IASTORE        : genStoreIndexed(Kind.Int   ); break;
-        case LASTORE        : genStoreIndexed(Kind.Long  ); break;
-        case FASTORE        : genStoreIndexed(Kind.Float ); break;
-        case DASTORE        : genStoreIndexed(Kind.Double); break;
-        case AASTORE        : genStoreIndexed(Kind.Object); break;
-        case BASTORE        : genStoreIndexed(Kind.Byte  ); break;
-        case CASTORE        : genStoreIndexed(Kind.Char  ); break;
-        case SASTORE        : genStoreIndexed(Kind.Short ); break;
-        case POP            : frameState.xpop(); break;
-        case POP2           : frameState.xpop(); frameState.xpop(); break;
-        case DUP            : frameState.xpush(frameState.xpeek()); break;
-        case DUP_X1         : // fall through
-        case DUP_X2         : // fall through
-        case DUP2           : // fall through
-        case DUP2_X1        : // fall through
-        case DUP2_X2        : // fall through
-        case SWAP           : stackOp(opcode); break;
-        case IADD           : // fall through
-        case ISUB           : // fall through
-        case IMUL           : genArithmeticOp(Kind.Int, opcode); break;
-        case IDIV           : // fall through
-        case IREM           : genIntegerDivOp(Kind.Int, opcode); break;
-        case LADD           : // fall through
-        case LSUB           : // fall through
-        case LMUL           : genArithmeticOp(Kind.Long, opcode); break;
-        case LDIV           : // fall through
-        case LREM           : genIntegerDivOp(Kind.Long, opcode); break;
-        case FADD           : // fall through
-        case FSUB           : // fall through
-        case FMUL           : // fall through
-        case FDIV           : // fall through
-        case FREM           : genArithmeticOp(Kind.Float, opcode); break;
-        case DADD           : // fall through
-        case DSUB           : // fall through
-        case DMUL           : // fall through
-        case DDIV           : // fall through
-        case DREM           : genArithmeticOp(Kind.Double, opcode); break;
-        case INEG           : genNegateOp(Kind.Int); break;
-        case LNEG           : genNegateOp(Kind.Long); break;
-        case FNEG           : genNegateOp(Kind.Float); break;
-        case DNEG           : genNegateOp(Kind.Double); break;
-        case ISHL           : // fall through
-        case ISHR           : // fall through
-        case IUSHR          : genShiftOp(Kind.Int, opcode); break;
-        case IAND           : // fall through
-        case IOR            : // fall through
-        case IXOR           : genLogicOp(Kind.Int, opcode); break;
-        case LSHL           : // fall through
-        case LSHR           : // fall through
-        case LUSHR          : genShiftOp(Kind.Long, opcode); break;
-        case LAND           : // fall through
-        case LOR            : // fall through
-        case LXOR           : genLogicOp(Kind.Long, opcode); break;
-        case IINC           : genIncrement(); break;
-        case I2F            : genFloatConvert(FloatConvert.I2F, Kind.Int, Kind.Float); break;
-        case I2D            : genFloatConvert(FloatConvert.I2D, Kind.Int, Kind.Double); break;
-        case L2F            : genFloatConvert(FloatConvert.L2F, Kind.Long, Kind.Float); break;
-        case L2D            : genFloatConvert(FloatConvert.L2D, Kind.Long, Kind.Double); break;
-        case F2I            : genFloatConvert(FloatConvert.F2I, Kind.Float, Kind.Int); break;
-        case F2L            : genFloatConvert(FloatConvert.F2L, Kind.Float, Kind.Long); break;
-        case F2D            : genFloatConvert(FloatConvert.F2D, Kind.Float, Kind.Double); break;
-        case D2I            : genFloatConvert(FloatConvert.D2I, Kind.Double, Kind.Int); break;
-        case D2L            : genFloatConvert(FloatConvert.D2L, Kind.Double, Kind.Long); break;
-        case D2F            : genFloatConvert(FloatConvert.D2F, Kind.Double, Kind.Float); break;
-        case L2I            : genNarrow(Kind.Long, Kind.Int); break;
-        case I2L            : genSignExtend(Kind.Int, Kind.Long); break;
-        case I2B            : genSignExtend(Kind.Byte, Kind.Int); break;
-        case I2S            : genSignExtend(Kind.Short, Kind.Int); break;
-        case I2C            : genZeroExtend(Kind.Char, Kind.Int); break;
-        case LCMP           : genCompareOp(Kind.Long, false); break;
-        case FCMPL          : genCompareOp(Kind.Float, true); break;
-        case FCMPG          : genCompareOp(Kind.Float, false); break;
-        case DCMPL          : genCompareOp(Kind.Double, true); break;
-        case DCMPG          : genCompareOp(Kind.Double, false); break;
-        case IFEQ           : genIfZero(Condition.EQ); break;
-        case IFNE           : genIfZero(Condition.NE); break;
-        case IFLT           : genIfZero(Condition.LT); break;
-        case IFGE           : genIfZero(Condition.GE); break;
-        case IFGT           : genIfZero(Condition.GT); break;
-        case IFLE           : genIfZero(Condition.LE); break;
-        case IF_ICMPEQ      : genIfSame(Kind.Int, Condition.EQ); break;
-        case IF_ICMPNE      : genIfSame(Kind.Int, Condition.NE); break;
-        case IF_ICMPLT      : genIfSame(Kind.Int, Condition.LT); break;
-        case IF_ICMPGE      : genIfSame(Kind.Int, Condition.GE); break;
-        case IF_ICMPGT      : genIfSame(Kind.Int, Condition.GT); break;
-        case IF_ICMPLE      : genIfSame(Kind.Int, Condition.LE); break;
-        case IF_ACMPEQ      : genIfSame(Kind.Object, Condition.EQ); break;
-        case IF_ACMPNE      : genIfSame(Kind.Object, Condition.NE); break;
-        case GOTO           : genGoto(); break;
-        case JSR            : genJsr(stream.readBranchDest()); break;
-        case RET            : genRet(stream.readLocalIndex()); break;
-        case TABLESWITCH    : genSwitch(new BytecodeTableSwitch(getStream(), bci())); break;
-        case LOOKUPSWITCH   : genSwitch(new BytecodeLookupSwitch(getStream(), bci())); break;
-        case IRETURN        : genReturn(frameState.ipop(), Kind.Int); break;
-        case LRETURN        : genReturn(frameState.lpop(), Kind.Long); break;
-        case FRETURN        : genReturn(frameState.fpop(), Kind.Float); break;
-        case DRETURN        : genReturn(frameState.dpop(), Kind.Double); break;
-        case ARETURN        : genReturn(frameState.apop(), Kind.Object); break;
-        case RETURN         : genReturn(null, Kind.Void); break;
-        case GETSTATIC      : cpi = stream.readCPI(); genGetStatic(lookupField(cpi, opcode)); break;
-        case PUTSTATIC      : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break;
-        case GETFIELD       : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break;
-        case PUTFIELD       : cpi = stream.readCPI(); genPutField(lookupField(cpi, opcode)); break;
-        case INVOKEVIRTUAL  : cpi = stream.readCPI(); genInvokeVirtual(lookupMethod(cpi, opcode)); break;
-        case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break;
-        case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break;
-        case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break;
-        case INVOKEDYNAMIC  : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break;
-        case NEW            : genNewInstance(stream.readCPI()); break;
-        case NEWARRAY       : genNewPrimitiveArray(stream.readLocalIndex()); break;
-        case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
-        case ARRAYLENGTH    : genArrayLength(); break;
-        case ATHROW         : genThrow(); break;
-        case CHECKCAST      : genCheckCast(); break;
-        case INSTANCEOF     : genInstanceOf(); break;
-        case MONITORENTER   : genMonitorEnter(frameState.apop(), stream.nextBCI()); break;
-        case MONITOREXIT    : genMonitorExit(frameState.apop(), null, stream.nextBCI()); break;
-        case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
-        case IFNULL         : genIfNull(Condition.EQ); break;
-        case IFNONNULL      : genIfNull(Condition.NE); break;
-        case GOTO_W         : genGoto(); break;
-        case JSR_W          : genJsr(stream.readBranchDest()); break;
-        case BREAKPOINT:
-            throw new BailoutException("concurrent setting of breakpoint");
-        default:
-            throw new BailoutException("Unsupported opcode %d (%s) [bci=%d]", opcode, nameOf(opcode), bci);
-    }
-    // @formatter:on
+        switch (opcode) {
+            case NOP            : /* nothing to do */ break;
+            case ACONST_NULL    : frameState.apush(appendConstant(JavaConstant.NULL_POINTER)); break;
+            case ICONST_M1      : // fall through
+            case ICONST_0       : // fall through
+            case ICONST_1       : // fall through
+            case ICONST_2       : // fall through
+            case ICONST_3       : // fall through
+            case ICONST_4       : // fall through
+            case ICONST_5       : frameState.ipush(appendConstant(JavaConstant.forInt(opcode - ICONST_0))); break;
+            case LCONST_0       : // fall through
+            case LCONST_1       : frameState.lpush(appendConstant(JavaConstant.forLong(opcode - LCONST_0))); break;
+            case FCONST_0       : // fall through
+            case FCONST_1       : // fall through
+            case FCONST_2       : frameState.fpush(appendConstant(JavaConstant.forFloat(opcode - FCONST_0))); break;
+            case DCONST_0       : // fall through
+            case DCONST_1       : frameState.dpush(appendConstant(JavaConstant.forDouble(opcode - DCONST_0))); break;
+            case BIPUSH         : frameState.ipush(appendConstant(JavaConstant.forInt(stream.readByte()))); break;
+            case SIPUSH         : frameState.ipush(appendConstant(JavaConstant.forInt(stream.readShort()))); break;
+            case LDC            : // fall through
+            case LDC_W          : // fall through
+            case LDC2_W         : genLoadConstant(stream.readCPI(), opcode); break;
+            case ILOAD          : loadLocal(stream.readLocalIndex(), Kind.Int); break;
+            case LLOAD          : loadLocal(stream.readLocalIndex(), Kind.Long); break;
+            case FLOAD          : loadLocal(stream.readLocalIndex(), Kind.Float); break;
+            case DLOAD          : loadLocal(stream.readLocalIndex(), Kind.Double); break;
+            case ALOAD          : loadLocal(stream.readLocalIndex(), Kind.Object); break;
+            case ILOAD_0        : // fall through
+            case ILOAD_1        : // fall through
+            case ILOAD_2        : // fall through
+            case ILOAD_3        : loadLocal(opcode - ILOAD_0, Kind.Int); break;
+            case LLOAD_0        : // fall through
+            case LLOAD_1        : // fall through
+            case LLOAD_2        : // fall through
+            case LLOAD_3        : loadLocal(opcode - LLOAD_0, Kind.Long); break;
+            case FLOAD_0        : // fall through
+            case FLOAD_1        : // fall through
+            case FLOAD_2        : // fall through
+            case FLOAD_3        : loadLocal(opcode - FLOAD_0, Kind.Float); break;
+            case DLOAD_0        : // fall through
+            case DLOAD_1        : // fall through
+            case DLOAD_2        : // fall through
+            case DLOAD_3        : loadLocal(opcode - DLOAD_0, Kind.Double); break;
+            case ALOAD_0        : // fall through
+            case ALOAD_1        : // fall through
+            case ALOAD_2        : // fall through
+            case ALOAD_3        : loadLocal(opcode - ALOAD_0, Kind.Object); break;
+            case IALOAD         : genLoadIndexed(Kind.Int   ); break;
+            case LALOAD         : genLoadIndexed(Kind.Long  ); break;
+            case FALOAD         : genLoadIndexed(Kind.Float ); break;
+            case DALOAD         : genLoadIndexed(Kind.Double); break;
+            case AALOAD         : genLoadIndexed(Kind.Object); break;
+            case BALOAD         : genLoadIndexed(Kind.Byte  ); break;
+            case CALOAD         : genLoadIndexed(Kind.Char  ); break;
+            case SALOAD         : genLoadIndexed(Kind.Short ); break;
+            case ISTORE         : storeLocal(Kind.Int, stream.readLocalIndex()); break;
+            case LSTORE         : storeLocal(Kind.Long, stream.readLocalIndex()); break;
+            case FSTORE         : storeLocal(Kind.Float, stream.readLocalIndex()); break;
+            case DSTORE         : storeLocal(Kind.Double, stream.readLocalIndex()); break;
+            case ASTORE         : storeLocal(Kind.Object, stream.readLocalIndex()); break;
+            case ISTORE_0       : // fall through
+            case ISTORE_1       : // fall through
+            case ISTORE_2       : // fall through
+            case ISTORE_3       : storeLocal(Kind.Int, opcode - ISTORE_0); break;
+            case LSTORE_0       : // fall through
+            case LSTORE_1       : // fall through
+            case LSTORE_2       : // fall through
+            case LSTORE_3       : storeLocal(Kind.Long, opcode - LSTORE_0); break;
+            case FSTORE_0       : // fall through
+            case FSTORE_1       : // fall through
+            case FSTORE_2       : // fall through
+            case FSTORE_3       : storeLocal(Kind.Float, opcode - FSTORE_0); break;
+            case DSTORE_0       : // fall through
+            case DSTORE_1       : // fall through
+            case DSTORE_2       : // fall through
+            case DSTORE_3       : storeLocal(Kind.Double, opcode - DSTORE_0); break;
+            case ASTORE_0       : // fall through
+            case ASTORE_1       : // fall through
+            case ASTORE_2       : // fall through
+            case ASTORE_3       : storeLocal(Kind.Object, opcode - ASTORE_0); break;
+            case IASTORE        : genStoreIndexed(Kind.Int   ); break;
+            case LASTORE        : genStoreIndexed(Kind.Long  ); break;
+            case FASTORE        : genStoreIndexed(Kind.Float ); break;
+            case DASTORE        : genStoreIndexed(Kind.Double); break;
+            case AASTORE        : genStoreIndexed(Kind.Object); break;
+            case BASTORE        : genStoreIndexed(Kind.Byte  ); break;
+            case CASTORE        : genStoreIndexed(Kind.Char  ); break;
+            case SASTORE        : genStoreIndexed(Kind.Short ); break;
+            case POP            : frameState.xpop(); break;
+            case POP2           : frameState.xpop(); frameState.xpop(); break;
+            case DUP            : frameState.xpush(frameState.xpeek()); break;
+            case DUP_X1         : // fall through
+            case DUP_X2         : // fall through
+            case DUP2           : // fall through
+            case DUP2_X1        : // fall through
+            case DUP2_X2        : // fall through
+            case SWAP           : stackOp(opcode); break;
+            case IADD           : // fall through
+            case ISUB           : // fall through
+            case IMUL           : genArithmeticOp(Kind.Int, opcode); break;
+            case IDIV           : // fall through
+            case IREM           : genIntegerDivOp(Kind.Int, opcode); break;
+            case LADD           : // fall through
+            case LSUB           : // fall through
+            case LMUL           : genArithmeticOp(Kind.Long, opcode); break;
+            case LDIV           : // fall through
+            case LREM           : genIntegerDivOp(Kind.Long, opcode); break;
+            case FADD           : // fall through
+            case FSUB           : // fall through
+            case FMUL           : // fall through
+            case FDIV           : // fall through
+            case FREM           : genArithmeticOp(Kind.Float, opcode); break;
+            case DADD           : // fall through
+            case DSUB           : // fall through
+            case DMUL           : // fall through
+            case DDIV           : // fall through
+            case DREM           : genArithmeticOp(Kind.Double, opcode); break;
+            case INEG           : genNegateOp(Kind.Int); break;
+            case LNEG           : genNegateOp(Kind.Long); break;
+            case FNEG           : genNegateOp(Kind.Float); break;
+            case DNEG           : genNegateOp(Kind.Double); break;
+            case ISHL           : // fall through
+            case ISHR           : // fall through
+            case IUSHR          : genShiftOp(Kind.Int, opcode); break;
+            case IAND           : // fall through
+            case IOR            : // fall through
+            case IXOR           : genLogicOp(Kind.Int, opcode); break;
+            case LSHL           : // fall through
+            case LSHR           : // fall through
+            case LUSHR          : genShiftOp(Kind.Long, opcode); break;
+            case LAND           : // fall through
+            case LOR            : // fall through
+            case LXOR           : genLogicOp(Kind.Long, opcode); break;
+            case IINC           : genIncrement(); break;
+            case I2F            : genFloatConvert(FloatConvert.I2F, Kind.Int, Kind.Float); break;
+            case I2D            : genFloatConvert(FloatConvert.I2D, Kind.Int, Kind.Double); break;
+            case L2F            : genFloatConvert(FloatConvert.L2F, Kind.Long, Kind.Float); break;
+            case L2D            : genFloatConvert(FloatConvert.L2D, Kind.Long, Kind.Double); break;
+            case F2I            : genFloatConvert(FloatConvert.F2I, Kind.Float, Kind.Int); break;
+            case F2L            : genFloatConvert(FloatConvert.F2L, Kind.Float, Kind.Long); break;
+            case F2D            : genFloatConvert(FloatConvert.F2D, Kind.Float, Kind.Double); break;
+            case D2I            : genFloatConvert(FloatConvert.D2I, Kind.Double, Kind.Int); break;
+            case D2L            : genFloatConvert(FloatConvert.D2L, Kind.Double, Kind.Long); break;
+            case D2F            : genFloatConvert(FloatConvert.D2F, Kind.Double, Kind.Float); break;
+            case L2I            : genNarrow(Kind.Long, Kind.Int); break;
+            case I2L            : genSignExtend(Kind.Int, Kind.Long); break;
+            case I2B            : genSignExtend(Kind.Byte, Kind.Int); break;
+            case I2S            : genSignExtend(Kind.Short, Kind.Int); break;
+            case I2C            : genZeroExtend(Kind.Char, Kind.Int); break;
+            case LCMP           : genCompareOp(Kind.Long, false); break;
+            case FCMPL          : genCompareOp(Kind.Float, true); break;
+            case FCMPG          : genCompareOp(Kind.Float, false); break;
+            case DCMPL          : genCompareOp(Kind.Double, true); break;
+            case DCMPG          : genCompareOp(Kind.Double, false); break;
+            case IFEQ           : genIfZero(Condition.EQ); break;
+            case IFNE           : genIfZero(Condition.NE); break;
+            case IFLT           : genIfZero(Condition.LT); break;
+            case IFGE           : genIfZero(Condition.GE); break;
+            case IFGT           : genIfZero(Condition.GT); break;
+            case IFLE           : genIfZero(Condition.LE); break;
+            case IF_ICMPEQ      : genIfSame(Kind.Int, Condition.EQ); break;
+            case IF_ICMPNE      : genIfSame(Kind.Int, Condition.NE); break;
+            case IF_ICMPLT      : genIfSame(Kind.Int, Condition.LT); break;
+            case IF_ICMPGE      : genIfSame(Kind.Int, Condition.GE); break;
+            case IF_ICMPGT      : genIfSame(Kind.Int, Condition.GT); break;
+            case IF_ICMPLE      : genIfSame(Kind.Int, Condition.LE); break;
+            case IF_ACMPEQ      : genIfSame(Kind.Object, Condition.EQ); break;
+            case IF_ACMPNE      : genIfSame(Kind.Object, Condition.NE); break;
+            case GOTO           : genGoto(); break;
+            case JSR            : genJsr(stream.readBranchDest()); break;
+            case RET            : genRet(stream.readLocalIndex()); break;
+            case TABLESWITCH    : genSwitch(new BytecodeTableSwitch(getStream(), bci())); break;
+            case LOOKUPSWITCH   : genSwitch(new BytecodeLookupSwitch(getStream(), bci())); break;
+            case IRETURN        : genReturn(frameState.ipop(), Kind.Int); break;
+            case LRETURN        : genReturn(frameState.lpop(), Kind.Long); break;
+            case FRETURN        : genReturn(frameState.fpop(), Kind.Float); break;
+            case DRETURN        : genReturn(frameState.dpop(), Kind.Double); break;
+            case ARETURN        : genReturn(frameState.apop(), Kind.Object); break;
+            case RETURN         : genReturn(null, Kind.Void); break;
+            case GETSTATIC      : cpi = stream.readCPI(); genGetStatic(lookupField(cpi, opcode)); break;
+            case PUTSTATIC      : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break;
+            case GETFIELD       : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break;
+            case PUTFIELD       : cpi = stream.readCPI(); genPutField(lookupField(cpi, opcode)); break;
+            case INVOKEVIRTUAL  : cpi = stream.readCPI(); genInvokeVirtual(lookupMethod(cpi, opcode)); break;
+            case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break;
+            case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break;
+            case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break;
+            case INVOKEDYNAMIC  : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break;
+            case NEW            : genNewInstance(stream.readCPI()); break;
+            case NEWARRAY       : genNewPrimitiveArray(stream.readLocalIndex()); break;
+            case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
+            case ARRAYLENGTH    : genArrayLength(); break;
+            case ATHROW         : genThrow(); break;
+            case CHECKCAST      : genCheckCast(); break;
+            case INSTANCEOF     : genInstanceOf(); break;
+            case MONITORENTER   : genMonitorEnter(frameState.apop(), stream.nextBCI()); break;
+            case MONITOREXIT    : genMonitorExit(frameState.apop(), null, stream.nextBCI()); break;
+            case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
+            case IFNULL         : genIfNull(Condition.EQ); break;
+            case IFNONNULL      : genIfNull(Condition.NE); break;
+            case GOTO_W         : genGoto(); break;
+            case JSR_W          : genJsr(stream.readBranchDest()); break;
+            case BREAKPOINT:
+                throw new BailoutException("concurrent setting of breakpoint");
+            default:
+                throw new BailoutException("Unsupported opcode %d (%s) [bci=%d]", opcode, nameOf(opcode), bci);
+        }
+        // @formatter:on
         // Checkstyle: resume
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Mon Mar 23 00:26:47 2015 +0100
@@ -51,6 +51,15 @@
      * @return {@code null} if {@code method} has no bytecode (e.g., it is native or abstract)
      */
     public String disassemble(ResolvedJavaMethod method) {
+        return disassemble(method, 0, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Disassembles the bytecode of a given method in a {@code javap}-like format.
+     *
+     * @return {@code null} if {@code method} has no bytecode (e.g., it is native or abstract)
+     */
+    public String disassemble(ResolvedJavaMethod method, int startBci, int endBci) {
         if (method.getCode() == null) {
             return null;
         }
@@ -60,10 +69,11 @@
         int opcode = stream.currentBC();
         while (opcode != Bytecodes.END) {
             int bci = stream.currentBCI();
-            String mnemonic = Bytecodes.nameOf(opcode);
-            buf.append(String.format("%4d: %-14s", bci, mnemonic));
-            if (stream.nextBCI() > bci + 1) {
-                // @formatter:off
+            if (bci >= startBci && bci <= endBci) {
+                String mnemonic = Bytecodes.nameOf(opcode);
+                buf.append(String.format("%4d: %-14s", bci, mnemonic));
+                if (stream.nextBCI() > bci + 1) {
+                    // @formatter:off
                 switch (opcode) {
                     case BIPUSH         : buf.append(stream.readByte()); break;
                     case SIPUSH         : buf.append(stream.readShort()); break;
@@ -211,8 +221,9 @@
                     }
                 }
                 // @formatter:on
+                }
+                buf.append(String.format("%n"));
             }
-            buf.append(String.format("%n"));
             stream.next();
             opcode = stream.currentBC();
         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Mar 23 00:26:47 2015 +0100
@@ -100,7 +100,9 @@
          * Furthermore, if it is non-null and not equal to {@link #rootMethod} then this is the
          * original method for which a snippet exists (e.g., System.arraycopy()).
          */
-        private final ResolvedJavaMethod rootMethodIsReplacement;
+        // private final ResolvedJavaMethod rootMethodIsReplacement;
+
+        private final ReplacementContext initialReplacementContext;
 
         private final GraphBuilderConfiguration graphBuilderConfig;
         private final OptimisticOptimizations optimisticOpts;
@@ -109,20 +111,21 @@
         private final SnippetReflectionProvider snippetReflectionProvider;
 
         public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, ConstantReflectionProvider constantReflection,
-                        GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod rootMethodIsReplacement) {
+                        GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, ReplacementContext initialReplacementContext) {
             this.graphBuilderConfig = graphBuilderConfig;
             this.optimisticOpts = optimisticOpts;
             this.metaAccess = metaAccess;
             this.stampProvider = stampProvider;
             this.constantReflection = constantReflection;
             this.snippetReflectionProvider = snippetReflectionProvider;
-            this.rootMethodIsReplacement = rootMethodIsReplacement;
+            this.initialReplacementContext = initialReplacementContext;
+
             assert metaAccess != null;
         }
 
         public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig,
-                        OptimisticOptimizations optimisticOpts, ResolvedJavaMethod rootMethodIsReplacement) {
-            this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, optimisticOpts, rootMethodIsReplacement);
+                        OptimisticOptimizations optimisticOpts, ReplacementContext initialReplacementContext) {
+            this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, optimisticOpts, initialReplacementContext);
         }
 
         @Override
@@ -134,10 +137,10 @@
             this.currentGraph = graph;
             TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
             try {
-                ReplacementContext replacementContext = rootMethodIsReplacement != null ? new ReplacementContext(rootMethodIsReplacement, rootMethod) : null;
+                ReplacementContext replacementContext = initialReplacementContext;
                 BytecodeParser parser = new BytecodeParser(null, metaAccess, method, graphBuilderConfig, optimisticOpts, entryBCI, replacementContext);
                 HIRFrameStateBuilder frameState = new HIRFrameStateBuilder(parser, method, graph);
-                frameState.initializeForMethodStart(graphBuilderConfig.eagerResolving() || rootMethodIsReplacement != null, graphBuilderConfig.getPlugins().getParameterPlugin());
+                frameState.initializeForMethodStart(graphBuilderConfig.eagerResolving() || replacementContext != null, graphBuilderConfig.getPlugins().getParameterPlugin());
                 parser.build(graph.start(), frameState);
 
                 parser.connectLoopEndToBegin();
@@ -1316,13 +1319,30 @@
                 }
                 ReplacementContext context = this.replacementContext;
                 if (context != null && context.isCallToOriginal(targetMethod)) {
-                    assert context.asIntrinsic() == null : "intrinsic cannot call the method it is intrinsifying";
-                    // Self recursive replacement means the original
-                    // method should be called.
-                    if (context.method.hasBytecodes()) {
-                        parseAndInlineCallee(context.method, args, null);
+                    IntrinsicContext intrinsic = context.asIntrinsic();
+                    if (intrinsic != null) {
+                        if (intrinsic.isCompilationRoot()) {
+                            // A root compiled intrinsic needs to deoptimize
+                            // if the slow path is taken
+                            DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
+                            deopt.setStateBefore(intrinsic.getInvokeStateBefore(currentGraph, null));
+                            return true;
+                        } else {
+                            // Otherwise inline the original method. Any frame state created
+                            // during the inlining will exclude frame(s) in the
+                            // intrinsic method (see HIRFrameStateBuilder.create(int bci)).
+                            parseAndInlineCallee(context.method, args, null);
+                            return true;
+                        }
                     } else {
-                        return false;
+                        // Self recursive replacement means the original
+                        // method should be called.
+                        if (context.method.hasBytecodes()) {
+                            parseAndInlineCallee(context.method, args, null);
+                            return true;
+                        } else {
+                            return false;
+                        }
                     }
                 } else {
                     if (context == null && inlineInfo.isReplacement) {
@@ -2451,7 +2471,8 @@
                     if (bp != this) {
                         fmt.format("%n%s", indent);
                     }
-                    fmt.format("%s [bci: %d, replacement: %s]", bp.method.asStackTraceElement(bp.bci()), bci(), bp.parsingReplacement());
+                    fmt.format("%s [bci: %d, replacement: %s]", bp.method.asStackTraceElement(bp.bci()), bp.bci(), bp.parsingReplacement());
+                    fmt.format("%n%s", new BytecodeDisassembler().disassemble(bp.method, bp.bci(), bp.bci() + 10));
                     bp = bp.parent;
                     indent += " ";
                 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Mon Mar 23 00:26:47 2015 +0100
@@ -43,8 +43,8 @@
 
 public final class HIRFrameStateBuilder {
 
-    private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0];
-    private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0];
+    static final ValueNode[] EMPTY_ARRAY = new ValueNode[0];
+    static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0];
 
     protected final BytecodeParser parser;
     protected final ResolvedJavaMethod method;
@@ -145,6 +145,14 @@
             javaIndex += kind.getSlotCount();
             index++;
         }
+
+        if (parser.replacementContext instanceof IntrinsicContext) {
+            IntrinsicContext intrinsic = (IntrinsicContext) parser.replacementContext;
+            if (intrinsic.isCompilationRoot()) {
+                // Records the parameters to an root compiled intrinsic
+                intrinsic.args = locals.clone();
+            }
+        }
     }
 
     private HIRFrameStateBuilder(HIRFrameStateBuilder other) {
@@ -200,28 +208,20 @@
         if (parser.parsingReplacement()) {
             IntrinsicContext intrinsic = parser.replacementContext.asIntrinsic();
             if (intrinsic != null) {
-                assert parent != null : "intrinsics can only be processed in context of a caller";
-
-                // We're somewhere in an intrinsic. In this case, we want a frame state
-                // that will restart the interpreter just before the intrinsified
-                // invocation.
-                return intrinsic.getInvokeStateBefore(parent);
+                return intrinsic.getInvokeStateBefore(parser.getGraph(), parent);
             }
         }
+        // If this is the recursive call in a partial intrinsification
+        // the frame(s) of the intrinsic method are omitted
+        while (parent != null && parent.parsingReplacement() && parent.replacementContext.asIntrinsic() != null) {
+            parent = parent.getParent();
+        }
         return create(bci, parent, false);
     }
 
     public FrameState create(int bci, BytecodeParser parent, boolean duringCall) {
         if (outerFrameState == null && parent != null) {
             outerFrameState = parent.getFrameState().create(parent.bci());
-            if (parser.parsingReplacement()) {
-                IntrinsicContext intrinsic = parser.replacementContext.asIntrinsic();
-                if (intrinsic != null) {
-                    // A side-effect of creating the frame state in a replacing
-                    // parent is that the 'during' frame state is created as well
-                    outerFrameState = intrinsic.getInvokeStateDuring();
-                }
-            }
         }
         if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) {
             FrameState newFrameState = outerFrameState.duplicateModified(outerFrameState.bci, true, Kind.Void, this.peek(0));
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Math_sin.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Math_sin.java	Mon Mar 23 00:26:47 2015 +0100
@@ -35,7 +35,7 @@
     }
 
     public static double test(double arg) throws NaN {
-        double v = Math.sin(arg);
+        double v = Math.sin(arg) * Math.sin(arg * 5);
         if (Double.isNaN(v)) {
             // NaN can't be tested against itself
             throw new NaN();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Mon Mar 23 00:26:47 2015 +0100
@@ -33,8 +33,6 @@
  * Interface for managing replacements.
  */
 public interface Replacements {
-    // Disabled until bug in support for this is fixed.
-    boolean SELF_RECURSIVE_INTRINSICS_ENABLED = false;
 
     /**
      * Gets the snippet graph derived from a given method.
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Mon Mar 23 00:26:47 2015 +0100
@@ -32,6 +32,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
@@ -432,14 +433,18 @@
                     frameState.replaceAndDelete(stateAfterException);
                 } else if (frameState.bci == BytecodeFrame.UNWIND_BCI || frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
                     handleMissingAfterExceptionFrameState(frameState);
+                } else if (frameState.bci == BytecodeFrame.BEFORE_BCI) {
+                    // This is an intrinsic. Deoptimizing within an intrinsic
+                    // must re-execute the intrinsified invocation
+                    assert frameState.outerFrameState() == null;
+                    NodeInputList<ValueNode> invokeArgsList = invoke.callTarget().arguments();
+                    ValueNode[] invokeArgs = invokeArgsList.isEmpty() ? NO_ARGS : invokeArgsList.toArray(new ValueNode[invokeArgsList.size()]);
+                    FrameState stateBeforeCall = stateAtReturn.duplicateModifiedBeforeCall(invoke.bci(), invokeReturnKind, invokeArgs);
+                    frameState.replaceAndDelete(stateBeforeCall);
                 } else {
                     // only handle the outermost frame states
                     if (frameState.outerFrameState() == null) {
-                        assert frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI : frameState;
-                        assert frameState.bci != BytecodeFrame.BEFORE_BCI : frameState;
-                        assert frameState.bci != BytecodeFrame.UNKNOWN_BCI : frameState;
-                        assert frameState.bci != BytecodeFrame.UNWIND_BCI : frameState;
-                        assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method()) : frameState;
+                        assert checkInlineeFrameState(invoke, inlineGraph, frameState);
                         if (outerFrameState == null) {
                             outerFrameState = stateAtReturn.duplicateModifiedDuringCall(invoke.bci(), invokeReturnKind);
                         }
@@ -450,6 +455,32 @@
         }
     }
 
+    static boolean checkInlineeFrameState(Invoke invoke, StructuredGraph inlineGraph, FrameState frameState) {
+        assert frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI : frameState;
+        assert frameState.bci != BytecodeFrame.BEFORE_BCI : frameState;
+        assert frameState.bci != BytecodeFrame.UNKNOWN_BCI : frameState;
+        assert frameState.bci != BytecodeFrame.UNWIND_BCI : frameState;
+        if (frameState.bci != BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+            if (frameState.method().equals(inlineGraph.method())) {
+                // Normal inlining expects all outermost inlinee frame states to
+                // denote the inlinee method
+            } else if (frameState.method().equals(invoke.callTarget().targetMethod())) {
+                // This occurs when an intrinsic calls back to the original
+                // method to handle a slow path. During parsing of such a
+                // partial intrinsic, these calls are given frame states
+                // that exclude the outer frame state denoting a position
+                // in the intrinsic code.
+                assert inlineGraph.method().getAnnotation(MethodSubstitution.class) != null : "expected an intrinsic when inlinee frame state matches method of call target but does not match the method of the inlinee graph: " +
+                                frameState;
+            } else {
+                throw new AssertionError(frameState.toString());
+            }
+        }
+        return true;
+    }
+
+    private static final ValueNode[] NO_ARGS = {};
+
     private static boolean isStateAfterException(FrameState frameState) {
         return frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI || (frameState.bci == BytecodeFrame.UNWIND_BCI && !frameState.method().isSynchronized());
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Mon Mar 23 00:26:47 2015 +0100
@@ -50,7 +50,7 @@
 
     @Override
     protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) {
-        return installer.makeGraph(m, null, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect);
+        return installer.makeGraph(m, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect);
     }
 
     @Test
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Mar 23 00:26:47 2015 +0100
@@ -36,7 +36,6 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing;
-import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
 import com.oracle.graal.word.*;
 import com.oracle.graal.word.nodes.*;
 
@@ -55,11 +54,9 @@
         installer = (ReplacementsImpl) getProviders().getReplacements();
     }
 
-    private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
-
     @Override
     protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) {
-        return installer.makeGraph(m, null, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect);
+        return installer.makeGraph(m, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect);
     }
 
     @Test
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java	Mon Mar 23 00:26:47 2015 +0100
@@ -24,14 +24,25 @@
 
 import org.junit.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.runtime.*;
 
 public class ReplacementsParseTest extends GraalCompilerTest {
 
+    private static final Object THROW_EXCEPTION_MARKER = new Object() {
+        @Override
+        public String toString() {
+            return "THROW_EXCEPTION_MARKER";
+        }
+    };
+
     static class TestMethods {
         static double next(double v) {
             return Math.nextAfter(v, 1.0);
@@ -45,6 +56,14 @@
             return Math.nextAfter(x, d);
         }
 
+        static String stringize(Object obj) {
+            String res = String.valueOf(obj);
+            if (res.equals(THROW_EXCEPTION_MARKER.toString())) {
+                // Tests exception throwing from partial intrinsification
+                throw new RuntimeException("ex: " + obj);
+            }
+            return res;
+        }
     }
 
     @ClassSubstitution(TestMethods.class)
@@ -55,6 +74,23 @@
             double xx = (x == -0.0 ? 0.0 : x);
             return Math.nextAfter(xx, d);
         }
+
+        @MethodSubstitution
+        static String stringize(Object obj) {
+            if (obj != null && obj.getClass() == String.class) {
+                return asNonNullString(obj);
+            } else {
+                return stringize(obj);
+            }
+        }
+
+        public static String asNonNullString(Object object) {
+            return asNonNullStringIntrinsic(object, String.class, true, true);
+        }
+
+        @NodeIntrinsic(PiNode.class)
+        private static native String asNonNullStringIntrinsic(Object object, @ConstantNodeParameter Class<?> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull);
+
     }
 
     private static boolean substitutionsInstalled;
@@ -112,4 +148,23 @@
             outArray[i] = TestMethods.nextAfter(inArray[i], direction);
         }
     }
+
+    @Test
+    public void testCallStringize() {
+        test("callStringize", "a string");
+        test("callStringize", THROW_EXCEPTION_MARKER);
+        test("callStringize", Boolean.TRUE);
+    }
+
+    public Object callStringize(Object obj) {
+        return TestMethods.stringize(obj);
+    }
+
+    @Test
+    public void testRootCompileStringize() {
+        ResolvedJavaMethod method = getResolvedJavaMethod(TestMethods.class, "stringize");
+        test(method, null, "a string");
+        test(method, null, Boolean.TRUE);
+        test(method, null, THROW_EXCEPTION_MARKER);
+    }
 }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Mar 23 00:26:47 2015 +0100
@@ -45,7 +45,7 @@
 
     @Override
     protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) {
-        return installer.makeGraph(m, null, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect);
+        return installer.makeGraph(m, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect);
     }
 
     @Test
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Mon Mar 23 00:26:47 2015 +0100
@@ -32,141 +32,109 @@
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.type.*;
 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.util.*;
 import com.oracle.graal.phases.util.*;
-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 (method.isNative()) {
-                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)
+    @Snippet
     public static Object booleanValueOf(boolean value) {
         valueOfCounter.inc();
         return PiNode.piCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static Object byteValueOf(byte value) {
         valueOfCounter.inc();
         return PiNode.piCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static Object charValueOf(char value) {
         valueOfCounter.inc();
         return PiNode.piCast(Character.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static Object doubleValueOf(double value) {
         valueOfCounter.inc();
         return PiNode.piCast(Double.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static Object floatValueOf(float value) {
         valueOfCounter.inc();
         return PiNode.piCast(Float.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static Object intValueOf(int value) {
         valueOfCounter.inc();
         return PiNode.piCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static Object longValueOf(long value) {
         valueOfCounter.inc();
         return PiNode.piCast(Long.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static Object shortValueOf(short value) {
         valueOfCounter.inc();
         return PiNode.piCast(Short.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static boolean booleanValue(Boolean value) {
         valueOfCounter.inc();
         return value.booleanValue();
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static byte byteValue(Byte value) {
         valueOfCounter.inc();
         return value.byteValue();
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static char charValue(Character value) {
         valueOfCounter.inc();
         return value.charValue();
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static double doubleValue(Double value) {
         valueOfCounter.inc();
         return value.doubleValue();
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static float floatValue(Float value) {
         valueOfCounter.inc();
         return value.floatValue();
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static int intValue(Integer value) {
         valueOfCounter.inc();
         return value.intValue();
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static long longValue(Long value) {
         valueOfCounter.inc();
         return value.longValue();
     }
 
-    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    @Snippet
     public static short shortValue(Short value) {
         valueOfCounter.inc();
         return value.shortValue();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Mon Mar 23 00:26:47 2015 +0100
@@ -28,16 +28,21 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality;
 import com.oracle.graal.phases.common.inlining.*;
 import com.oracle.graal.phases.util.*;
-import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing;
 import com.oracle.graal.word.*;
 
 /**
@@ -50,6 +55,7 @@
     protected final Providers providers;
     protected final StructuredGraph graph;
     protected final WordTypes wordTypes;
+    protected final GraphBuilderConfiguration.Plugins graphBuilderPlugins;
     protected FixedWithNextNode lastFixedNode;
 
     private final List<Structure> structures;
@@ -57,10 +63,11 @@
     abstract static class Structure {
     }
 
-    public GraphKit(StructuredGraph graph, Providers providers, WordTypes wordTypes) {
+    public GraphKit(StructuredGraph graph, Providers providers, WordTypes wordTypes, GraphBuilderConfiguration.Plugins graphBuilderPlugins) {
         this.providers = providers;
         this.graph = graph;
         this.wordTypes = wordTypes;
+        this.graphBuilderPlugins = graphBuilderPlugins;
         this.lastFixedNode = graph.start();
 
         structures = new ArrayList<>();
@@ -202,14 +209,28 @@
     }
 
     /**
-     * Inlines a given invocation to a method. The graph of the inlined method is
-     * {@linkplain ReplacementsImpl#makeGraph processed} in the same manner as for snippets and
-     * method substitutions.
+     * Inlines a given invocation to a method. The graph of the inlined method is processed in the
+     * same manner as for snippets and method substitutions.
      */
     public void inline(InvokeNode invoke) {
         ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
-        ReplacementsImpl replacements = (ReplacementsImpl) providers.getReplacements();
-        StructuredGraph calleeGraph = replacements.makeGraph(method, null, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect);
+
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        Plugins plugins = new Plugins(graphBuilderPlugins);
+        GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
+
+        StructuredGraph calleeGraph = new StructuredGraph(method, AllowAssumptions.NO);
+        IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, null, IntrinsicContext.POST_PARSE_INLINE_BCI);
+        new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(calleeGraph);
+
+        // Remove all frame states from inlinee
+        for (Node node : calleeGraph.getNodes()) {
+            if (node instanceof StateSplit) {
+                ((StateSplit) node).setStateAfter(null);
+            }
+        }
+        new DeadCodeEliminationPhase(Optionality.Required).apply(calleeGraph);
+
         InliningUtil.inline(invoke, calleeGraph, false, null);
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Mar 23 00:26:47 2015 +0100
@@ -41,10 +41,11 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.graph.Graph.Mark;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.graphbuilderconf.*;
-import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext;
+import com.oracle.graal.java.AbstractBytecodeParser.ReplacementContext;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderPhase.Instance;
 import com.oracle.graal.nodes.*;
@@ -53,11 +54,8 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.inlining.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
-import com.oracle.graal.replacements.Snippet.DefaultSnippetInliningPolicy;
-import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
 
 public class ReplacementsImpl implements Replacements {
 
@@ -273,7 +271,7 @@
             try (DebugCloseable a = SnippetPreparationTime.start()) {
                 FrameStateProcessing frameStateProcessing = method.getAnnotation(Snippet.class).removeAllFrameStates() ? FrameStateProcessing.Removal
                                 : FrameStateProcessing.CollapseFrameForSingleSideEffect;
-                StructuredGraph newGraph = makeGraph(method, args, recursiveEntry, inliningPolicy(method), frameStateProcessing);
+                StructuredGraph newGraph = makeGraph(method, args, recursiveEntry, frameStateProcessing);
                 Debug.metric("SnippetNodeCount[%#s]", method).add(newGraph.getNodeCount());
                 if (!UseSnippetGraphCache || args != null) {
                     return newGraph;
@@ -313,7 +311,7 @@
         }
         StructuredGraph graph = graphs.get(substitute);
         if (graph == null) {
-            graph = makeGraph(substitute, null, original, inliningPolicy(substitute), FrameStateProcessing.None);
+            graph = makeGraph(substitute, null, original, FrameStateProcessing.None);
             graph.freeze();
             graphs.putIfAbsent(substitute, graph);
             graph = graphs.get(substitute);
@@ -424,26 +422,6 @@
         return originalJavaMethod;
     }
 
-    private static SnippetInliningPolicy createPolicyClassInstance(Class<? extends SnippetInliningPolicy> policyClass) {
-        try {
-            return policyClass.getConstructor().newInstance();
-        } catch (Exception e) {
-            throw new GraalInternalError(e);
-        }
-    }
-
-    public SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) {
-        Class<? extends SnippetInliningPolicy> policyClass = SnippetInliningPolicy.class;
-        Snippet snippet = method.getAnnotation(Snippet.class);
-        if (snippet != null) {
-            policyClass = snippet.inlining();
-        }
-        if (policyClass == SnippetInliningPolicy.class) {
-            return new DefaultSnippetInliningPolicy(providers.getMetaAccess());
-        }
-        return createPolicyClassInstance(policyClass);
-    }
-
     /**
      * Creates a preprocessed graph for a snippet or method substitution.
      *
@@ -451,11 +429,10 @@
      * @param args
      * @param original the original method if {@code method} is a {@linkplain MethodSubstitution
      *            substitution} otherwise null
-     * @param policy the inlining policy to use during preprocessing
      * @param frameStateProcessing controls how {@link FrameState FrameStates} should be handled.
      */
-    public StructuredGraph makeGraph(ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original, SnippetInliningPolicy policy, FrameStateProcessing frameStateProcessing) {
-        return createGraphMaker(method, original, frameStateProcessing).makeGraph(args, policy);
+    public StructuredGraph makeGraph(ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original, FrameStateProcessing frameStateProcessing) {
+        return createGraphMaker(method, original, frameStateProcessing).makeGraph(args);
     }
 
     /**
@@ -527,9 +504,9 @@
             this.frameStateProcessing = frameStateProcessing;
         }
 
-        public StructuredGraph makeGraph(Object[] args, final SnippetInliningPolicy policy) {
+        public StructuredGraph makeGraph(Object[] args) {
             try (Scope s = Debug.scope("BuildSnippetGraph", method)) {
-                StructuredGraph graph = parseGraph(method, args, policy, 0);
+                StructuredGraph graph = parseGraph(method, args);
 
                 if (args == null) {
                     // Cannot have a finalized version of a graph in the cache
@@ -603,14 +580,12 @@
             return false;
         }
 
-        private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough
-
-        private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, Object[] args, final SnippetInliningPolicy policy, int inliningDepth) {
+        private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, Object[] args) {
             StructuredGraph graph = args == null ? replacements.graphCache.get(methodToParse) : null;
             if (graph == null) {
                 StructuredGraph newGraph = null;
                 try (Scope s = Debug.scope("ParseGraph", methodToParse)) {
-                    newGraph = buildGraph(methodToParse, args, policy == null ? replacements.inliningPolicy(methodToParse) : policy, inliningDepth);
+                    newGraph = buildGraph(methodToParse, args);
                 } catch (Throwable e) {
                     throw Debug.handle(e);
                 }
@@ -662,8 +637,17 @@
 
         protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig,
                         OptimisticOptimizations optimisticOpts) {
-            ResolvedJavaMethod rootMethodIsReplacement = substitutedMethod == null ? method : substitutedMethod;
-            return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, graphBuilderConfig, optimisticOpts, rootMethodIsReplacement);
+            ReplacementContext initialReplacementContext = null;
+            if (method.getAnnotation(MethodSubstitution.class) != null) {
+                // Late inlined intrinsic
+                initialReplacementContext = new IntrinsicContext(substitutedMethod, method, null, -1);
+            } else {
+                // Snippet
+                assert method.getAnnotation(Snippet.class) != null;
+                ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method;
+                initialReplacementContext = new ReplacementContext(original, method);
+            }
+            return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, graphBuilderConfig, optimisticOpts, initialReplacementContext);
         }
 
         /**
@@ -700,67 +684,10 @@
             }
         }
 
-        private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, Object[] args, final SnippetInliningPolicy policy, int inliningDepth) {
-            assert inliningDepth < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded";
+        private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, Object[] args) {
             assert methodToParse.hasBytecodes() : methodToParse;
             final StructuredGraph graph = buildInitialGraph(methodToParse, args);
             try (Scope s = Debug.scope("buildGraph", graph)) {
-                Set<MethodCallTargetNode> doNotInline = null;
-                for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) {
-                    if (doNotInline != null && doNotInline.contains(callTarget)) {
-                        continue;
-                    }
-                    ResolvedJavaMethod callee = callTarget.targetMethod();
-                    if (substitutedMethod != null && (callee.equals(method) || callee.equals(substitutedMethod))) {
-                        /*
-                         * Ensure that calls to the original method inside of a substitution ends up
-                         * calling it instead of the Graal substitution.
-                         */
-                        if (substitutedMethod.hasBytecodes()) {
-                            final StructuredGraph originalGraph = buildInitialGraph(substitutedMethod, null);
-                            Mark mark = graph.getMark();
-                            InliningUtil.inline(callTarget.invoke(), originalGraph, true, null);
-                            for (MethodCallTargetNode inlinedCallTarget : graph.getNewNodes(mark).filter(MethodCallTargetNode.class)) {
-                                if (doNotInline == null) {
-                                    doNotInline = new HashSet<>();
-                                }
-                                // We do not want to do further inlining (now) for calls
-                                // in the original method as this can cause unlimited
-                                // recursive inlining given an eager inlining policy such
-                                // as DefaultSnippetInliningPolicy.
-                                doNotInline.add(inlinedCallTarget);
-                            }
-                            Debug.dump(graph, "after inlining %s", callee);
-                            afterInline(graph, originalGraph, null);
-                        }
-                    } else {
-                        Class<? extends FixedWithNextNode> macroNodeClass = InliningUtil.getMacroNodeClass(replacements, callee);
-                        if (macroNodeClass != null) {
-                            InliningUtil.inlineMacroNode(callTarget.invoke(), callee, macroNodeClass);
-                        } else {
-                            StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(replacements, callee);
-                            if (callTarget.invokeKind().isDirect() && (policy.shouldInline(callee, methodToParse) || (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)))) {
-                                StructuredGraph targetGraph;
-                                if (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)) {
-                                    targetGraph = intrinsicGraph;
-                                } else {
-                                    if (callee.getName().startsWith("$jacoco")) {
-                                        throw new GraalInternalError("Parsing call to JaCoCo instrumentation method " + callee.format("%H.%n(%p)") + " from " + methodToParse.format("%H.%n(%p)") +
-                                                        " while preparing replacement " + method.format("%H.%n(%p)") + ". Placing \"//JaCoCo Exclude\" anywhere in " +
-                                                        methodToParse.getDeclaringClass().getSourceFileName() + " should fix this.");
-                                    }
-                                    targetGraph = parseGraph(callee, null, policy, inliningDepth + 1);
-                                }
-                                Object beforeInlineData = beforeInline(callTarget, targetGraph);
-                                InliningUtil.inline(callTarget.invoke(), targetGraph, true, null);
-                                Debug.dump(graph, "after inlining %s", callee);
-                                afterInline(graph, targetGraph, beforeInlineData);
-                            }
-                        }
-                    }
-                }
-
-                afterInlining(graph);
 
                 for (LoopEndNode end : graph.getNodes(LoopEndNode.TYPE)) {
                     end.disableSafepoint();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Mon Mar 23 00:26:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Mon Mar 23 00:26:47 2015 +0100
@@ -24,11 +24,7 @@
 
 import java.lang.annotation.*;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.replacements.nodes.*;
-import com.oracle.graal.word.*;
 
 /**
  * A snippet is a Graal graph expressed as a Java source method. Snippets are used for lowering
@@ -39,12 +35,6 @@
 public @interface Snippet {
 
     /**
-     * Specifies the class defining the inlining policy for this snippet. A
-     * {@linkplain DefaultSnippetInliningPolicy default} policy is used if none is supplied.
-     */
-    Class<? extends SnippetInliningPolicy> inlining() default SnippetInliningPolicy.class;
-
-    /**
      * Specifies whether all FrameStates within this snippet should always be removed. If this is
      * false, FrameStates are only removed if there are no side-effecting instructions in the
      * snippet.
@@ -52,70 +42,6 @@
     boolean removeAllFrameStates() default false;
 
     /**
-     * Guides inlining decisions used when installing a snippet.
-     */
-    public interface SnippetInliningPolicy {
-
-        /**
-         * Determines if {@code method} should be inlined into {@code caller}.
-         */
-        boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller);
-
-        /**
-         * Determines if {@code method} should be inlined using its replacement graph.
-         *
-         * @return true if the replacement graph should be used, false for normal inlining.
-         */
-        boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse);
-    }
-
-    /**
-     * The default inlining policy which inlines everything except for methods in any of the
-     * following categories.
-     * <ul>
-     * <li>{@linkplain Fold foldable} methods</li>
-     * <li>{@linkplain NodeIntrinsic node intrinsics}</li>
-     * <li>native methods</li>
-     * <li>constructors of {@link Throwable} classes</li>
-     * </ul>
-     */
-    public static class DefaultSnippetInliningPolicy implements SnippetInliningPolicy {
-
-        private final MetaAccessProvider metaAccess;
-
-        public DefaultSnippetInliningPolicy(MetaAccessProvider metaAccess) {
-            this.metaAccess = metaAccess;
-        }
-
-        @Override
-        public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
-            if (method.isNative()) {
-                return false;
-            }
-            if (method.getAnnotation(Fold.class) != null) {
-                return false;
-            }
-            if (method.getAnnotation(NodeIntrinsic.class) != null) {
-                return false;
-            }
-            if (metaAccess.lookupJavaType(Throwable.class).isAssignableFrom(method.getDeclaringClass())) {
-                if (method.isConstructor()) {
-                    return false;
-                }
-            }
-            if (method.getAnnotation(Word.Operation.class) != null) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) {
-            return true;
-        }
-    }
-
-    /**
      * 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
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Mon Mar 23 00:26:37 2015 +0100
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Mon Mar 23 00:26:47 2015 +0100
@@ -1,5 +1,5 @@
 colorize("name", ".*", white);
-colorize("name", "Begin|EndNode|LoopBegin|LoopEnd|LoopExit|Return", orange);
+colorize("name", "Begin|KillingBegin|EndNode|LoopBegin|LoopEnd|LoopExit|Return", orange);
 colorize("name", "Phi.*|ValueProxy", magenta);
 colorize("name", "FrameState@.*", new java.awt.Color(0.5, 0.8, 1.0));
 colorize("name", "If|Merge", pink);