changeset 21357:acfc5e32e678

Merge with 6d5a198d23e67bb4b850ce1d74f5c338840cfe04
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Tue, 12 May 2015 18:04:53 -0700
parents e34bc00733d1 (current diff) 6d5a198d23e6 (diff)
children 19801a65cf57
files graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java
diffstat 14 files changed, 1173 insertions(+), 1389 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue May 12 18:04:53 2015 -0700
@@ -52,15 +52,7 @@
 import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.StrategySwitchOp;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp;
-import com.oracle.graal.lir.sparc.SPARCMove.LoadAddressOp;
-import com.oracle.graal.lir.sparc.SPARCMove.LoadDataAddressOp;
-import com.oracle.graal.lir.sparc.SPARCMove.MembarOp;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGp;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGpVIS3;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp;
-import com.oracle.graal.lir.sparc.SPARCMove.SPARCStackMove;
-import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp;
+import com.oracle.graal.lir.sparc.SPARCMove.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.sparc.*;
 import com.oracle.graal.sparc.SPARC.CPUFeature;
@@ -1074,4 +1066,11 @@
         append(new ReturnOp(Value.ILLEGAL));
     }
 
+    public Value emitSignExtendLoad(LIRKind kind, Value address, LIRFrameState state) {
+        SPARCAddressValue loadAddress = asAddressValue(address);
+        Variable result = newVariable(kind);
+        append(new LoadOp((Kind) kind.getPlatformKind(), result, loadAddress, state, true));
+        return result;
+    }
+
 }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Tue May 12 18:04:53 2015 -0700
@@ -29,7 +29,7 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.match.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.*;
@@ -106,7 +106,7 @@
         Kind localToKind = toKind;
         return builder -> {
             Value address = access.accessLocation().generateAddress(builder, gen, operand(access.object()));
-            Value v = getLIRGeneratorTool().emitLoad(LIRKind.value(localFromKind), address, getState(access));
+            Value v = getLIRGeneratorTool().emitSignExtendLoad(LIRKind.value(localFromKind), address, getState(access));
             return getLIRGeneratorTool().emitReinterpret(LIRKind.value(localToKind), v);
         };
     }
@@ -116,4 +116,9 @@
     public ComplexMatchResult signExtend(SignExtendNode root, Access access) {
         return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits());
     }
+
+    @Override
+    public SPARCLIRGenerator getLIRGeneratorTool() {
+        return (SPARCLIRGenerator) super.getLIRGeneratorTool();
+    }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java	Tue May 12 18:04:53 2015 -0700
@@ -28,26 +28,29 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Annul;
 import com.oracle.graal.asm.sparc.SPARCAssembler.BranchPredict;
 import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
 import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
 import com.oracle.graal.asm.sparc.SPARCAssembler.RCondition;
-import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.sparc.*;
 
 public class SPARCHotSpotMove {
 
     public static final class HotSpotLoadConstantOp extends SPARCLIRInstruction implements MoveOp {
         public static final LIRInstructionClass<HotSpotLoadConstantOp> TYPE = LIRInstructionClass.create(HotSpotLoadConstantOp.class);
 
-        @Def({REG}) private AllocatableValue result;
+        @Def({REG, STACK}) private AllocatableValue result;
         private final JavaConstant input;
 
         public HotSpotLoadConstantOp(AllocatableValue result, JavaConstant input) {
@@ -58,43 +61,74 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            assert isRegister(result);
-            if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(input)) {
-                masm.mov(0, asRegister(result));
-            } else if (input instanceof HotSpotObjectConstant) {
-                boolean compressed = ((HotSpotObjectConstant) input).isCompressed();
+            if (isStackSlot(result)) {
+                StackSlot ss = asStackSlot(result);
+                try (ScratchRegister s1 = masm.getScratchRegister()) {
+                    Register sr1 = s1.getRegister();
+                    loadToRegister(crb, masm, sr1.asValue(), input);
+                    try (ScratchRegister s2 = masm.getScratchRegister()) {
+                        Register sr2 = s2.getRegister();
+                        int stackBias = HotSpotGraalRuntime.runtime().getConfig().stackBias;
+                        int offset = crb.frameMap.offsetForStackSlot(ss);
+                        new SPARCMacroAssembler.Setx(offset + stackBias, sr2).emit(masm);
+                        SPARCAddress addr = new SPARCAddress(SPARC.sp, sr2);
+                        Kind resultKind = (Kind) result.getPlatformKind();
+                        switch (resultKind) {
+                            case Int:
+                                masm.stw(sr1, addr);
+                                break;
+                            case Long:
+                            case Object:
+                                masm.stx(sr1, addr);
+                                break;
+                            default:
+                                throw GraalInternalError.shouldNotReachHere();
+                        }
+                    }
+                }
+            } else {
+                loadToRegister(crb, masm, result, input);
+            }
+        }
+
+        private static void loadToRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, AllocatableValue dest, JavaConstant constant) {
+            assert isRegister(dest);
+            if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(constant)) {
+                masm.mov(0, asRegister(dest));
+            } else if (constant instanceof HotSpotObjectConstant) {
+                boolean compressed = ((HotSpotObjectConstant) constant).isCompressed();
                 if (crb.target.inlineObjects) {
-                    crb.recordInlineDataInCode(input);
+                    crb.recordInlineDataInCode(constant);
                     if (compressed) {
-                        masm.sethi(0xDEADDEAD >>> 10, asRegister(result));
-                        masm.add(asRegister(result), 0xAD & 0x3F, asRegister(result));
+                        masm.sethi(0xDEADDEAD >>> 10, asRegister(dest));
+                        masm.add(asRegister(dest), 0xAD & 0x3F, asRegister(dest));
                     } else {
-                        new SPARCMacroAssembler.Setx(0xDEADDEADDEADDEADL, asRegister(result), true).emit(masm);
+                        new SPARCMacroAssembler.Setx(0xDEADDEADDEADDEADL, asRegister(dest), true).emit(masm);
                     }
                 } else {
                     GraalInternalError.unimplemented();
                 }
-            } else if (input instanceof HotSpotMetaspaceConstant) {
-                assert input.getKind() == Kind.Int || input.getKind() == Kind.Long;
-                boolean compressed = input.getKind() == Kind.Int;
+            } else if (constant instanceof HotSpotMetaspaceConstant) {
+                assert constant.getKind() == Kind.Int || constant.getKind() == Kind.Long;
+                boolean compressed = constant.getKind() == Kind.Int;
                 boolean isImmutable = GraalOptions.ImmutableCode.getValue();
                 boolean generatePIC = GraalOptions.GeneratePIC.getValue();
-                crb.recordInlineDataInCode(input);
+                crb.recordInlineDataInCode(constant);
                 if (compressed) {
                     if (isImmutable && generatePIC) {
                         GraalInternalError.unimplemented();
                     } else {
-                        new SPARCMacroAssembler.Setx(input.asInt(), asRegister(result), true).emit(masm);
+                        new SPARCMacroAssembler.Setx(constant.asInt(), asRegister(dest), true).emit(masm);
                     }
                 } else {
                     if (isImmutable && generatePIC) {
                         GraalInternalError.unimplemented();
                     } else {
-                        new SPARCMacroAssembler.Setx(input.asLong(), asRegister(result), true).emit(masm);
+                        new SPARCMacroAssembler.Setx(constant.asLong(), asRegister(dest), true).emit(masm);
                     }
                 }
             } else {
-                SPARCMove.move(crb, masm, result, input, SPARCDelayedControlTransfer.DUMMY);
+                SPARCMove.move(crb, masm, dest, constant, SPARCDelayedControlTransfer.DUMMY);
             }
         }
 
@@ -171,8 +205,7 @@
 
             Register resReg = asRegister(result);
             if (encoding.shift != 0) {
-                masm.sllx(resReg, 32, resReg);
-                masm.srlx(resReg, 32 - encoding.shift, resReg);
+                masm.sll(resReg, encoding.shift, resReg);
             }
 
             if (encoding.base != 0) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Tue May 12 17:29:49 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1260 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.java;
-
-import static com.oracle.graal.api.code.TypeCheckHints.*;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
-import static com.oracle.graal.bytecode.Bytecodes.*;
-import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.bytecode.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.calc.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graphbuilderconf.*;
-import com.oracle.graal.java.BciBlockMapping.BciBlock;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.options.*;
-import com.oracle.graal.phases.*;
-
-public abstract class AbstractBytecodeParser {
-
-    public static class Options {
-        // @formatter:off
-        @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug)
-        public static final OptionValue<Integer> TraceBytecodeParserLevel = new OptionValue<>(0);
-
-        @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert)
-        public static final StableOptionValue<Boolean> InlineDuringParsing = new StableOptionValue<>(false);
-
-        @Option(help = "Inlines intrinsic methods during bytecode parsing.", type = OptionType.Expert)
-        public static final StableOptionValue<Boolean> InlineIntrinsicsDuringParsing = new StableOptionValue<>(true);
-
-        @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug)
-        public static final StableOptionValue<Boolean> TraceInlineDuringParsing = new StableOptionValue<>(false);
-
-        @Option(help = "Traces use of plugins during bytecode parsing.", type = OptionType.Debug)
-        public static final StableOptionValue<Boolean> TraceParserPlugins = new StableOptionValue<>(false);
-
-        @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug)
-        public static final StableOptionValue<Integer> InlineDuringParsingMaxDepth = new StableOptionValue<>(10);
-
-        @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug)
-        public static final StableOptionValue<Boolean> DumpDuringGraphBuilding = new StableOptionValue<>(false);
-
-        @Option(help = "Max number of loop explosions per method.", type = OptionType.Debug)
-        public static final OptionValue<Integer> MaximumLoopExplosionCount = new OptionValue<>(10000);
-
-        @Option(help = "Do not bail out but throw an exception on failed loop explosion.", type = OptionType.Debug)
-        public static final OptionValue<Boolean> FailedLoopExplosionIsFatal = new OptionValue<>(false);
-
-        @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug)
-        public static final OptionValue<Boolean> HideSubstitutionStates = new OptionValue<>(false);
-
-        // @formatter:on
-    }
-
-    /**
-     * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the
-     * bytecode instructions as they are parsed.
-     */
-    public static final int TRACELEVEL_INSTRUCTIONS = 1;
-
-    /**
-     * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the
-     * frame state before each bytecode instruction as it is parsed.
-     */
-    public static final int TRACELEVEL_STATE = 2;
-
-    protected HIRFrameStateBuilder frameState;
-    protected BciBlock currentBlock;
-
-    protected final BytecodeStream stream;
-    protected final GraphBuilderConfiguration graphBuilderConfig;
-    protected final ResolvedJavaMethod method;
-    protected final ProfilingInfo profilingInfo;
-    protected final OptimisticOptimizations optimisticOpts;
-    protected final ConstantPool constantPool;
-    protected final MetaAccessProvider metaAccess;
-
-    protected final IntrinsicContext intrinsicContext;
-
-    /**
-     * Meters the number of actual bytecodes parsed.
-     */
-    public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed");
-
-    public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts,
-                    IntrinsicContext intrinsicContext) {
-        this.graphBuilderConfig = graphBuilderConfig;
-        this.optimisticOpts = optimisticOpts;
-        this.metaAccess = metaAccess;
-        this.stream = new BytecodeStream(method.getCode());
-        this.profilingInfo = (graphBuilderConfig.getUseProfiling() ? method.getProfilingInfo() : null);
-        this.constantPool = method.getConstantPool();
-        this.method = method;
-        this.intrinsicContext = intrinsicContext;
-        assert metaAccess != null;
-    }
-
-    public void setCurrentFrameState(HIRFrameStateBuilder frameState) {
-        this.frameState = frameState;
-    }
-
-    protected final BytecodeStream getStream() {
-        return stream;
-    }
-
-    public int bci() {
-        return stream.currentBCI();
-    }
-
-    public void loadLocal(int index, Kind kind) {
-        frameState.push(kind, frameState.loadLocal(index));
-    }
-
-    public void storeLocal(Kind kind, int index) {
-        ValueNode value;
-        if (kind == Kind.Object) {
-            value = frameState.xpop();
-            // astore and astore_<n> may be used to store a returnAddress (jsr)
-            assert parsingIntrinsic() || (value.getKind() == Kind.Object || value.getKind() == Kind.Int) : value + ":" + value.getKind();
-        } else {
-            value = frameState.pop(kind);
-        }
-        frameState.storeLocal(index, value, kind);
-    }
-
-    /**
-     * @param type the unresolved type of the constant
-     */
-    protected abstract void handleUnresolvedLoadConstant(JavaType type);
-
-    /**
-     * @param type the unresolved type of the type check
-     * @param object the object value whose type is being checked against {@code type}
-     */
-    protected abstract void handleUnresolvedCheckCast(JavaType type, ValueNode object);
-
-    /**
-     * @param type the unresolved type of the type check
-     * @param object the object value whose type is being checked against {@code type}
-     */
-    protected abstract void handleUnresolvedInstanceOf(JavaType type, ValueNode object);
-
-    /**
-     * @param type the type being instantiated
-     */
-    protected abstract void handleUnresolvedNewInstance(JavaType type);
-
-    /**
-     * @param type the type of the array being instantiated
-     * @param length the length of the array
-     */
-    protected abstract void handleUnresolvedNewObjectArray(JavaType type, ValueNode length);
-
-    /**
-     * @param type the type being instantiated
-     * @param dims the dimensions for the multi-array
-     */
-    protected abstract void handleUnresolvedNewMultiArray(JavaType type, List<ValueNode> dims);
-
-    /**
-     * @param field the unresolved field
-     * @param receiver the object containing the field or {@code null} if {@code field} is static
-     */
-    protected abstract void handleUnresolvedLoadField(JavaField field, ValueNode receiver);
-
-    /**
-     * @param field the unresolved field
-     * @param value the value being stored to the field
-     * @param receiver the object containing the field or {@code null} if {@code field} is static
-     */
-    protected abstract void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver);
-
-    /**
-     * @param type
-     */
-    protected abstract void handleUnresolvedExceptionType(JavaType type);
-
-    // protected abstract void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind);
-
-    // protected abstract DispatchBeginNode handleException(ValueNode exceptionObject, int bci);
-
-    private void genLoadConstant(int cpi, int opcode) {
-        Object con = lookupConstant(cpi, opcode);
-
-        if (con instanceof JavaType) {
-            // this is a load of class constant which might be unresolved
-            JavaType type = (JavaType) con;
-            if (type instanceof ResolvedJavaType) {
-                frameState.push(Kind.Object, appendConstant(((ResolvedJavaType) type).getJavaClass()));
-            } else {
-                handleUnresolvedLoadConstant(type);
-            }
-        } else if (con instanceof JavaConstant) {
-            JavaConstant constant = (JavaConstant) con;
-            frameState.push(constant.getKind().getStackKind(), appendConstant(constant));
-        } else {
-            throw new Error("lookupConstant returned an object of incorrect type");
-        }
-    }
-
-    protected abstract ValueNode genLoadIndexed(ValueNode index, ValueNode array, Kind kind);
-
-    private void genLoadIndexed(Kind kind) {
-        ValueNode index = frameState.ipop();
-        ValueNode array = emitExplicitExceptions(frameState.apop(), index);
-        if (!tryLoadIndexedPlugin(kind, index, array)) {
-            frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind)));
-        }
-    }
-
-    protected abstract void traceWithContext(String format, Object... args);
-
-    protected boolean tryLoadIndexedPlugin(Kind kind, ValueNode index, ValueNode array) {
-        LoadIndexedPlugin loadIndexedPlugin = graphBuilderConfig.getPlugins().getLoadIndexedPlugin();
-        if (loadIndexedPlugin != null && loadIndexedPlugin.apply((GraphBuilderContext) this, array, index, kind)) {
-            if (TraceParserPlugins.getValue()) {
-                traceWithContext("used load indexed plugin");
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    protected abstract void genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value);
-
-    private void genStoreIndexed(Kind kind) {
-        ValueNode value = frameState.pop(kind.getStackKind());
-        ValueNode index = frameState.ipop();
-        ValueNode array = emitExplicitExceptions(frameState.apop(), index);
-        genStoreIndexed(array, index, kind, value);
-    }
-
-    private void stackOp(int opcode) {
-        switch (opcode) {
-            case DUP_X1: {
-                ValueNode w1 = frameState.xpop();
-                ValueNode w2 = frameState.xpop();
-                frameState.xpush(w1);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case DUP_X2: {
-                ValueNode w1 = frameState.xpop();
-                ValueNode w2 = frameState.xpop();
-                ValueNode w3 = frameState.xpop();
-                frameState.xpush(w1);
-                frameState.xpush(w3);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case DUP2: {
-                ValueNode w1 = frameState.xpop();
-                ValueNode w2 = frameState.xpop();
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case DUP2_X1: {
-                ValueNode w1 = frameState.xpop();
-                ValueNode w2 = frameState.xpop();
-                ValueNode w3 = frameState.xpop();
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                frameState.xpush(w3);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case DUP2_X2: {
-                ValueNode w1 = frameState.xpop();
-                ValueNode w2 = frameState.xpop();
-                ValueNode w3 = frameState.xpop();
-                ValueNode w4 = frameState.xpop();
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                frameState.xpush(w4);
-                frameState.xpush(w3);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case SWAP: {
-                ValueNode w1 = frameState.xpop();
-                ValueNode w2 = frameState.xpop();
-                frameState.xpush(w1);
-                frameState.xpush(w2);
-                break;
-            }
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    protected abstract ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
-
-    protected abstract ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
-
-    protected abstract ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
-
-    protected abstract ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
-
-    protected abstract ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
-
-    private void genArithmeticOp(Kind result, int opcode) {
-        ValueNode y = frameState.pop(result);
-        ValueNode x = frameState.pop(result);
-        boolean isStrictFP = method.isStrict();
-        ValueNode v;
-        switch (opcode) {
-            case IADD:
-            case LADD:
-                v = genIntegerAdd(result, x, y);
-                break;
-            case FADD:
-            case DADD:
-                v = genFloatAdd(result, x, y, isStrictFP);
-                break;
-            case ISUB:
-            case LSUB:
-                v = genIntegerSub(result, x, y);
-                break;
-            case FSUB:
-            case DSUB:
-                v = genFloatSub(result, x, y, isStrictFP);
-                break;
-            case IMUL:
-            case LMUL:
-                v = genIntegerMul(result, x, y);
-                break;
-            case FMUL:
-            case DMUL:
-                v = genFloatMul(result, x, y, isStrictFP);
-                break;
-            case FDIV:
-            case DDIV:
-                v = genFloatDiv(result, x, y, isStrictFP);
-                break;
-            case FREM:
-            case DREM:
-                v = genFloatRem(result, x, y, isStrictFP);
-                break;
-            default:
-                throw new GraalInternalError("should not reach");
-        }
-        frameState.push(result, append(v));
-    }
-
-    protected abstract ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y);
-
-    private void genIntegerDivOp(Kind result, int opcode) {
-        ValueNode y = frameState.pop(result);
-        ValueNode x = frameState.pop(result);
-        ValueNode v;
-        switch (opcode) {
-            case IDIV:
-            case LDIV:
-                v = genIntegerDiv(result, x, y);
-                break;
-            case IREM:
-            case LREM:
-                v = genIntegerRem(result, x, y);
-                break;
-            default:
-                throw new GraalInternalError("should not reach");
-        }
-        frameState.push(result, append(v));
-    }
-
-    protected abstract ValueNode genNegateOp(ValueNode x);
-
-    private void genNegateOp(Kind kind) {
-        frameState.push(kind, append(genNegateOp(frameState.pop(kind))));
-    }
-
-    protected abstract ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y);
-
-    private void genShiftOp(Kind kind, int opcode) {
-        ValueNode s = frameState.ipop();
-        ValueNode x = frameState.pop(kind);
-        ValueNode v;
-        switch (opcode) {
-            case ISHL:
-            case LSHL:
-                v = genLeftShift(kind, x, s);
-                break;
-            case ISHR:
-            case LSHR:
-                v = genRightShift(kind, x, s);
-                break;
-            case IUSHR:
-            case LUSHR:
-                v = genUnsignedRightShift(kind, x, s);
-                break;
-            default:
-                throw new GraalInternalError("should not reach");
-        }
-        frameState.push(kind, append(v));
-    }
-
-    protected abstract ValueNode genAnd(Kind kind, ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genOr(Kind kind, ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genXor(Kind kind, ValueNode x, ValueNode y);
-
-    private void genLogicOp(Kind kind, int opcode) {
-        ValueNode y = frameState.pop(kind);
-        ValueNode x = frameState.pop(kind);
-        ValueNode v;
-        switch (opcode) {
-            case IAND:
-            case LAND:
-                v = genAnd(kind, x, y);
-                break;
-            case IOR:
-            case LOR:
-                v = genOr(kind, x, y);
-                break;
-            case IXOR:
-            case LXOR:
-                v = genXor(kind, x, y);
-                break;
-            default:
-                throw new GraalInternalError("should not reach");
-        }
-        frameState.push(kind, append(v));
-    }
-
-    protected abstract ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess);
-
-    private void genCompareOp(Kind kind, boolean isUnorderedLess) {
-        ValueNode y = frameState.pop(kind);
-        ValueNode x = frameState.pop(kind);
-        frameState.ipush(append(genNormalizeCompare(x, y, isUnorderedLess)));
-    }
-
-    protected abstract ValueNode genFloatConvert(FloatConvert op, ValueNode input);
-
-    private void genFloatConvert(FloatConvert op, Kind from, Kind to) {
-        ValueNode input = frameState.pop(from.getStackKind());
-        frameState.push(to.getStackKind(), append(genFloatConvert(op, input)));
-    }
-
-    protected abstract ValueNode genNarrow(ValueNode input, int bitCount);
-
-    protected abstract ValueNode genSignExtend(ValueNode input, int bitCount);
-
-    protected abstract ValueNode genZeroExtend(ValueNode input, int bitCount);
-
-    private void genSignExtend(Kind from, Kind to) {
-        ValueNode input = frameState.pop(from.getStackKind());
-        if (from != from.getStackKind()) {
-            input = append(genNarrow(input, from.getBitCount()));
-        }
-        frameState.push(to.getStackKind(), append(genSignExtend(input, to.getBitCount())));
-    }
-
-    private void genZeroExtend(Kind from, Kind to) {
-        ValueNode input = frameState.pop(from.getStackKind());
-        if (from != from.getStackKind()) {
-            input = append(genNarrow(input, from.getBitCount()));
-        }
-        frameState.push(to.getStackKind(), append(genZeroExtend(input, to.getBitCount())));
-    }
-
-    private void genNarrow(Kind from, Kind to) {
-        ValueNode input = frameState.pop(from.getStackKind());
-        frameState.push(to.getStackKind(), append(genNarrow(input, to.getBitCount())));
-    }
-
-    private void genIncrement() {
-        int index = getStream().readLocalIndex();
-        int delta = getStream().readIncrement();
-        ValueNode x = frameState.loadLocal(index);
-        ValueNode y = appendConstant(JavaConstant.forInt(delta));
-        frameState.storeLocal(index, append(genIntegerAdd(Kind.Int, x, y)));
-    }
-
-    protected abstract void genGoto();
-
-    protected abstract ValueNode genObjectEquals(ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genIntegerEquals(ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genIntegerLessThan(ValueNode x, ValueNode y);
-
-    protected abstract ValueNode genUnique(ValueNode x);
-
-    protected abstract void genIf(ValueNode x, Condition cond, ValueNode y);
-
-    private void genIfZero(Condition cond) {
-        ValueNode y = appendConstant(JavaConstant.INT_0);
-        ValueNode x = frameState.ipop();
-        genIf(x, cond, y);
-    }
-
-    private void genIfNull(Condition cond) {
-        ValueNode y = appendConstant(JavaConstant.NULL_POINTER);
-        ValueNode x = frameState.apop();
-        genIf(x, cond, y);
-    }
-
-    private void genIfSame(Kind kind, Condition cond) {
-        ValueNode y = frameState.pop(kind);
-        ValueNode x = frameState.pop(kind);
-        genIf(x, cond, y);
-    }
-
-    protected abstract void genThrow();
-
-    protected JavaType lookupType(int cpi, int bytecode) {
-        maybeEagerlyResolve(cpi, bytecode);
-        JavaType result = constantPool.lookupType(cpi, bytecode);
-        assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
-        return result;
-    }
-
-    private JavaMethod lookupMethod(int cpi, int opcode) {
-        maybeEagerlyResolve(cpi, opcode);
-        JavaMethod result = constantPool.lookupMethod(cpi, opcode);
-        /*
-         * In general, one cannot assume that the declaring class being initialized is useful, since
-         * the actual concrete receiver may be a different class (except for static calls). Also,
-         * interfaces are initialized only under special circumstances, so that this assertion would
-         * often fail for interface calls.
-         */
-        assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaMethod && (opcode != INVOKESTATIC || ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized())) : result;
-        return result;
-    }
-
-    private JavaField lookupField(int cpi, int opcode) {
-        maybeEagerlyResolve(cpi, opcode);
-        JavaField result = constantPool.lookupField(cpi, opcode);
-        assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
-        return result;
-    }
-
-    private Object lookupConstant(int cpi, int opcode) {
-        maybeEagerlyResolve(cpi, opcode);
-        Object result = constantPool.lookupConstant(cpi);
-        assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType) : result;
-        return result;
-    }
-
-    private void maybeEagerlyResolve(int cpi, int bytecode) {
-        if (graphBuilderConfig.eagerResolving() || intrinsicContext != null) {
-            constantPool.loadReferencedType(cpi, bytecode);
-        }
-    }
-
-    private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) {
-        if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) {
-            return null;
-        } else {
-            return profilingInfo.getTypeProfile(bci());
-        }
-    }
-
-    protected abstract ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck);
-
-    private void genCheckCast() {
-        int cpi = getStream().readCPI();
-        JavaType type = lookupType(cpi, CHECKCAST);
-        ValueNode object = frameState.apop();
-        if (type instanceof ResolvedJavaType) {
-            ResolvedJavaType resolvedType = (ResolvedJavaType) type;
-            JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
-            TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin();
-            if (typeCheckPlugin == null || !typeCheckPlugin.checkCast((GraphBuilderContext) this, object, resolvedType, profile)) {
-                ValueNode checkCastNode = append(createCheckCast(resolvedType, object, profile, false));
-                frameState.apush(checkCastNode);
-            }
-        } else {
-            handleUnresolvedCheckCast(type, object);
-        }
-    }
-
-    protected abstract ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck);
-
-    protected abstract ValueNode genConditional(ValueNode x);
-
-    private void genInstanceOf() {
-        int cpi = getStream().readCPI();
-        JavaType type = lookupType(cpi, INSTANCEOF);
-        ValueNode object = frameState.apop();
-        if (type instanceof ResolvedJavaType) {
-            ResolvedJavaType resolvedType = (ResolvedJavaType) type;
-            JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
-            TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin();
-            if (typeCheckPlugin == null || !typeCheckPlugin.instanceOf((GraphBuilderContext) this, object, resolvedType, profile)) {
-                ValueNode instanceOfNode = createInstanceOf(resolvedType, object, profile);
-                frameState.ipush(append(genConditional(genUnique(instanceOfNode))));
-            }
-        } else {
-            handleUnresolvedInstanceOf(type, object);
-        }
-    }
-
-    protected abstract ValueNode createNewInstance(ResolvedJavaType type, boolean fillContents);
-
-    void genNewInstance(int cpi) {
-        JavaType type = lookupType(cpi, NEW);
-        if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) {
-            ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
-            if (skippedExceptionTypes != null) {
-                for (ResolvedJavaType exceptionType : skippedExceptionTypes) {
-                    if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) {
-                        append(new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter));
-                        return;
-                    }
-                }
-            }
-            frameState.apush(append(createNewInstance((ResolvedJavaType) type, true)));
-        } else {
-            handleUnresolvedNewInstance(type);
-        }
-    }
-
-    /**
-     * Gets the kind of array elements for the array type code that appears in a
-     * {@link Bytecodes#NEWARRAY} bytecode.
-     *
-     * @param code the array type code
-     * @return the kind from the array type code
-     */
-    public static Class<?> arrayTypeCodeToClass(int code) {
-        // Checkstyle: stop
-        switch (code) {
-            case 4:
-                return boolean.class;
-            case 5:
-                return char.class;
-            case 6:
-                return float.class;
-            case 7:
-                return double.class;
-            case 8:
-                return byte.class;
-            case 9:
-                return short.class;
-            case 10:
-                return int.class;
-            case 11:
-                return long.class;
-            default:
-                throw new IllegalArgumentException("unknown array type code: " + code);
-        }
-        // Checkstyle: resume
-    }
-
-    private void genNewPrimitiveArray(int typeCode) {
-        Class<?> clazz = arrayTypeCodeToClass(typeCode);
-        ResolvedJavaType elementType = metaAccess.lookupJavaType(clazz);
-        frameState.apush(append(createNewArray(elementType, frameState.ipop(), true)));
-    }
-
-    private void genNewObjectArray(int cpi) {
-        JavaType type = lookupType(cpi, ANEWARRAY);
-        ValueNode length = frameState.ipop();
-        if (type instanceof ResolvedJavaType) {
-            frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true)));
-        } else {
-            handleUnresolvedNewObjectArray(type, length);
-        }
-
-    }
-
-    protected abstract ValueNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents);
-
-    private void genNewMultiArray(int cpi) {
-        JavaType type = lookupType(cpi, MULTIANEWARRAY);
-        int rank = getStream().readUByte(bci() + 3);
-        List<ValueNode> dims = new ArrayList<>(Collections.nCopies(rank, null));
-        for (int i = rank - 1; i >= 0; i--) {
-            dims.set(i, frameState.ipop());
-        }
-        if (type instanceof ResolvedJavaType) {
-            frameState.apush(append(createNewMultiArray((ResolvedJavaType) type, dims)));
-        } else {
-            handleUnresolvedNewMultiArray(type, dims);
-        }
-    }
-
-    protected abstract ValueNode createNewMultiArray(ResolvedJavaType type, List<ValueNode> dims);
-
-    protected abstract ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field);
-
-    private void genGetField(JavaField field) {
-        Kind kind = field.getKind();
-        ValueNode receiver = emitExplicitExceptions(frameState.apop(), null);
-        if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
-            LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin();
-            if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, receiver, (ResolvedJavaField) field)) {
-                appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field));
-            }
-        } else {
-            handleUnresolvedLoadField(field, receiver);
-        }
-    }
-
-    /**
-     * Emits control flow to null check a receiver if it's stamp does not indicate it is
-     * {@linkplain StampTool#isPointerNonNull always non-null}.
-     *
-     * @return the receiver with a stamp indicating non-nullness
-     */
-    protected abstract ValueNode emitExplicitNullCheck(ValueNode receiver);
-
-    /**
-     * Emits control flow to check an array index is within bounds of an array's length.
-     *
-     * @param index the index to check
-     * @param length the length of the array being indexed
-     */
-    protected abstract void emitExplicitBoundsCheck(ValueNode index, ValueNode length);
-
-    private static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions");
-
-    protected abstract ValueNode genArrayLength(ValueNode x);
-
-    /**
-     * @param receiver the receiver of an object based operation
-     * @param index the index of an array based operation that is to be tested for out of bounds.
-     *            This is null for a non-array operation.
-     * @return the receiver value possibly modified to have a tighter stamp
-     */
-    protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) {
-        assert receiver != null;
-        if (graphBuilderConfig.omitAllExceptionEdges() || profilingInfo == null ||
-                        (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue())) {
-            return receiver;
-        }
-
-        ValueNode nonNullReceiver = emitExplicitNullCheck(receiver);
-        if (index != null) {
-            ValueNode length = append(genArrayLength(nonNullReceiver));
-            emitExplicitBoundsCheck(index, length);
-        }
-        EXPLICIT_EXCEPTIONS.increment();
-        return nonNullReceiver;
-    }
-
-    protected abstract void genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value);
-
-    private void genPutField(JavaField field) {
-        ValueNode value = frameState.pop(field.getKind().getStackKind());
-        ValueNode receiver = emitExplicitExceptions(frameState.apop(), null);
-        if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
-            genStoreField(receiver, (ResolvedJavaField) field, value);
-        } else {
-            handleUnresolvedStoreField(field, value, receiver);
-        }
-    }
-
-    private void genGetStatic(JavaField field) {
-        Kind kind = field.getKind();
-        if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
-            LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin();
-            if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) {
-                appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field));
-            }
-        } else {
-            handleUnresolvedLoadField(field, null);
-        }
-    }
-
-    public boolean tryLoadFieldPlugin(JavaField field, LoadFieldPlugin loadFieldPlugin) {
-        return loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field);
-    }
-
-    private void genPutStatic(JavaField field) {
-        ValueNode value = frameState.pop(field.getKind().getStackKind());
-        if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
-            genStoreField(null, (ResolvedJavaField) field, value);
-        } else {
-            handleUnresolvedStoreField(field, value, null);
-        }
-    }
-
-    protected void appendOptimizedLoadField(Kind kind, ValueNode load) {
-        // append the load to the instruction
-        ValueNode optimized = append(load);
-        frameState.push(kind.getStackKind(), optimized);
-    }
-
-    protected abstract void genInvokeStatic(JavaMethod target);
-
-    protected abstract void genInvokeInterface(JavaMethod target);
-
-    protected abstract void genInvokeDynamic(JavaMethod target);
-
-    protected abstract void genInvokeVirtual(JavaMethod target);
-
-    protected abstract void genInvokeSpecial(JavaMethod target);
-
-    protected abstract void genReturn(ValueNode x, Kind kind);
-
-    protected abstract void genMonitorEnter(ValueNode x, int bci);
-
-    protected abstract void genMonitorExit(ValueNode x, ValueNode returnValue, int bci);
-
-    protected abstract void genJsr(int dest);
-
-    protected abstract void genRet(int localIndex);
-
-    private double[] switchProbability(int numberOfCases, int bci) {
-        double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci));
-        if (prob != null) {
-            assert prob.length == numberOfCases;
-        } else {
-            Debug.log("Missing probability (switch) in %s at bci %d", method, bci);
-            prob = new double[numberOfCases];
-            for (int i = 0; i < numberOfCases; i++) {
-                prob[i] = 1.0d / numberOfCases;
-            }
-        }
-        assert allPositive(prob);
-        return prob;
-    }
-
-    private static boolean allPositive(double[] a) {
-        for (double d : a) {
-            if (d < 0) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Helper function that sums up the probabilities of all keys that lead to a specific successor.
-     *
-     * @return an array of size successorCount with the accumulated probability for each successor.
-     */
-    public static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
-        double[] probability = new double[successorCount];
-        for (int i = 0; i < keySuccessors.length; i++) {
-            probability[keySuccessors[i]] += keyProbabilities[i];
-        }
-        return probability;
-    }
-
-    private void genSwitch(BytecodeSwitch bs) {
-        int bci = bci();
-        ValueNode value = frameState.ipop();
-
-        int nofCases = bs.numberOfCases();
-        double[] keyProbabilities = switchProbability(nofCases + 1, bci);
-
-        Map<Integer, SuccessorInfo> bciToBlockSuccessorIndex = new HashMap<>();
-        for (int i = 0; i < currentBlock.getSuccessorCount(); i++) {
-            assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci);
-            if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) {
-                bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i));
-            }
-        }
-
-        ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
-        int[] keys = new int[nofCases];
-        int[] keySuccessors = new int[nofCases + 1];
-        int deoptSuccessorIndex = -1;
-        int nextSuccessorIndex = 0;
-        boolean constantValue = value.isConstant();
-        for (int i = 0; i < nofCases + 1; i++) {
-            if (i < nofCases) {
-                keys[i] = bs.keyAt(i);
-            }
-
-            if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
-                if (deoptSuccessorIndex < 0) {
-                    deoptSuccessorIndex = nextSuccessorIndex++;
-                    actualSuccessors.add(null);
-                }
-                keySuccessors[i] = deoptSuccessorIndex;
-            } else {
-                int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i);
-                SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
-                if (info.actualIndex < 0) {
-                    info.actualIndex = nextSuccessorIndex++;
-                    actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex));
-                }
-                keySuccessors[i] = info.actualIndex;
-            }
-        }
-
-        genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors);
-
-    }
-
-    protected abstract void genIntegerSwitch(ValueNode value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors);
-
-    private static class SuccessorInfo {
-
-        int blockIndex;
-        int actualIndex;
-
-        public SuccessorInfo(int blockSuccessorIndex) {
-            this.blockIndex = blockSuccessorIndex;
-            actualIndex = -1;
-        }
-    }
-
-    protected abstract ValueNode appendConstant(JavaConstant constant);
-
-    protected abstract <T extends ValueNode> T append(T v);
-
-    protected boolean isNeverExecutedCode(double probability) {
-        return probability == 0 && optimisticOpts.removeNeverExecutedCode();
-    }
-
-    protected double branchProbability() {
-        if (profilingInfo == null) {
-            return 0.5;
-        }
-        assert assertAtIfBytecode();
-        double probability = profilingInfo.getBranchTakenProbability(bci());
-        if (probability < 0) {
-            assert probability == -1 : "invalid probability";
-            Debug.log("missing probability in %s at bci %d", method, bci());
-            probability = 0.5;
-        }
-
-        if (!optimisticOpts.removeNeverExecutedCode()) {
-            if (probability == 0) {
-                probability = 0.0000001;
-            } else if (probability == 1) {
-                probability = 0.999999;
-            }
-        }
-        return probability;
-    }
-
-    private boolean assertAtIfBytecode() {
-        int bytecode = stream.currentBC();
-        switch (bytecode) {
-            case IFEQ:
-            case IFNE:
-            case IFLT:
-            case IFGE:
-            case IFGT:
-            case IFLE:
-            case IF_ICMPEQ:
-            case IF_ICMPNE:
-            case IF_ICMPLT:
-            case IF_ICMPGE:
-            case IF_ICMPGT:
-            case IF_ICMPLE:
-            case IF_ACMPEQ:
-            case IF_ACMPNE:
-            case IFNULL:
-            case IFNONNULL:
-                return true;
-        }
-        assert false : String.format("%x is not an if bytecode", bytecode);
-        return true;
-    }
-
-    protected abstract void iterateBytecodesForBlock(BciBlock block);
-
-    public final void processBytecode(int bci, int opcode) {
-        int cpi;
-
-        // 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
-        // Checkstyle: resume
-    }
-
-    private void genArrayLength() {
-        frameState.ipush(append(genArrayLength(frameState.apop())));
-    }
-
-    public ResolvedJavaMethod getMethod() {
-        return method;
-    }
-
-    public HIRFrameStateBuilder getFrameState() {
-        return frameState;
-    }
-
-    protected boolean traceInstruction(int bci, int opcode, boolean blockStart) {
-        if (Debug.isEnabled() && Options.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) {
-            traceInstructionHelper(bci, opcode, blockStart);
-        }
-        return true;
-    }
-
-    private void traceInstructionHelper(int bci, int opcode, boolean blockStart) {
-        StringBuilder sb = new StringBuilder(40);
-        sb.append(blockStart ? '+' : '|');
-        if (bci < 10) {
-            sb.append("  ");
-        } else if (bci < 100) {
-            sb.append(' ');
-        }
-        sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode));
-        for (int i = bci + 1; i < stream.nextBCI(); ++i) {
-            sb.append(' ').append(stream.readUByte(i));
-        }
-        if (!currentBlock.getJsrScope().isEmpty()) {
-            sb.append(' ').append(currentBlock.getJsrScope());
-        }
-        Debug.log("%s", sb);
-    }
-
-    public boolean parsingIntrinsic() {
-        return intrinsicContext != null;
-    }
-}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue May 12 18:04:53 2015 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.java;
 
+import static com.oracle.graal.api.code.TypeCheckHints.*;
 import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
@@ -29,7 +30,7 @@
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.compiler.common.type.StampFactory.*;
 import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.*;
-import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
+import static com.oracle.graal.java.GraphBuilderPhase.Options.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
 import static com.oracle.graal.nodes.type.StampTool.*;
 import static java.lang.String.*;
@@ -63,6 +64,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -71,6 +73,125 @@
  */
 public class GraphBuilderPhase extends BasePhase<HighTierContext> {
 
+    public static class Options {
+        // @formatter:off
+        @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug)
+        public static final OptionValue<Integer> TraceBytecodeParserLevel = new OptionValue<>(0);
+
+        @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert)
+        public static final StableOptionValue<Boolean> InlineDuringParsing = new StableOptionValue<>(false);
+
+        @Option(help = "Inlines intrinsic methods during bytecode parsing.", type = OptionType.Expert)
+        public static final StableOptionValue<Boolean> InlineIntrinsicsDuringParsing = new StableOptionValue<>(true);
+
+        @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug)
+        public static final StableOptionValue<Boolean> TraceInlineDuringParsing = new StableOptionValue<>(false);
+
+        @Option(help = "Traces use of plugins during bytecode parsing.", type = OptionType.Debug)
+        public static final StableOptionValue<Boolean> TraceParserPlugins = new StableOptionValue<>(false);
+
+        @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug)
+        public static final StableOptionValue<Integer> InlineDuringParsingMaxDepth = new StableOptionValue<>(10);
+
+        @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug)
+        public static final StableOptionValue<Boolean> DumpDuringGraphBuilding = new StableOptionValue<>(false);
+
+        @Option(help = "Max number of loop explosions per method.", type = OptionType.Debug)
+        public static final OptionValue<Integer> MaximumLoopExplosionCount = new OptionValue<>(10000);
+
+        @Option(help = "Do not bail out but throw an exception on failed loop explosion.", type = OptionType.Debug)
+        public static final OptionValue<Boolean> FailedLoopExplosionIsFatal = new OptionValue<>(false);
+
+        @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug)
+        public static final OptionValue<Boolean> HideSubstitutionStates = new OptionValue<>(false);
+
+        // @formatter:on
+    }
+
+    /**
+     * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the
+     * bytecode instructions as they are parsed.
+     */
+    public static final int TRACELEVEL_INSTRUCTIONS = 1;
+
+    /**
+     * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the
+     * frame state before each bytecode instruction as it is parsed.
+     */
+    public static final int TRACELEVEL_STATE = 2;
+
+    /**
+     * Meters the number of actual bytecodes parsed.
+     */
+    public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed");
+
+    /**
+     * Gets the kind of array elements for the array type code that appears in a
+     * {@link Bytecodes#NEWARRAY} bytecode.
+     *
+     * @param code the array type code
+     * @return the kind from the array type code
+     */
+    public static Class<?> arrayTypeCodeToClass(int code) {
+        // Checkstyle: stop
+        switch (code) {
+            case 4:
+                return boolean.class;
+            case 5:
+                return char.class;
+            case 6:
+                return float.class;
+            case 7:
+                return double.class;
+            case 8:
+                return byte.class;
+            case 9:
+                return short.class;
+            case 10:
+                return int.class;
+            case 11:
+                return long.class;
+            default:
+                throw new IllegalArgumentException("unknown array type code: " + code);
+        }
+        // Checkstyle: resume
+    }
+
+    protected static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions");
+
+    protected static boolean allPositive(double[] a) {
+        for (double d : a) {
+            if (d < 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Helper function that sums up the probabilities of all keys that lead to a specific successor.
+     *
+     * @return an array of size successorCount with the accumulated probability for each successor.
+     */
+    public static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
+        double[] probability = new double[successorCount];
+        for (int i = 0; i < keySuccessors.length; i++) {
+            probability[keySuccessors[i]] += keyProbabilities[i];
+        }
+        return probability;
+    }
+
+    static class SuccessorInfo {
+
+        int blockIndex;
+        int actualIndex;
+
+        public SuccessorInfo(int blockSuccessorIndex) {
+            this.blockIndex = blockSuccessorIndex;
+            actualIndex = -1;
+        }
+    }
+
     private final GraphBuilderConfiguration graphBuilderConfig;
 
     public GraphBuilderPhase(GraphBuilderConfiguration config) {
@@ -305,7 +426,7 @@
             }
         }
 
-        public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext {
+        public class BytecodeParser implements GraphBuilderContext {
 
             private BciBlockMapping blockMap;
             private LocalLiveness liveness;
@@ -339,7 +460,15 @@
 
             public BytecodeParser(BytecodeParser parent, MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig,
                             OptimisticOptimizations optimisticOpts, int entryBCI, IntrinsicContext intrinsicContext) {
-                super(metaAccess, method, graphBuilderConfig, optimisticOpts, intrinsicContext);
+                this.graphBuilderConfig = graphBuilderConfig;
+                this.optimisticOpts = optimisticOpts;
+                this.metaAccess = metaAccess;
+                this.stream = new BytecodeStream(method.getCode());
+                this.profilingInfo = (graphBuilderConfig.getUseProfiling() ? method.getProfilingInfo() : null);
+                this.constantPool = method.getConstantPool();
+                this.method = method;
+                this.intrinsicContext = intrinsicContext;
+                assert metaAccess != null;
                 this.entryBCI = entryBCI;
                 this.parent = parent;
 
@@ -743,7 +872,6 @@
             /**
              * @param type the unresolved type of the constant
              */
-            @Override
             protected void handleUnresolvedLoadConstant(JavaType type) {
                 assert !graphBuilderConfig.eagerResolving();
                 append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
@@ -753,7 +881,6 @@
              * @param type the unresolved type of the type check
              * @param object the object value whose type is being checked against {@code type}
              */
-            @Override
             protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) {
                 assert !graphBuilderConfig.eagerResolving();
                 append(new FixedGuardNode(graph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile));
@@ -764,7 +891,6 @@
              * @param type the unresolved type of the type check
              * @param object the object value whose type is being checked against {@code type}
              */
-            @Override
             protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) {
                 assert !graphBuilderConfig.eagerResolving();
                 AbstractBeginNode successor = graph.add(new BeginNode());
@@ -777,7 +903,6 @@
             /**
              * @param type the type being instantiated
              */
-            @Override
             protected void handleUnresolvedNewInstance(JavaType type) {
                 assert !graphBuilderConfig.eagerResolving();
                 append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
@@ -787,7 +912,6 @@
              * @param type the type of the array being instantiated
              * @param length the length of the array
              */
-            @Override
             protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) {
                 assert !graphBuilderConfig.eagerResolving();
                 append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
@@ -797,7 +921,6 @@
              * @param type the type being instantiated
              * @param dims the dimensions for the multi-array
              */
-            @Override
             protected void handleUnresolvedNewMultiArray(JavaType type, List<ValueNode> dims) {
                 assert !graphBuilderConfig.eagerResolving();
                 append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
@@ -808,7 +931,6 @@
              * @param receiver the object containing the field or {@code null} if {@code field} is
              *            static
              */
-            @Override
             protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) {
                 assert !graphBuilderConfig.eagerResolving();
                 append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
@@ -820,7 +942,6 @@
              * @param receiver the object containing the field or {@code null} if {@code field} is
              *            static
              */
-            @Override
             protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) {
                 assert !graphBuilderConfig.eagerResolving();
                 append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
@@ -829,7 +950,6 @@
             /**
              * @param type
              */
-            @Override
             protected void handleUnresolvedExceptionType(JavaType type) {
                 assert !graphBuilderConfig.eagerResolving();
                 append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
@@ -880,148 +1000,119 @@
                 return dispatchBegin;
             }
 
-            @Override
             protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, Kind kind) {
                 return LoadIndexedNode.create(array, index, kind, metaAccess, constantReflection);
             }
 
-            @Override
             protected void genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value) {
                 add(new StoreIndexedNode(array, index, kind, value));
             }
 
-            @Override
-            protected ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genIntegerAdd(ValueNode x, ValueNode y) {
                 return AddNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genIntegerSub(ValueNode x, ValueNode y) {
                 return SubNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genIntegerMul(ValueNode x, ValueNode y) {
                 return MulNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
+            protected ValueNode genFloatAdd(ValueNode x, ValueNode y) {
                 return AddNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
+            protected ValueNode genFloatSub(ValueNode x, ValueNode y) {
                 return SubNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
+            protected ValueNode genFloatMul(ValueNode x, ValueNode y) {
                 return MulNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
+            protected ValueNode genFloatDiv(ValueNode x, ValueNode y) {
                 return DivNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
+            protected ValueNode genFloatRem(ValueNode x, ValueNode y) {
                 return new RemNode(x, y);
             }
 
-            @Override
-            protected ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genIntegerDiv(ValueNode x, ValueNode y) {
                 return new IntegerDivNode(x, y);
             }
 
-            @Override
-            protected ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genIntegerRem(ValueNode x, ValueNode y) {
                 return new IntegerRemNode(x, y);
             }
 
-            @Override
             protected ValueNode genNegateOp(ValueNode x) {
                 return (new NegateNode(x));
             }
 
-            @Override
-            protected ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genLeftShift(ValueNode x, ValueNode y) {
                 return new LeftShiftNode(x, y);
             }
 
-            @Override
-            protected ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genRightShift(ValueNode x, ValueNode y) {
                 return new RightShiftNode(x, y);
             }
 
-            @Override
-            protected ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genUnsignedRightShift(ValueNode x, ValueNode y) {
                 return new UnsignedRightShiftNode(x, y);
             }
 
-            @Override
-            protected ValueNode genAnd(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genAnd(ValueNode x, ValueNode y) {
                 return AndNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genOr(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genOr(ValueNode x, ValueNode y) {
                 return OrNode.create(x, y);
             }
 
-            @Override
-            protected ValueNode genXor(Kind kind, ValueNode x, ValueNode y) {
+            protected ValueNode genXor(ValueNode x, ValueNode y) {
                 return XorNode.create(x, y);
             }
 
-            @Override
             protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) {
                 return NormalizeCompareNode.create(x, y, isUnorderedLess, constantReflection);
             }
 
-            @Override
             protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) {
                 return FloatConvertNode.create(op, input);
             }
 
-            @Override
             protected ValueNode genNarrow(ValueNode input, int bitCount) {
                 return NarrowNode.create(input, bitCount);
             }
 
-            @Override
             protected ValueNode genSignExtend(ValueNode input, int bitCount) {
                 return SignExtendNode.create(input, bitCount);
             }
 
-            @Override
             protected ValueNode genZeroExtend(ValueNode input, int bitCount) {
                 return ZeroExtendNode.create(input, bitCount);
             }
 
-            @Override
             protected void genGoto() {
                 appendGoto(currentBlock.getSuccessor(0));
                 assert currentBlock.numNormalSuccessors() == 1;
             }
 
-            @Override
             protected LogicNode genObjectEquals(ValueNode x, ValueNode y) {
                 return ObjectEqualsNode.create(x, y, constantReflection);
             }
 
-            @Override
             protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) {
                 return IntegerEqualsNode.create(x, y, constantReflection);
             }
 
-            @Override
             protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) {
                 return IntegerLessThanNode.create(x, y, constantReflection);
             }
 
-            @Override
             protected ValueNode genUnique(ValueNode x) {
                 return (ValueNode) graph.unique((Node & ValueNumberable) x);
             }
@@ -1030,49 +1121,40 @@
                 return new IfNode(condition, falseSuccessor, trueSuccessor, d);
             }
 
-            @Override
             protected void genThrow() {
                 ValueNode exception = frameState.apop();
                 append(new FixedGuardNode(graph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true));
                 lastInstr.setNext(handleException(exception, bci()));
             }
 
-            @Override
             protected ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck) {
                 return CheckCastNode.create(type, object, profileForTypeCheck, forStoreCheck, graph.getAssumptions());
             }
 
-            @Override
             protected ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck) {
                 return InstanceOfNode.create(type, object, profileForTypeCheck);
             }
 
-            @Override
             protected ValueNode genConditional(ValueNode x) {
                 return new ConditionalNode((LogicNode) x);
             }
 
-            @Override
             protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) {
                 return new NewInstanceNode(type, fillContents);
             }
 
-            @Override
             protected NewArrayNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents) {
                 return new NewArrayNode(elementType, length, fillContents);
             }
 
-            @Override
             protected NewMultiArrayNode createNewMultiArray(ResolvedJavaType type, List<ValueNode> dimensions) {
                 return new NewMultiArrayNode(type, dimensions.toArray(new ValueNode[0]));
             }
 
-            @Override
             protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) {
                 return new LoadFieldNode(receiver, field);
             }
 
-            @Override
             protected ValueNode emitExplicitNullCheck(ValueNode receiver) {
                 if (StampTool.isPointerNonNull(receiver.stamp())) {
                     return receiver;
@@ -1089,7 +1171,6 @@
                 return nonNullReceiver;
             }
 
-            @Override
             protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
                 AbstractBeginNode trueSucc = graph.add(new BeginNode());
                 BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
@@ -1100,12 +1181,10 @@
                 exception.setNext(handleException(exception, bci()));
             }
 
-            @Override
             protected ValueNode genArrayLength(ValueNode x) {
                 return ArrayLengthNode.create(x, constantReflection);
             }
 
-            @Override
             protected void genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value) {
                 StoreFieldNode storeFieldNode = new StoreFieldNode(receiver, field, value);
                 append(storeFieldNode);
@@ -1128,7 +1207,6 @@
                 return false;
             }
 
-            @Override
             protected void genInvokeStatic(JavaMethod target) {
                 if (callTargetIsResolved(target)) {
                     ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
@@ -1144,7 +1222,6 @@
                 }
             }
 
-            @Override
             protected void genInvokeInterface(JavaMethod target) {
                 if (callTargetIsResolved(target)) {
                     ValueNode[] args = frameState.popArguments(target.getSignature().getParameterCount(true));
@@ -1154,7 +1231,6 @@
                 }
             }
 
-            @Override
             protected void genInvokeDynamic(JavaMethod target) {
                 if (target instanceof ResolvedJavaMethod) {
                     JavaConstant appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC);
@@ -1168,7 +1244,6 @@
                 }
             }
 
-            @Override
             protected void genInvokeVirtual(JavaMethod target) {
                 if (callTargetIsResolved(target)) {
                     /*
@@ -1195,7 +1270,6 @@
 
             }
 
-            @Override
             protected void genInvokeSpecial(JavaMethod target) {
                 if (callTargetIsResolved(target)) {
                     assert target != null;
@@ -1209,6 +1283,16 @@
 
             private InvokeKind currentInvokeKind;
             private JavaType currentInvokeReturnType;
+            protected HIRFrameStateBuilder frameState;
+            protected BciBlock currentBlock;
+            protected final BytecodeStream stream;
+            protected final GraphBuilderConfiguration graphBuilderConfig;
+            protected final ResolvedJavaMethod method;
+            protected final ProfilingInfo profilingInfo;
+            protected final OptimisticOptimizations optimisticOpts;
+            protected final ConstantPool constantPool;
+            protected final MetaAccessProvider metaAccess;
+            protected final IntrinsicContext intrinsicContext;
 
             public InvokeKind getInvokeKind() {
                 return currentInvokeKind;
@@ -1466,7 +1550,7 @@
              * @param format a format string
              * @param args arguments to the format string
              */
-            @Override
+
             protected void traceWithContext(String format, Object... args) {
                 StackTraceElement where = method.asStackTraceElement(bci());
                 TTY.println(format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(),
@@ -1540,7 +1624,6 @@
                 return invoke;
             }
 
-            @Override
             protected void genReturn(ValueNode returnVal, Kind returnKind) {
                 if (parsingIntrinsic() && returnVal != null) {
                     if (returnVal instanceof StateSplit) {
@@ -1603,7 +1686,6 @@
                 }
             }
 
-            @Override
             protected void genMonitorEnter(ValueNode x, int bci) {
                 MonitorIdNode monitorId = graph.add(new MonitorIdNode(frameState.lockDepth()));
                 MonitorEnterNode monitorEnter = append(new MonitorEnterNode(x, monitorId));
@@ -1611,7 +1693,6 @@
                 monitorEnter.setStateAfter(createFrameState(bci, monitorEnter));
             }
 
-            @Override
             protected void genMonitorExit(ValueNode x, ValueNode escapedReturnValue, int bci) {
                 MonitorIdNode monitorId = frameState.peekMonitorId();
                 ValueNode lockedObject = frameState.popLock();
@@ -1622,7 +1703,6 @@
                 monitorExit.setStateAfter(createFrameState(bci, monitorExit));
             }
 
-            @Override
             protected void genJsr(int dest) {
                 BciBlock successor = currentBlock.getJsrSuccessor();
                 assert successor.startBci == dest : successor.startBci + " != " + dest + " @" + bci();
@@ -1639,7 +1719,6 @@
                 appendGoto(successor);
             }
 
-            @Override
             protected void genRet(int localIndex) {
                 BciBlock successor = currentBlock.getRetSuccessor();
                 ValueNode local = frameState.loadLocal(localIndex);
@@ -1662,7 +1741,6 @@
                 return graph.unique(nextBciNode);
             }
 
-            @Override
             protected void genIntegerSwitch(ValueNode value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
                 if (value.isConstant()) {
                     JavaConstant constant = (JavaConstant) value.asConstant();
@@ -1684,7 +1762,6 @@
                 }
             }
 
-            @Override
             protected ConstantNode appendConstant(JavaConstant constant) {
                 assert constant != null;
                 return ConstantNode.forConstant(constant, metaAccess, graph);
@@ -2187,7 +2264,6 @@
                 }
             }
 
-            @Override
             protected void iterateBytecodesForBlock(BciBlock block) {
                 if (block.isLoopHeader && !explodeLoops) {
                     // Create the loop header block, which later will merge the backward branches of
@@ -2350,7 +2426,6 @@
                 }
             }
 
-            @Override
             protected void genIf(ValueNode x, Condition cond, ValueNode y) {
                 assert currentBlock.getSuccessorCount() == 2;
                 BciBlock trueBlock = currentBlock.getSuccessor(0);
@@ -2600,6 +2675,894 @@
             private BytecodePosition createBytecodePosition() {
                 return frameState.createBytecodePosition(bci());
             }
+
+            public void setCurrentFrameState(HIRFrameStateBuilder frameState) {
+                this.frameState = frameState;
+            }
+
+            protected final BytecodeStream getStream() {
+                return stream;
+            }
+
+            public int bci() {
+                return stream.currentBCI();
+            }
+
+            public void loadLocal(int index, Kind kind) {
+                frameState.push(kind, frameState.loadLocal(index));
+            }
+
+            public void storeLocal(Kind kind, int index) {
+                ValueNode value;
+                if (kind == Kind.Object) {
+                    value = frameState.xpop();
+                    // astore and astore_<n> may be used to store a returnAddress (jsr)
+                    assert parsingIntrinsic() || (value.getKind() == Kind.Object || value.getKind() == Kind.Int) : value + ":" + value.getKind();
+                } else {
+                    value = frameState.pop(kind);
+                }
+                frameState.storeLocal(index, value, kind);
+            }
+
+            private void genLoadConstant(int cpi, int opcode) {
+                Object con = lookupConstant(cpi, opcode);
+
+                if (con instanceof JavaType) {
+                    // this is a load of class constant which might be unresolved
+                    JavaType type = (JavaType) con;
+                    if (type instanceof ResolvedJavaType) {
+                        frameState.push(Kind.Object, appendConstant(((ResolvedJavaType) type).getJavaClass()));
+                    } else {
+                        handleUnresolvedLoadConstant(type);
+                    }
+                } else if (con instanceof JavaConstant) {
+                    JavaConstant constant = (JavaConstant) con;
+                    frameState.push(constant.getKind().getStackKind(), appendConstant(constant));
+                } else {
+                    throw new Error("lookupConstant returned an object of incorrect type");
+                }
+            }
+
+            private void genLoadIndexed(Kind kind) {
+                ValueNode index = frameState.ipop();
+                ValueNode array = emitExplicitExceptions(frameState.apop(), index);
+                if (!tryLoadIndexedPlugin(kind, index, array)) {
+                    frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind)));
+                }
+            }
+
+            protected boolean tryLoadIndexedPlugin(Kind kind, ValueNode index, ValueNode array) {
+                LoadIndexedPlugin loadIndexedPlugin = graphBuilderConfig.getPlugins().getLoadIndexedPlugin();
+                if (loadIndexedPlugin != null && loadIndexedPlugin.apply(this, array, index, kind)) {
+                    if (TraceParserPlugins.getValue()) {
+                        traceWithContext("used load indexed plugin");
+                    }
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+
+            private void genStoreIndexed(Kind kind) {
+                ValueNode value = frameState.pop(kind.getStackKind());
+                ValueNode index = frameState.ipop();
+                ValueNode array = emitExplicitExceptions(frameState.apop(), index);
+                genStoreIndexed(array, index, kind, value);
+            }
+
+            private void stackOp(int opcode) {
+                switch (opcode) {
+                    case DUP_X1: {
+                        ValueNode w1 = frameState.xpop();
+                        ValueNode w2 = frameState.xpop();
+                        frameState.xpush(w1);
+                        frameState.xpush(w2);
+                        frameState.xpush(w1);
+                        break;
+                    }
+                    case DUP_X2: {
+                        ValueNode w1 = frameState.xpop();
+                        ValueNode w2 = frameState.xpop();
+                        ValueNode w3 = frameState.xpop();
+                        frameState.xpush(w1);
+                        frameState.xpush(w3);
+                        frameState.xpush(w2);
+                        frameState.xpush(w1);
+                        break;
+                    }
+                    case DUP2: {
+                        ValueNode w1 = frameState.xpop();
+                        ValueNode w2 = frameState.xpop();
+                        frameState.xpush(w2);
+                        frameState.xpush(w1);
+                        frameState.xpush(w2);
+                        frameState.xpush(w1);
+                        break;
+                    }
+                    case DUP2_X1: {
+                        ValueNode w1 = frameState.xpop();
+                        ValueNode w2 = frameState.xpop();
+                        ValueNode w3 = frameState.xpop();
+                        frameState.xpush(w2);
+                        frameState.xpush(w1);
+                        frameState.xpush(w3);
+                        frameState.xpush(w2);
+                        frameState.xpush(w1);
+                        break;
+                    }
+                    case DUP2_X2: {
+                        ValueNode w1 = frameState.xpop();
+                        ValueNode w2 = frameState.xpop();
+                        ValueNode w3 = frameState.xpop();
+                        ValueNode w4 = frameState.xpop();
+                        frameState.xpush(w2);
+                        frameState.xpush(w1);
+                        frameState.xpush(w4);
+                        frameState.xpush(w3);
+                        frameState.xpush(w2);
+                        frameState.xpush(w1);
+                        break;
+                    }
+                    case SWAP: {
+                        ValueNode w1 = frameState.xpop();
+                        ValueNode w2 = frameState.xpop();
+                        frameState.xpush(w1);
+                        frameState.xpush(w2);
+                        break;
+                    }
+                    default:
+                        throw GraalInternalError.shouldNotReachHere();
+                }
+            }
+
+            private void genArithmeticOp(Kind result, int opcode) {
+                ValueNode y = frameState.pop(result);
+                ValueNode x = frameState.pop(result);
+                ValueNode v;
+                switch (opcode) {
+                    case IADD:
+                    case LADD:
+                        v = genIntegerAdd(x, y);
+                        break;
+                    case FADD:
+                    case DADD:
+                        v = genFloatAdd(x, y);
+                        break;
+                    case ISUB:
+                    case LSUB:
+                        v = genIntegerSub(x, y);
+                        break;
+                    case FSUB:
+                    case DSUB:
+                        v = genFloatSub(x, y);
+                        break;
+                    case IMUL:
+                    case LMUL:
+                        v = genIntegerMul(x, y);
+                        break;
+                    case FMUL:
+                    case DMUL:
+                        v = genFloatMul(x, y);
+                        break;
+                    case FDIV:
+                    case DDIV:
+                        v = genFloatDiv(x, y);
+                        break;
+                    case FREM:
+                    case DREM:
+                        v = genFloatRem(x, y);
+                        break;
+                    default:
+                        throw new GraalInternalError("should not reach");
+                }
+                frameState.push(result, append(v));
+            }
+
+            private void genIntegerDivOp(Kind result, int opcode) {
+                ValueNode y = frameState.pop(result);
+                ValueNode x = frameState.pop(result);
+                ValueNode v;
+                switch (opcode) {
+                    case IDIV:
+                    case LDIV:
+                        v = genIntegerDiv(x, y);
+                        break;
+                    case IREM:
+                    case LREM:
+                        v = genIntegerRem(x, y);
+                        break;
+                    default:
+                        throw new GraalInternalError("should not reach");
+                }
+                frameState.push(result, append(v));
+            }
+
+            private void genNegateOp(Kind kind) {
+                frameState.push(kind, append(genNegateOp(frameState.pop(kind))));
+            }
+
+            private void genShiftOp(Kind kind, int opcode) {
+                ValueNode s = frameState.ipop();
+                ValueNode x = frameState.pop(kind);
+                ValueNode v;
+                switch (opcode) {
+                    case ISHL:
+                    case LSHL:
+                        v = genLeftShift(x, s);
+                        break;
+                    case ISHR:
+                    case LSHR:
+                        v = genRightShift(x, s);
+                        break;
+                    case IUSHR:
+                    case LUSHR:
+                        v = genUnsignedRightShift(x, s);
+                        break;
+                    default:
+                        throw new GraalInternalError("should not reach");
+                }
+                frameState.push(kind, append(v));
+            }
+
+            private void genLogicOp(Kind kind, int opcode) {
+                ValueNode y = frameState.pop(kind);
+                ValueNode x = frameState.pop(kind);
+                ValueNode v;
+                switch (opcode) {
+                    case IAND:
+                    case LAND:
+                        v = genAnd(x, y);
+                        break;
+                    case IOR:
+                    case LOR:
+                        v = genOr(x, y);
+                        break;
+                    case IXOR:
+                    case LXOR:
+                        v = genXor(x, y);
+                        break;
+                    default:
+                        throw new GraalInternalError("should not reach");
+                }
+                frameState.push(kind, append(v));
+            }
+
+            private void genCompareOp(Kind kind, boolean isUnorderedLess) {
+                ValueNode y = frameState.pop(kind);
+                ValueNode x = frameState.pop(kind);
+                frameState.ipush(append(genNormalizeCompare(x, y, isUnorderedLess)));
+            }
+
+            private void genFloatConvert(FloatConvert op, Kind from, Kind to) {
+                ValueNode input = frameState.pop(from.getStackKind());
+                frameState.push(to.getStackKind(), append(genFloatConvert(op, input)));
+            }
+
+            private void genSignExtend(Kind from, Kind to) {
+                ValueNode input = frameState.pop(from.getStackKind());
+                if (from != from.getStackKind()) {
+                    input = append(genNarrow(input, from.getBitCount()));
+                }
+                frameState.push(to.getStackKind(), append(genSignExtend(input, to.getBitCount())));
+            }
+
+            private void genZeroExtend(Kind from, Kind to) {
+                ValueNode input = frameState.pop(from.getStackKind());
+                if (from != from.getStackKind()) {
+                    input = append(genNarrow(input, from.getBitCount()));
+                }
+                frameState.push(to.getStackKind(), append(genZeroExtend(input, to.getBitCount())));
+            }
+
+            private void genNarrow(Kind from, Kind to) {
+                ValueNode input = frameState.pop(from.getStackKind());
+                frameState.push(to.getStackKind(), append(genNarrow(input, to.getBitCount())));
+            }
+
+            private void genIncrement() {
+                int index = getStream().readLocalIndex();
+                int delta = getStream().readIncrement();
+                ValueNode x = frameState.loadLocal(index);
+                ValueNode y = appendConstant(JavaConstant.forInt(delta));
+                frameState.storeLocal(index, append(genIntegerAdd(x, y)));
+            }
+
+            private void genIfZero(Condition cond) {
+                ValueNode y = appendConstant(JavaConstant.INT_0);
+                ValueNode x = frameState.ipop();
+                genIf(x, cond, y);
+            }
+
+            private void genIfNull(Condition cond) {
+                ValueNode y = appendConstant(JavaConstant.NULL_POINTER);
+                ValueNode x = frameState.apop();
+                genIf(x, cond, y);
+            }
+
+            private void genIfSame(Kind kind, Condition cond) {
+                ValueNode y = frameState.pop(kind);
+                ValueNode x = frameState.pop(kind);
+                genIf(x, cond, y);
+            }
+
+            protected JavaType lookupType(int cpi, int bytecode) {
+                maybeEagerlyResolve(cpi, bytecode);
+                JavaType result = constantPool.lookupType(cpi, bytecode);
+                assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
+                return result;
+            }
+
+            private JavaMethod lookupMethod(int cpi, int opcode) {
+                maybeEagerlyResolve(cpi, opcode);
+                JavaMethod result = constantPool.lookupMethod(cpi, opcode);
+                /*
+                 * In general, one cannot assume that the declaring class being initialized is
+                 * useful, since the actual concrete receiver may be a different class (except for
+                 * static calls). Also, interfaces are initialized only under special circumstances,
+                 * so that this assertion would often fail for interface calls.
+                 */
+                assert !graphBuilderConfig.unresolvedIsError() ||
+                                (result instanceof ResolvedJavaMethod && (opcode != INVOKESTATIC || ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized())) : result;
+                return result;
+            }
+
+            private JavaField lookupField(int cpi, int opcode) {
+                maybeEagerlyResolve(cpi, opcode);
+                JavaField result = constantPool.lookupField(cpi, opcode);
+                assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
+                return result;
+            }
+
+            private Object lookupConstant(int cpi, int opcode) {
+                maybeEagerlyResolve(cpi, opcode);
+                Object result = constantPool.lookupConstant(cpi);
+                assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType) : result;
+                return result;
+            }
+
+            private void maybeEagerlyResolve(int cpi, int bytecode) {
+                if (graphBuilderConfig.eagerResolving() || intrinsicContext != null) {
+                    constantPool.loadReferencedType(cpi, bytecode);
+                }
+            }
+
+            private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) {
+                if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) {
+                    return null;
+                } else {
+                    return profilingInfo.getTypeProfile(bci());
+                }
+            }
+
+            private void genCheckCast() {
+                int cpi = getStream().readCPI();
+                JavaType type = lookupType(cpi, CHECKCAST);
+                ValueNode object = frameState.apop();
+                if (type instanceof ResolvedJavaType) {
+                    ResolvedJavaType resolvedType = (ResolvedJavaType) type;
+                    JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
+                    TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin();
+                    if (typeCheckPlugin == null || !typeCheckPlugin.checkCast(this, object, resolvedType, profile)) {
+                        ValueNode checkCastNode = append(createCheckCast(resolvedType, object, profile, false));
+                        frameState.apush(checkCastNode);
+                    }
+                } else {
+                    handleUnresolvedCheckCast(type, object);
+                }
+            }
+
+            private void genInstanceOf() {
+                int cpi = getStream().readCPI();
+                JavaType type = lookupType(cpi, INSTANCEOF);
+                ValueNode object = frameState.apop();
+                if (type instanceof ResolvedJavaType) {
+                    ResolvedJavaType resolvedType = (ResolvedJavaType) type;
+                    JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
+                    TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin();
+                    if (typeCheckPlugin == null || !typeCheckPlugin.instanceOf(this, object, resolvedType, profile)) {
+                        ValueNode instanceOfNode = createInstanceOf(resolvedType, object, profile);
+                        frameState.ipush(append(genConditional(genUnique(instanceOfNode))));
+                    }
+                } else {
+                    handleUnresolvedInstanceOf(type, object);
+                }
+            }
+
+            void genNewInstance(int cpi) {
+                JavaType type = lookupType(cpi, NEW);
+                if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) {
+                    ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
+                    if (skippedExceptionTypes != null) {
+                        for (ResolvedJavaType exceptionType : skippedExceptionTypes) {
+                            if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) {
+                                append(new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter));
+                                return;
+                            }
+                        }
+                    }
+                    frameState.apush(append(createNewInstance((ResolvedJavaType) type, true)));
+                } else {
+                    handleUnresolvedNewInstance(type);
+                }
+            }
+
+            private void genNewPrimitiveArray(int typeCode) {
+                Class<?> clazz = arrayTypeCodeToClass(typeCode);
+                ResolvedJavaType elementType = metaAccess.lookupJavaType(clazz);
+                frameState.apush(append(createNewArray(elementType, frameState.ipop(), true)));
+            }
+
+            private void genNewObjectArray(int cpi) {
+                JavaType type = lookupType(cpi, ANEWARRAY);
+                ValueNode length = frameState.ipop();
+                if (type instanceof ResolvedJavaType) {
+                    frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true)));
+                } else {
+                    handleUnresolvedNewObjectArray(type, length);
+                }
+
+            }
+
+            private void genNewMultiArray(int cpi) {
+                JavaType type = lookupType(cpi, MULTIANEWARRAY);
+                int rank = getStream().readUByte(bci() + 3);
+                List<ValueNode> dims = new ArrayList<>(Collections.nCopies(rank, null));
+                for (int i = rank - 1; i >= 0; i--) {
+                    dims.set(i, frameState.ipop());
+                }
+                if (type instanceof ResolvedJavaType) {
+                    frameState.apush(append(createNewMultiArray((ResolvedJavaType) type, dims)));
+                } else {
+                    handleUnresolvedNewMultiArray(type, dims);
+                }
+            }
+
+            private void genGetField(JavaField field) {
+                Kind kind = field.getKind();
+                ValueNode receiver = emitExplicitExceptions(frameState.apop(), null);
+                if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
+                    LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin();
+                    if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, receiver, (ResolvedJavaField) field)) {
+                        appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field));
+                    }
+                } else {
+                    handleUnresolvedLoadField(field, receiver);
+                }
+            }
+
+            /**
+             * @param receiver the receiver of an object based operation
+             * @param index the index of an array based operation that is to be tested for out of
+             *            bounds. This is null for a non-array operation.
+             * @return the receiver value possibly modified to have a tighter stamp
+             */
+            protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) {
+                assert receiver != null;
+                if (graphBuilderConfig.omitAllExceptionEdges() ||
+                                profilingInfo == null ||
+                                (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue())) {
+                    return receiver;
+                }
+
+                ValueNode nonNullReceiver = emitExplicitNullCheck(receiver);
+                if (index != null) {
+                    ValueNode length = append(genArrayLength(nonNullReceiver));
+                    emitExplicitBoundsCheck(index, length);
+                }
+                EXPLICIT_EXCEPTIONS.increment();
+                return nonNullReceiver;
+            }
+
+            private void genPutField(JavaField field) {
+                ValueNode value = frameState.pop(field.getKind().getStackKind());
+                ValueNode receiver = emitExplicitExceptions(frameState.apop(), null);
+                if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
+                    genStoreField(receiver, (ResolvedJavaField) field, value);
+                } else {
+                    handleUnresolvedStoreField(field, value, receiver);
+                }
+            }
+
+            private void genGetStatic(JavaField field) {
+                Kind kind = field.getKind();
+                if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
+                    LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin();
+                    if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) {
+                        appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field));
+                    }
+                } else {
+                    handleUnresolvedLoadField(field, null);
+                }
+            }
+
+            public boolean tryLoadFieldPlugin(JavaField field, LoadFieldPlugin loadFieldPlugin) {
+                return loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field);
+            }
+
+            private void genPutStatic(JavaField field) {
+                ValueNode value = frameState.pop(field.getKind().getStackKind());
+                if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
+                    genStoreField(null, (ResolvedJavaField) field, value);
+                } else {
+                    handleUnresolvedStoreField(field, value, null);
+                }
+            }
+
+            protected void appendOptimizedLoadField(Kind kind, ValueNode load) {
+                // append the load to the instruction
+                ValueNode optimized = append(load);
+                frameState.push(kind.getStackKind(), optimized);
+            }
+
+            private double[] switchProbability(int numberOfCases, int bci) {
+                double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci));
+                if (prob != null) {
+                    assert prob.length == numberOfCases;
+                } else {
+                    Debug.log("Missing probability (switch) in %s at bci %d", method, bci);
+                    prob = new double[numberOfCases];
+                    for (int i = 0; i < numberOfCases; i++) {
+                        prob[i] = 1.0d / numberOfCases;
+                    }
+                }
+                assert allPositive(prob);
+                return prob;
+            }
+
+            private void genSwitch(BytecodeSwitch bs) {
+                int bci = bci();
+                ValueNode value = frameState.ipop();
+
+                int nofCases = bs.numberOfCases();
+                double[] keyProbabilities = switchProbability(nofCases + 1, bci);
+
+                Map<Integer, SuccessorInfo> bciToBlockSuccessorIndex = new HashMap<>();
+                for (int i = 0; i < currentBlock.getSuccessorCount(); i++) {
+                    assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci);
+                    if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) {
+                        bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i));
+                    }
+                }
+
+                ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
+                int[] keys = new int[nofCases];
+                int[] keySuccessors = new int[nofCases + 1];
+                int deoptSuccessorIndex = -1;
+                int nextSuccessorIndex = 0;
+                boolean constantValue = value.isConstant();
+                for (int i = 0; i < nofCases + 1; i++) {
+                    if (i < nofCases) {
+                        keys[i] = bs.keyAt(i);
+                    }
+
+                    if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
+                        if (deoptSuccessorIndex < 0) {
+                            deoptSuccessorIndex = nextSuccessorIndex++;
+                            actualSuccessors.add(null);
+                        }
+                        keySuccessors[i] = deoptSuccessorIndex;
+                    } else {
+                        int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i);
+                        SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
+                        if (info.actualIndex < 0) {
+                            info.actualIndex = nextSuccessorIndex++;
+                            actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex));
+                        }
+                        keySuccessors[i] = info.actualIndex;
+                    }
+                }
+
+                genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors);
+
+            }
+
+            protected boolean isNeverExecutedCode(double probability) {
+                return probability == 0 && optimisticOpts.removeNeverExecutedCode();
+            }
+
+            protected double branchProbability() {
+                if (profilingInfo == null) {
+                    return 0.5;
+                }
+                assert assertAtIfBytecode();
+                double probability = profilingInfo.getBranchTakenProbability(bci());
+                if (probability < 0) {
+                    assert probability == -1 : "invalid probability";
+                    Debug.log("missing probability in %s at bci %d", method, bci());
+                    probability = 0.5;
+                }
+
+                if (!optimisticOpts.removeNeverExecutedCode()) {
+                    if (probability == 0) {
+                        probability = 0.0000001;
+                    } else if (probability == 1) {
+                        probability = 0.999999;
+                    }
+                }
+                return probability;
+            }
+
+            private boolean assertAtIfBytecode() {
+                int bytecode = stream.currentBC();
+                switch (bytecode) {
+                    case IFEQ:
+                    case IFNE:
+                    case IFLT:
+                    case IFGE:
+                    case IFGT:
+                    case IFLE:
+                    case IF_ICMPEQ:
+                    case IF_ICMPNE:
+                    case IF_ICMPLT:
+                    case IF_ICMPGE:
+                    case IF_ICMPGT:
+                    case IF_ICMPLE:
+                    case IF_ACMPEQ:
+                    case IF_ACMPNE:
+                    case IFNULL:
+                    case IFNONNULL:
+                        return true;
+                }
+                assert false : String.format("%x is not an if bytecode", bytecode);
+                return true;
+            }
+
+            public final void processBytecode(int bci, int opcode) {
+                int cpi;
+
+                // 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
+                // Checkstyle: resume
+            }
+
+            private void genArrayLength() {
+                frameState.ipush(append(genArrayLength(frameState.apop())));
+            }
+
+            public ResolvedJavaMethod getMethod() {
+                return method;
+            }
+
+            public HIRFrameStateBuilder getFrameState() {
+                return frameState;
+            }
+
+            protected boolean traceInstruction(int bci, int opcode, boolean blockStart) {
+                if (Debug.isEnabled() && Options.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) {
+                    traceInstructionHelper(bci, opcode, blockStart);
+                }
+                return true;
+            }
+
+            private void traceInstructionHelper(int bci, int opcode, boolean blockStart) {
+                StringBuilder sb = new StringBuilder(40);
+                sb.append(blockStart ? '+' : '|');
+                if (bci < 10) {
+                    sb.append("  ");
+                } else if (bci < 100) {
+                    sb.append(' ');
+                }
+                sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode));
+                for (int i = bci + 1; i < stream.nextBCI(); ++i) {
+                    sb.append(' ').append(stream.readUByte(i));
+                }
+                if (!currentBlock.getJsrScope().isEmpty()) {
+                    sb.append(' ').append(currentBlock.getJsrScope());
+                }
+                Debug.log("%s", sb);
+            }
+
+            public boolean parsingIntrinsic() {
+                return intrinsicContext != null;
+            }
         }
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Tue May 12 18:04:53 2015 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.graph.iterators.NodePredicates.*;
+import static com.oracle.graal.java.GraphBuilderPhase.Options.*;
 
 import java.util.*;
 
@@ -31,8 +32,8 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.graphbuilderconf.IntrinsicContext.SideEffectsState;
 import com.oracle.graal.graphbuilderconf.*;
-import com.oracle.graal.graphbuilderconf.IntrinsicContext.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser;
 import com.oracle.graal.nodeinfo.*;
@@ -227,7 +228,7 @@
 
     public BytecodePosition createBytecodePosition(int bci) {
         BytecodeParser parent = parser.getParent();
-        if (AbstractBytecodeParser.Options.HideSubstitutionStates.getValue()) {
+        if (HideSubstitutionStates.getValue()) {
             if (parser.parsingIntrinsic()) {
                 // Attribute to the method being replaced
                 return new BytecodePosition(parent.getFrameState().createBytecodePosition(parent.bci()), parser.intrinsicContext.getOriginalMethod(), -1);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue May 12 18:04:53 2015 -0700
@@ -343,10 +343,16 @@
         public static final LIRInstructionClass<LoadOp> TYPE = LIRInstructionClass.create(LoadOp.class);
 
         @Def({REG}) protected AllocatableValue result;
+        protected boolean signExtend;
 
         public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state) {
+            this(kind, result, address, state, false);
+        }
+
+        public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state, boolean signExtend) {
             super(TYPE, kind, address, state);
             this.result = result;
+            this.signExtend = signExtend;
         }
 
         @Override
@@ -362,16 +368,28 @@
                 switch ((Kind) kind) {
                     case Boolean:
                     case Byte:
-                        masm.ldsb(addr, dst);
+                        if (signExtend) {
+                            masm.ldsb(addr, dst);
+                        } else {
+                            masm.ldub(addr, dst);
+                        }
                         break;
                     case Short:
-                        masm.ldsh(addr, dst);
+                        if (signExtend) {
+                            masm.ldsh(addr, dst);
+                        } else {
+                            masm.lduh(addr, dst);
+                        }
                         break;
                     case Char:
                         masm.lduh(addr, dst);
                         break;
                     case Int:
-                        masm.ldsw(addr, dst);
+                        if (signExtend) {
+                            masm.ldsw(addr, dst);
+                        } else {
+                            masm.lduw(addr, dst);
+                        }
                         break;
                     case Long:
                         masm.ldx(addr, dst);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Tue May 12 18:04:53 2015 -0700
@@ -412,4 +412,23 @@
         test("arrayCopyTypeName", (Object) new Object[]{"one", "two", "three"});
         test("arrayCopyTypeName", (Object) new String[]{"one", "two", "three"});
     }
+
+    public int conditionalInstantiation(Object o) {
+        int total = 0;
+        if (o instanceof CharSequence) {
+            if (o instanceof StringBuilder || o instanceof String) {
+                total = 9;
+            }
+            total += (o instanceof String ? 2 : 1);
+        }
+
+        return total;
+    }
+
+    @Test
+    public void testInstantiation() {
+        test("conditionalInstantiation", "foo");
+        test("conditionalInstantiation", new StringBuilder());
+        test("conditionalInstantiation", 1);
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultInlineInvokePlugin.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultInlineInvokePlugin.java	Tue May 12 18:04:53 2015 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.replacements;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
-import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
+import static com.oracle.graal.java.GraphBuilderPhase.Options.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graphbuilderconf.*;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue May 12 18:04:53 2015 -0700
@@ -96,7 +96,17 @@
     protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, Instantiation instantiation, Node usage, final StructuredGraph graph) {
         InstanceOfUsageReplacer replacer;
         if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ShortCircuitOrNode || usage instanceof GuardingPiNode || usage instanceof ConditionAnchorNode) {
-            replacer = new NonMaterializationUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, usage);
+            ValueNode trueValue = ConstantNode.forInt(1, graph);
+            ValueNode falseValue = ConstantNode.forInt(0, graph);
+            if (instantiation.isInitialized() && (trueValue != instantiation.trueValue || falseValue != instantiation.falseValue)) {
+                /*
+                 * This code doesn't really care what values are used so adopt the values from the
+                 * previous instantiation.
+                 */
+                trueValue = instantiation.trueValue;
+                falseValue = instantiation.falseValue;
+            }
+            replacer = new NonMaterializationUsageReplacer(instantiation, trueValue, falseValue, instanceOf, usage);
         } else {
             assert usage instanceof ConditionalNode : "unexpected usage of " + instanceOf + ": " + usage;
             ConditionalNode c = (ConditionalNode) usage;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Tue May 12 18:04:53 2015 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.replacements;
 
 import static com.oracle.graal.compiler.common.GraalInternalError.*;
-import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
+import static com.oracle.graal.java.GraphBuilderPhase.Options.*;
 
 import java.util.*;
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue May 12 18:04:53 2015 -0700
@@ -25,7 +25,7 @@
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.*;
-import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
+import static com.oracle.graal.java.GraphBuilderPhase.Options.*;
 import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
 import static java.lang.String.*;
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue May 12 17:29:49 2015 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue May 12 18:04:53 2015 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.truffle;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
-import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
+import static com.oracle.graal.java.GraphBuilderPhase.Options.*;
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
 import java.lang.invoke.*;
--- a/src/share/vm/runtime/arguments.cpp	Tue May 12 17:29:49 2015 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Tue May 12 18:04:53 2015 -0700
@@ -1502,9 +1502,6 @@
   // to use UseCompressedOops is InitialHeapSize.
   size_t max_heap_size = MAX2(MaxHeapSize, InitialHeapSize);
   // Set default on graal with sparc to not use compressed oops as long they are not implemented
-/*#if defined(GRAAL) && defined(TARGET_ARCH_sparc)
-  FLAG_SET_DEFAULT(UseCompressedOops, false);
-#else // if !(GRAAL && SOLARIS)*/
   if (max_heap_size <= max_heap_for_compressed_oops()) {
 #if !defined(COMPILER1) || defined(TIERED)
     if (FLAG_IS_DEFAULT(UseCompressedOops)) {
@@ -1529,7 +1526,6 @@
   }
 #endif // _LP64
 #endif // ZERO
-//#endif // !(GRAAL && SOLARIS)
 }