1 /*
   2  * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.java;
  24 
  25 import static java.lang.String.format;
  26 import static java.lang.reflect.Modifier.STATIC;
  27 import static java.lang.reflect.Modifier.SYNCHRONIZED;
  28 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile;
  29 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
  30 import static jdk.vm.ci.meta.DeoptimizationAction.None;
  31 import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException;
  32 import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
  33 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
  34 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
  35 import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated;
  36 import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
  37 import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved;
  38 import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
  39 import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
  40 import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE;
  41 import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL;
  42 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD;
  43 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_0;
  44 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_1;
  45 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_2;
  46 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_3;
  47 import static org.graalvm.compiler.bytecode.Bytecodes.ANEWARRAY;
  48 import static org.graalvm.compiler.bytecode.Bytecodes.ARETURN;
  49 import static org.graalvm.compiler.bytecode.Bytecodes.ARRAYLENGTH;
  50 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE;
  51 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_0;
  52 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_1;
  53 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_2;
  54 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_3;
  55 import static org.graalvm.compiler.bytecode.Bytecodes.ATHROW;
  56 import static org.graalvm.compiler.bytecode.Bytecodes.BALOAD;
  57 import static org.graalvm.compiler.bytecode.Bytecodes.BASTORE;
  58 import static org.graalvm.compiler.bytecode.Bytecodes.BIPUSH;
  59 import static org.graalvm.compiler.bytecode.Bytecodes.BREAKPOINT;
  60 import static org.graalvm.compiler.bytecode.Bytecodes.CALOAD;
  61 import static org.graalvm.compiler.bytecode.Bytecodes.CASTORE;
  62 import static org.graalvm.compiler.bytecode.Bytecodes.CHECKCAST;
  63 import static org.graalvm.compiler.bytecode.Bytecodes.D2F;
  64 import static org.graalvm.compiler.bytecode.Bytecodes.D2I;
  65 import static org.graalvm.compiler.bytecode.Bytecodes.D2L;
  66 import static org.graalvm.compiler.bytecode.Bytecodes.DADD;
  67 import static org.graalvm.compiler.bytecode.Bytecodes.DALOAD;
  68 import static org.graalvm.compiler.bytecode.Bytecodes.DASTORE;
  69 import static org.graalvm.compiler.bytecode.Bytecodes.DCMPG;
  70 import static org.graalvm.compiler.bytecode.Bytecodes.DCMPL;
  71 import static org.graalvm.compiler.bytecode.Bytecodes.DCONST_0;
  72 import static org.graalvm.compiler.bytecode.Bytecodes.DCONST_1;
  73 import static org.graalvm.compiler.bytecode.Bytecodes.DDIV;
  74 import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD;
  75 import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_0;
  76 import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_1;
  77 import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_2;
  78 import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_3;
  79 import static org.graalvm.compiler.bytecode.Bytecodes.DMUL;
  80 import static org.graalvm.compiler.bytecode.Bytecodes.DNEG;
  81 import static org.graalvm.compiler.bytecode.Bytecodes.DREM;
  82 import static org.graalvm.compiler.bytecode.Bytecodes.DRETURN;
  83 import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE;
  84 import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_0;
  85 import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_1;
  86 import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_2;
  87 import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_3;
  88 import static org.graalvm.compiler.bytecode.Bytecodes.DSUB;
  89 import static org.graalvm.compiler.bytecode.Bytecodes.DUP;
  90 import static org.graalvm.compiler.bytecode.Bytecodes.DUP2;
  91 import static org.graalvm.compiler.bytecode.Bytecodes.DUP2_X1;
  92 import static org.graalvm.compiler.bytecode.Bytecodes.DUP2_X2;
  93 import static org.graalvm.compiler.bytecode.Bytecodes.DUP_X1;
  94 import static org.graalvm.compiler.bytecode.Bytecodes.DUP_X2;
  95 import static org.graalvm.compiler.bytecode.Bytecodes.F2D;
  96 import static org.graalvm.compiler.bytecode.Bytecodes.F2I;
  97 import static org.graalvm.compiler.bytecode.Bytecodes.F2L;
  98 import static org.graalvm.compiler.bytecode.Bytecodes.FADD;
  99 import static org.graalvm.compiler.bytecode.Bytecodes.FALOAD;
 100 import static org.graalvm.compiler.bytecode.Bytecodes.FASTORE;
 101 import static org.graalvm.compiler.bytecode.Bytecodes.FCMPG;
 102 import static org.graalvm.compiler.bytecode.Bytecodes.FCMPL;
 103 import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_0;
 104 import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_1;
 105 import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_2;
 106 import static org.graalvm.compiler.bytecode.Bytecodes.FDIV;
 107 import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD;
 108 import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_0;
 109 import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_1;
 110 import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_2;
 111 import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_3;
 112 import static org.graalvm.compiler.bytecode.Bytecodes.FMUL;
 113 import static org.graalvm.compiler.bytecode.Bytecodes.FNEG;
 114 import static org.graalvm.compiler.bytecode.Bytecodes.FREM;
 115 import static org.graalvm.compiler.bytecode.Bytecodes.FRETURN;
 116 import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE;
 117 import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_0;
 118 import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_1;
 119 import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_2;
 120 import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_3;
 121 import static org.graalvm.compiler.bytecode.Bytecodes.FSUB;
 122 import static org.graalvm.compiler.bytecode.Bytecodes.GETFIELD;
 123 import static org.graalvm.compiler.bytecode.Bytecodes.GETSTATIC;
 124 import static org.graalvm.compiler.bytecode.Bytecodes.GOTO;
 125 import static org.graalvm.compiler.bytecode.Bytecodes.GOTO_W;
 126 import static org.graalvm.compiler.bytecode.Bytecodes.I2B;
 127 import static org.graalvm.compiler.bytecode.Bytecodes.I2C;
 128 import static org.graalvm.compiler.bytecode.Bytecodes.I2D;
 129 import static org.graalvm.compiler.bytecode.Bytecodes.I2F;
 130 import static org.graalvm.compiler.bytecode.Bytecodes.I2L;
 131 import static org.graalvm.compiler.bytecode.Bytecodes.I2S;
 132 import static org.graalvm.compiler.bytecode.Bytecodes.IADD;
 133 import static org.graalvm.compiler.bytecode.Bytecodes.IALOAD;
 134 import static org.graalvm.compiler.bytecode.Bytecodes.IAND;
 135 import static org.graalvm.compiler.bytecode.Bytecodes.IASTORE;
 136 import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_0;
 137 import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_1;
 138 import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_2;
 139 import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_3;
 140 import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_4;
 141 import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_5;
 142 import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_M1;
 143 import static org.graalvm.compiler.bytecode.Bytecodes.IDIV;
 144 import static org.graalvm.compiler.bytecode.Bytecodes.IFEQ;
 145 import static org.graalvm.compiler.bytecode.Bytecodes.IFGE;
 146 import static org.graalvm.compiler.bytecode.Bytecodes.IFGT;
 147 import static org.graalvm.compiler.bytecode.Bytecodes.IFLE;
 148 import static org.graalvm.compiler.bytecode.Bytecodes.IFLT;
 149 import static org.graalvm.compiler.bytecode.Bytecodes.IFNE;
 150 import static org.graalvm.compiler.bytecode.Bytecodes.IFNONNULL;
 151 import static org.graalvm.compiler.bytecode.Bytecodes.IFNULL;
 152 import static org.graalvm.compiler.bytecode.Bytecodes.IF_ACMPEQ;
 153 import static org.graalvm.compiler.bytecode.Bytecodes.IF_ACMPNE;
 154 import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPEQ;
 155 import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPGE;
 156 import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPGT;
 157 import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPLE;
 158 import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPLT;
 159 import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPNE;
 160 import static org.graalvm.compiler.bytecode.Bytecodes.IINC;
 161 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD;
 162 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_0;
 163 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_1;
 164 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_2;
 165 import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_3;
 166 import static org.graalvm.compiler.bytecode.Bytecodes.IMUL;
 167 import static org.graalvm.compiler.bytecode.Bytecodes.INEG;
 168 import static org.graalvm.compiler.bytecode.Bytecodes.INSTANCEOF;
 169 import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEDYNAMIC;
 170 import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEINTERFACE;
 171 import static org.graalvm.compiler.bytecode.Bytecodes.INVOKESPECIAL;
 172 import static org.graalvm.compiler.bytecode.Bytecodes.INVOKESTATIC;
 173 import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEVIRTUAL;
 174 import static org.graalvm.compiler.bytecode.Bytecodes.IOR;
 175 import static org.graalvm.compiler.bytecode.Bytecodes.IREM;
 176 import static org.graalvm.compiler.bytecode.Bytecodes.IRETURN;
 177 import static org.graalvm.compiler.bytecode.Bytecodes.ISHL;
 178 import static org.graalvm.compiler.bytecode.Bytecodes.ISHR;
 179 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE;
 180 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_0;
 181 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_1;
 182 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_2;
 183 import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_3;
 184 import static org.graalvm.compiler.bytecode.Bytecodes.ISUB;
 185 import static org.graalvm.compiler.bytecode.Bytecodes.IUSHR;
 186 import static org.graalvm.compiler.bytecode.Bytecodes.IXOR;
 187 import static org.graalvm.compiler.bytecode.Bytecodes.JSR;
 188 import static org.graalvm.compiler.bytecode.Bytecodes.JSR_W;
 189 import static org.graalvm.compiler.bytecode.Bytecodes.L2D;
 190 import static org.graalvm.compiler.bytecode.Bytecodes.L2F;
 191 import static org.graalvm.compiler.bytecode.Bytecodes.L2I;
 192 import static org.graalvm.compiler.bytecode.Bytecodes.LADD;
 193 import static org.graalvm.compiler.bytecode.Bytecodes.LALOAD;
 194 import static org.graalvm.compiler.bytecode.Bytecodes.LAND;
 195 import static org.graalvm.compiler.bytecode.Bytecodes.LASTORE;
 196 import static org.graalvm.compiler.bytecode.Bytecodes.LCMP;
 197 import static org.graalvm.compiler.bytecode.Bytecodes.LCONST_0;
 198 import static org.graalvm.compiler.bytecode.Bytecodes.LCONST_1;
 199 import static org.graalvm.compiler.bytecode.Bytecodes.LDC;
 200 import static org.graalvm.compiler.bytecode.Bytecodes.LDC2_W;
 201 import static org.graalvm.compiler.bytecode.Bytecodes.LDC_W;
 202 import static org.graalvm.compiler.bytecode.Bytecodes.LDIV;
 203 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD;
 204 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_0;
 205 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_1;
 206 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_2;
 207 import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_3;
 208 import static org.graalvm.compiler.bytecode.Bytecodes.LMUL;
 209 import static org.graalvm.compiler.bytecode.Bytecodes.LNEG;
 210 import static org.graalvm.compiler.bytecode.Bytecodes.LOOKUPSWITCH;
 211 import static org.graalvm.compiler.bytecode.Bytecodes.LOR;
 212 import static org.graalvm.compiler.bytecode.Bytecodes.LREM;
 213 import static org.graalvm.compiler.bytecode.Bytecodes.LRETURN;
 214 import static org.graalvm.compiler.bytecode.Bytecodes.LSHL;
 215 import static org.graalvm.compiler.bytecode.Bytecodes.LSHR;
 216 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE;
 217 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_0;
 218 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_1;
 219 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_2;
 220 import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_3;
 221 import static org.graalvm.compiler.bytecode.Bytecodes.LSUB;
 222 import static org.graalvm.compiler.bytecode.Bytecodes.LUSHR;
 223 import static org.graalvm.compiler.bytecode.Bytecodes.LXOR;
 224 import static org.graalvm.compiler.bytecode.Bytecodes.MONITORENTER;
 225 import static org.graalvm.compiler.bytecode.Bytecodes.MONITOREXIT;
 226 import static org.graalvm.compiler.bytecode.Bytecodes.MULTIANEWARRAY;
 227 import static org.graalvm.compiler.bytecode.Bytecodes.NEW;
 228 import static org.graalvm.compiler.bytecode.Bytecodes.NEWARRAY;
 229 import static org.graalvm.compiler.bytecode.Bytecodes.NOP;
 230 import static org.graalvm.compiler.bytecode.Bytecodes.POP;
 231 import static org.graalvm.compiler.bytecode.Bytecodes.POP2;
 232 import static org.graalvm.compiler.bytecode.Bytecodes.PUTFIELD;
 233 import static org.graalvm.compiler.bytecode.Bytecodes.PUTSTATIC;
 234 import static org.graalvm.compiler.bytecode.Bytecodes.RET;
 235 import static org.graalvm.compiler.bytecode.Bytecodes.RETURN;
 236 import static org.graalvm.compiler.bytecode.Bytecodes.SALOAD;
 237 import static org.graalvm.compiler.bytecode.Bytecodes.SASTORE;
 238 import static org.graalvm.compiler.bytecode.Bytecodes.SIPUSH;
 239 import static org.graalvm.compiler.bytecode.Bytecodes.SWAP;
 240 import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH;
 241 import static org.graalvm.compiler.bytecode.Bytecodes.nameOf;
 242 import static org.graalvm.compiler.core.common.GraalOptions.DeoptALot;
 243 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 244 import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining;
 245 import static org.graalvm.compiler.core.common.GraalOptions.PrintProfilingInformation;
 246 import static org.graalvm.compiler.core.common.GraalOptions.ResolveClassBeforeStaticInvoke;
 247 import static org.graalvm.compiler.core.common.GraalOptions.StressExplicitExceptionCode;
 248 import static org.graalvm.compiler.core.common.GraalOptions.StressInvokeWithExceptionNode;
 249 import static org.graalvm.compiler.core.common.type.StampFactory.objectNonNull;
 250 import static org.graalvm.compiler.debug.GraalError.guarantee;
 251 import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
 252 import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing;
 253 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel;
 254 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
 255 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
 256 import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics;
 257 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
 258 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
 259 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING;
 260 import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull;
 261 
 262 import java.util.ArrayList;
 263 import java.util.Collections;
 264 import java.util.Comparator;
 265 import java.util.Formatter;
 266 import java.util.List;
 267 
 268 import org.graalvm.compiler.api.replacements.Snippet;
 269 import org.graalvm.compiler.bytecode.Bytecode;
 270 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
 271 import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
 272 import org.graalvm.compiler.bytecode.BytecodeProvider;
 273 import org.graalvm.compiler.bytecode.BytecodeStream;
 274 import org.graalvm.compiler.bytecode.BytecodeSwitch;
 275 import org.graalvm.compiler.bytecode.BytecodeTableSwitch;
 276 import org.graalvm.compiler.bytecode.Bytecodes;
 277 import org.graalvm.compiler.bytecode.Bytes;
 278 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
 279 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
 280 import org.graalvm.compiler.core.common.PermanentBailoutException;
 281 import org.graalvm.compiler.core.common.calc.Condition;
 282 import org.graalvm.compiler.core.common.calc.FloatConvert;
 283 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
 284 import org.graalvm.compiler.core.common.type.ObjectStamp;
 285 import org.graalvm.compiler.core.common.type.Stamp;
 286 import org.graalvm.compiler.core.common.type.StampFactory;
 287 import org.graalvm.compiler.core.common.type.StampPair;
 288 import org.graalvm.compiler.core.common.type.TypeReference;
 289 import org.graalvm.compiler.core.common.util.Util;
 290 import org.graalvm.compiler.debug.Assertions;
 291 import org.graalvm.compiler.debug.CounterKey;
 292 import org.graalvm.compiler.debug.DebugCloseable;
 293 import org.graalvm.compiler.debug.DebugContext;
 294 import org.graalvm.compiler.debug.GraalError;
 295 import org.graalvm.compiler.debug.Indent;
 296 import org.graalvm.compiler.debug.TTY;
 297 import org.graalvm.compiler.graph.Graph.Mark;
 298 import org.graalvm.compiler.graph.Node;
 299 import org.graalvm.compiler.graph.NodeSourcePosition;
 300 import org.graalvm.compiler.graph.iterators.NodeIterable;
 301 import org.graalvm.compiler.java.BciBlockMapping.BciBlock;
 302 import org.graalvm.compiler.java.BciBlockMapping.ExceptionDispatchBlock;
 303 import org.graalvm.compiler.nodes.AbstractBeginNode;
 304 import org.graalvm.compiler.nodes.AbstractMergeNode;
 305 import org.graalvm.compiler.nodes.BeginNode;
 306 import org.graalvm.compiler.nodes.BeginStateSplitNode;
 307 import org.graalvm.compiler.nodes.CallTargetNode;
 308 import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
 309 import org.graalvm.compiler.nodes.ConstantNode;
 310 import org.graalvm.compiler.nodes.ControlSplitNode;
 311 import org.graalvm.compiler.nodes.DeoptimizeNode;
 312 import org.graalvm.compiler.nodes.EndNode;
 313 import org.graalvm.compiler.nodes.EntryMarkerNode;
 314 import org.graalvm.compiler.nodes.EntryProxyNode;
 315 import org.graalvm.compiler.nodes.FieldLocationIdentity;
 316 import org.graalvm.compiler.nodes.FixedGuardNode;
 317 import org.graalvm.compiler.nodes.FixedNode;
 318 import org.graalvm.compiler.nodes.FixedWithNextNode;
 319 import org.graalvm.compiler.nodes.FrameState;
 320 import org.graalvm.compiler.nodes.FullInfopointNode;
 321 import org.graalvm.compiler.nodes.IfNode;
 322 import org.graalvm.compiler.nodes.Invoke;
 323 import org.graalvm.compiler.nodes.InvokeNode;
 324 import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
 325 import org.graalvm.compiler.nodes.KillingBeginNode;
 326 import org.graalvm.compiler.nodes.LogicConstantNode;
 327 import org.graalvm.compiler.nodes.LogicNegationNode;
 328 import org.graalvm.compiler.nodes.LogicNode;
 329 import org.graalvm.compiler.nodes.LoopBeginNode;
 330 import org.graalvm.compiler.nodes.LoopEndNode;
 331 import org.graalvm.compiler.nodes.LoopExitNode;
 332 import org.graalvm.compiler.nodes.MergeNode;
 333 import org.graalvm.compiler.nodes.ParameterNode;
 334 import org.graalvm.compiler.nodes.PiNode;
 335 import org.graalvm.compiler.nodes.ReturnNode;
 336 import org.graalvm.compiler.nodes.StartNode;
 337 import org.graalvm.compiler.nodes.StateSplit;
 338 import org.graalvm.compiler.nodes.StructuredGraph;
 339 import org.graalvm.compiler.nodes.UnwindNode;
 340 import org.graalvm.compiler.nodes.ValueNode;
 341 import org.graalvm.compiler.nodes.calc.AddNode;
 342 import org.graalvm.compiler.nodes.calc.AndNode;
 343 import org.graalvm.compiler.nodes.calc.CompareNode;
 344 import org.graalvm.compiler.nodes.calc.ConditionalNode;
 345 import org.graalvm.compiler.nodes.calc.FloatDivNode;
 346 import org.graalvm.compiler.nodes.calc.FloatConvertNode;
 347 import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
 348 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
 349 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
 350 import org.graalvm.compiler.nodes.calc.IsNullNode;
 351 import org.graalvm.compiler.nodes.calc.LeftShiftNode;
 352 import org.graalvm.compiler.nodes.calc.MulNode;
 353 import org.graalvm.compiler.nodes.calc.NarrowNode;
 354 import org.graalvm.compiler.nodes.calc.NegateNode;
 355 import org.graalvm.compiler.nodes.calc.NormalizeCompareNode;
 356 import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
 357 import org.graalvm.compiler.nodes.calc.OrNode;
 358 import org.graalvm.compiler.nodes.calc.RemNode;
 359 import org.graalvm.compiler.nodes.calc.RightShiftNode;
 360 import org.graalvm.compiler.nodes.calc.SignExtendNode;
 361 import org.graalvm.compiler.nodes.calc.SignedDivNode;
 362 import org.graalvm.compiler.nodes.calc.SignedRemNode;
 363 import org.graalvm.compiler.nodes.calc.SubNode;
 364 import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
 365 import org.graalvm.compiler.nodes.calc.XorNode;
 366 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
 367 import org.graalvm.compiler.nodes.extended.AnchoringNode;
 368 import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
 369 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode;
 370 import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
 371 import org.graalvm.compiler.nodes.extended.LoadHubNode;
 372 import org.graalvm.compiler.nodes.extended.LoadMethodNode;
 373 import org.graalvm.compiler.nodes.extended.MembarNode;
 374 import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
 375 import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
 376 import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
 377 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 378 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
 379 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 380 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
 381 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo;
 382 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
 383 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 384 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
 385 import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
 386 import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
 387 import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin;
 388 import org.graalvm.compiler.nodes.java.ArrayLengthNode;
 389 import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
 390 import org.graalvm.compiler.nodes.java.FinalFieldBarrierNode;
 391 import org.graalvm.compiler.nodes.java.InstanceOfNode;
 392 import org.graalvm.compiler.nodes.java.LoadFieldNode;
 393 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
 394 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
 395 import org.graalvm.compiler.nodes.java.MonitorEnterNode;
 396 import org.graalvm.compiler.nodes.java.MonitorExitNode;
 397 import org.graalvm.compiler.nodes.java.MonitorIdNode;
 398 import org.graalvm.compiler.nodes.java.NewArrayNode;
 399 import org.graalvm.compiler.nodes.java.NewInstanceNode;
 400 import org.graalvm.compiler.nodes.java.NewMultiArrayNode;
 401 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
 402 import org.graalvm.compiler.nodes.java.StoreFieldNode;
 403 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
 404 import org.graalvm.compiler.nodes.spi.StampProvider;
 405 import org.graalvm.compiler.nodes.type.StampTool;
 406 import org.graalvm.compiler.nodes.util.GraphUtil;
 407 import org.graalvm.compiler.options.OptionValues;
 408 import org.graalvm.compiler.phases.OptimisticOptimizations;
 409 import org.graalvm.compiler.phases.util.ValueMergeUtil;
 410 import org.graalvm.util.EconomicMap;
 411 import org.graalvm.util.Equivalence;
 412 import org.graalvm.word.LocationIdentity;
 413 
 414 import jdk.vm.ci.code.BailoutException;
 415 import jdk.vm.ci.code.BytecodeFrame;
 416 import jdk.vm.ci.code.CodeUtil;
 417 import jdk.vm.ci.code.site.InfopointReason;
 418 import jdk.vm.ci.meta.ConstantPool;
 419 import jdk.vm.ci.meta.ConstantReflectionProvider;
 420 import jdk.vm.ci.meta.DeoptimizationAction;
 421 import jdk.vm.ci.meta.DeoptimizationReason;
 422 import jdk.vm.ci.meta.JavaConstant;
 423 import jdk.vm.ci.meta.JavaField;
 424 import jdk.vm.ci.meta.JavaKind;
 425 import jdk.vm.ci.meta.JavaMethod;
 426 import jdk.vm.ci.meta.JavaType;
 427 import jdk.vm.ci.meta.JavaTypeProfile;
 428 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
 429 import jdk.vm.ci.meta.LineNumberTable;
 430 import jdk.vm.ci.meta.MetaAccessProvider;
 431 import jdk.vm.ci.meta.ProfilingInfo;
 432 import jdk.vm.ci.meta.RawConstant;
 433 import jdk.vm.ci.meta.ResolvedJavaField;
 434 import jdk.vm.ci.meta.ResolvedJavaMethod;
 435 import jdk.vm.ci.meta.ResolvedJavaType;
 436 import jdk.vm.ci.meta.Signature;
 437 import jdk.vm.ci.meta.TriState;
 438 import org.graalvm.compiler.core.common.type.IntegerStamp;
 439 
 440 /**
 441  * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
 442  */
 443 public class BytecodeParser implements GraphBuilderContext {
 444 
 445     /**
 446      * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
 447      * to trace the bytecode instructions as they are parsed.
 448      */
 449     public static final int TRACELEVEL_INSTRUCTIONS = 1;
 450 
 451     /**
 452      * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
 453      * to trace the frame state before each bytecode instruction as it is parsed.
 454      */
 455     public static final int TRACELEVEL_STATE = 2;
 456 
 457     /**
 458      * Meters the number of actual bytecodes parsed.
 459      */
 460     public static final CounterKey BytecodesParsed = DebugContext.counter("BytecodesParsed");
 461 
 462     protected static final CounterKey EXPLICIT_EXCEPTIONS = DebugContext.counter("ExplicitExceptions");
 463 
 464     /**
 465      * A scoped object for tasks to be performed after parsing an intrinsic such as processing
 466      * {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frames states.
 467      */
 468     static class IntrinsicScope implements AutoCloseable {
 469         FrameState stateBefore;
 470         final Mark mark;
 471         final BytecodeParser parser;
 472         List<ReturnToCallerData> returnDataList;
 473 
 474         /**
 475          * Creates a scope for root parsing an intrinsic.
 476          *
 477          * @param parser the parsing context of the intrinsic
 478          */
 479         IntrinsicScope(BytecodeParser parser) {
 480             this.parser = parser;
 481             assert parser.parent == null;
 482             assert parser.bci() == 0;
 483             mark = null;
 484         }
 485 
 486         /**
 487          * Creates a scope for parsing an intrinsic during graph builder inlining.
 488          *
 489          * @param parser the parsing context of the (non-intrinsic) method calling the intrinsic
 490          * @param args the arguments to the call
 491          */
 492         IntrinsicScope(BytecodeParser parser, JavaKind[] argSlotKinds, ValueNode[] args) {
 493             assert !parser.parsingIntrinsic();
 494             this.parser = parser;
 495             mark = parser.getGraph().getMark();
 496             stateBefore = parser.frameState.create(parser.bci(), parser.getNonIntrinsicAncestor(), false, argSlotKinds, args);
 497         }
 498 
 499         @Override
 500         public void close() {
 501             IntrinsicContext intrinsic = parser.intrinsicContext;
 502             if (intrinsic != null && intrinsic.isPostParseInlined()) {
 503                 return;
 504             }
 505 
 506             processPlaceholderFrameStates(intrinsic);
 507         }
 508 
 509         /**
 510          * Fixes up the {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frame states
 511          * added to the graph while parsing/inlining the intrinsic for which this object exists.
 512          */
 513         private void processPlaceholderFrameStates(IntrinsicContext intrinsic) {
 514             StructuredGraph graph = parser.getGraph();
 515             graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before processPlaceholderFrameStates in %s", parser.method);
 516             boolean sawInvalidFrameState = false;
 517             for (Node node : graph.getNewNodes(mark)) {
 518                 if (node instanceof FrameState) {
 519                     FrameState frameState = (FrameState) node;
 520                     if (BytecodeFrame.isPlaceholderBci(frameState.bci)) {
 521                         if (frameState.bci == BytecodeFrame.AFTER_BCI) {
 522                             if (parser.getInvokeReturnType() == null) {
 523                                 // A frame state in a root compiled intrinsic.
 524                                 assert intrinsic.isCompilationRoot();
 525                                 FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
 526                                 frameState.replaceAndDelete(newFrameState);
 527                             } else {
 528                                 JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
 529                                 FrameStateBuilder frameStateBuilder = parser.frameState;
 530                                 assert !frameState.rethrowException();
 531                                 if (frameState.stackSize() != 0) {
 532                                     ValueNode returnVal = frameState.stackAt(0);
 533                                     if (!ReturnToCallerData.containsReturnValue(returnDataList, returnVal)) {
 534                                         throw new GraalError("AFTER_BCI frame state within an intrinsic has a non-return value on the stack: %s", returnVal);
 535                                     }
 536 
 537                                     // Swap the top-of-stack value with the return value
 538                                     ValueNode tos = frameStateBuilder.pop(returnKind);
 539                                     assert tos.getStackKind() == returnVal.getStackKind();
 540                                     FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), parser.getNonIntrinsicAncestor(), false, new JavaKind[]{returnKind},
 541                                                     new ValueNode[]{returnVal});
 542                                     frameState.replaceAndDelete(newFrameState);
 543                                     newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
 544                                     frameStateBuilder.push(returnKind, tos);
 545                                 } else if (returnKind != JavaKind.Void) {
 546                                     // If the intrinsic returns a non-void value, then any frame
 547                                     // state with an empty stack is invalid as it cannot
 548                                     // be used to deoptimize to just after the call returns.
 549                                     // These invalid frame states are expected to be removed
 550                                     // by later compilation stages.
 551                                     FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
 552                                     newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
 553                                     frameState.replaceAndDelete(newFrameState);
 554                                     sawInvalidFrameState = true;
 555                                 } else {
 556                                     // An intrinsic for a void method.
 557                                     FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), null);
 558                                     newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
 559                                     frameState.replaceAndDelete(newFrameState);
 560                                 }
 561                             }
 562                         } else if (frameState.bci == BytecodeFrame.BEFORE_BCI) {
 563                             if (stateBefore == null) {
 564                                 stateBefore = graph.start().stateAfter();
 565                             }
 566                             if (stateBefore != frameState) {
 567                                 frameState.replaceAndDelete(stateBefore);
 568                             }
 569                         } else if (frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
 570                             // This is a frame state for the entry point to an exception
 571                             // dispatcher in an intrinsic. For example, the invoke denoting
 572                             // a partial intrinsic exit will have an edge to such a
 573                             // dispatcher if the profile for the original invoke being
 574                             // intrinsified indicates an exception was seen. As per JVM
 575                             // bytecode semantics, the interpreter expects a single
 576                             // value on the stack on entry to an exception handler,
 577                             // namely the exception object.
 578                             assert frameState.rethrowException();
 579                             ExceptionObjectNode exceptionObject = (ExceptionObjectNode) frameState.stackAt(0);
 580                             FrameStateBuilder dispatchState = parser.frameState.copy();
 581                             dispatchState.clearStack();
 582                             dispatchState.push(JavaKind.Object, exceptionObject);
 583                             dispatchState.setRethrowException(true);
 584                             FrameState newFrameState = dispatchState.create(parser.bci(), exceptionObject);
 585                             frameState.replaceAndDelete(newFrameState);
 586                             newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
 587                         } else {
 588                             assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI;
 589                         }
 590                     }
 591                 }
 592             }
 593             if (sawInvalidFrameState) {
 594                 JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
 595                 FrameStateBuilder frameStateBuilder = parser.frameState;
 596                 ValueNode returnValue = frameStateBuilder.pop(returnKind);
 597                 StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue));
 598                 parser.lastInstr.setNext(proxy);
 599                 frameStateBuilder.push(returnKind, proxy);
 600                 proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy));
 601                 parser.lastInstr = proxy;
 602             }
 603             graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method);
 604         }
 605     }
 606 
 607     private static class Target {
 608         FixedNode fixed;
 609         FrameStateBuilder state;
 610 
 611         Target(FixedNode fixed, FrameStateBuilder state) {
 612             this.fixed = fixed;
 613             this.state = state;
 614         }
 615     }
 616 
 617     @SuppressWarnings("serial")
 618     public static class BytecodeParserError extends GraalError {
 619 
 620         public BytecodeParserError(Throwable cause) {
 621             super(cause);
 622         }
 623 
 624         public BytecodeParserError(String msg, Object... args) {
 625             super(msg, args);
 626         }
 627     }
 628 
 629     protected static class ReturnToCallerData {
 630         protected final ValueNode returnValue;
 631         protected final FixedWithNextNode beforeReturnNode;
 632 
 633         protected ReturnToCallerData(ValueNode returnValue, FixedWithNextNode beforeReturnNode) {
 634             this.returnValue = returnValue;
 635             this.beforeReturnNode = beforeReturnNode;
 636         }
 637 
 638         static boolean containsReturnValue(List<ReturnToCallerData> list, ValueNode value) {
 639             for (ReturnToCallerData e : list) {
 640                 if (e.returnValue == value) {
 641                     return true;
 642                 }
 643             }
 644             return false;
 645         }
 646     }
 647 
 648     private final GraphBuilderPhase.Instance graphBuilderInstance;
 649     protected final StructuredGraph graph;
 650     protected final OptionValues options;
 651     protected final DebugContext debug;
 652 
 653     private BciBlockMapping blockMap;
 654     private LocalLiveness liveness;
 655     protected final int entryBCI;
 656     private final BytecodeParser parent;
 657 
 658     private LineNumberTable lnt;
 659     private int previousLineNumber;
 660     private int currentLineNumber;
 661 
 662     private ValueNode methodSynchronizedObject;
 663 
 664     private List<ReturnToCallerData> returnDataList;
 665     private ValueNode unwindValue;
 666     private FixedWithNextNode beforeUnwindNode;
 667 
 668     protected FixedWithNextNode lastInstr;                 // the last instruction added
 669     private boolean controlFlowSplit;
 670     private final InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(this);
 671 
 672     private FixedWithNextNode[] firstInstructionArray;
 673     private FrameStateBuilder[] entryStateArray;
 674 
 675     private boolean finalBarrierRequired;
 676     private ValueNode originalReceiver;
 677 
 678     protected BytecodeParser(GraphBuilderPhase.Instance graphBuilderInstance, StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method,
 679                     int entryBCI, IntrinsicContext intrinsicContext) {
 680         this.bytecodeProvider = intrinsicContext == null ? new ResolvedJavaMethodBytecodeProvider() : intrinsicContext.getBytecodeProvider();
 681         this.code = bytecodeProvider.getBytecode(method);
 682         this.method = code.getMethod();
 683         this.graphBuilderInstance = graphBuilderInstance;
 684         this.graph = graph;
 685         this.options = graph.getOptions();
 686         this.debug = graph.getDebug();
 687         this.graphBuilderConfig = graphBuilderInstance.graphBuilderConfig;
 688         this.optimisticOpts = graphBuilderInstance.optimisticOpts;
 689         this.metaAccess = graphBuilderInstance.metaAccess;
 690         this.stampProvider = graphBuilderInstance.stampProvider;
 691         this.constantReflection = graphBuilderInstance.constantReflection;
 692         this.constantFieldProvider = graphBuilderInstance.constantFieldProvider;
 693         this.stream = new BytecodeStream(code.getCode());
 694         this.profilingInfo = graph.useProfilingInfo() ? code.getProfilingInfo() : null;
 695         this.constantPool = code.getConstantPool();
 696         this.intrinsicContext = intrinsicContext;
 697         this.entryBCI = entryBCI;
 698         this.parent = parent;
 699 
 700         assert code.getCode() != null : "method must contain bytecodes: " + method;
 701 
 702         if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) {
 703             lnt = code.getLineNumberTable();
 704             previousLineNumber = -1;
 705         }
 706     }
 707 
 708     protected GraphBuilderPhase.Instance getGraphBuilderInstance() {
 709         return graphBuilderInstance;
 710     }
 711 
 712     public ValueNode getUnwindValue() {
 713         return unwindValue;
 714     }
 715 
 716     public FixedWithNextNode getBeforeUnwindNode() {
 717         return this.beforeUnwindNode;
 718     }
 719 
 720     @SuppressWarnings("try")
 721     protected void buildRootMethod() {
 722         FrameStateBuilder startFrameState = new FrameStateBuilder(this, code, graph);
 723         startFrameState.initializeForMethodStart(graph.getAssumptions(), graphBuilderConfig.eagerResolving() || intrinsicContext != null, graphBuilderConfig.getPlugins());
 724 
 725         try (IntrinsicScope s = intrinsicContext != null ? new IntrinsicScope(this) : null) {
 726             build(graph.start(), startFrameState);
 727         }
 728 
 729         cleanupFinalGraph();
 730         ComputeLoopFrequenciesClosure.compute(graph);
 731     }
 732 
 733     @SuppressWarnings("try")
 734     protected void build(FixedWithNextNode startInstruction, FrameStateBuilder startFrameState) {
 735         if (PrintProfilingInformation.getValue(options) && profilingInfo != null) {
 736             TTY.println("Profiling info for " + method.format("%H.%n(%p)"));
 737             TTY.println(Util.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), "  "));
 738         }
 739 
 740         try (Indent indent = debug.logAndIndent("build graph for %s", method)) {
 741             if (bytecodeProvider.shouldRecordMethodDependencies()) {
 742                 assert getParent() != null || method.equals(graph.method());
 743                 // Record method dependency in the graph
 744                 graph.recordMethod(method);
 745             }
 746 
 747             // compute the block map, setup exception handlers and get the entrypoint(s)
 748             BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options, graph.getDebug());
 749             this.blockMap = newMapping;
 750             this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()];
 751             this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()];
 752             if (!method.isStatic()) {
 753                 originalReceiver = startFrameState.loadLocal(0, JavaKind.Object);
 754             }
 755 
 756             /*
 757              * Configure the assertion checking behavior of the FrameStateBuilder. This needs to be
 758              * done only when assertions are enabled, so it is wrapped in an assertion itself.
 759              */
 760             assert computeKindVerification(startFrameState);
 761 
 762             try (DebugContext.Scope s = debug.scope("LivenessAnalysis")) {
 763                 int maxLocals = method.getMaxLocals();
 764                 liveness = LocalLiveness.compute(debug, stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount());
 765             } catch (Throwable e) {
 766                 throw debug.handle(e);
 767             }
 768 
 769             lastInstr = startInstruction;
 770             this.setCurrentFrameState(startFrameState);
 771             stream.setBCI(0);
 772 
 773             BciBlock startBlock = blockMap.getStartBlock();
 774             if (this.parent == null) {
 775                 StartNode startNode = graph.start();
 776                 if (method.isSynchronized()) {
 777                     assert !parsingIntrinsic();
 778                     startNode.setStateAfter(createFrameState(BytecodeFrame.BEFORE_BCI, startNode));
 779                 } else {
 780                     if (!parsingIntrinsic()) {
 781                         if (graph.method() != null && graph.method().isJavaLangObjectInit()) {
 782                             /*
 783                              * Don't clear the receiver when Object.<init> is the compilation root.
 784                              * The receiver is needed as input to RegisterFinalizerNode.
 785                              */
 786                         } else {
 787                             frameState.clearNonLiveLocals(startBlock, liveness, true);
 788                         }
 789                         assert bci() == 0;
 790                         startNode.setStateAfter(createFrameState(bci(), startNode));
 791                     } else {
 792                         if (startNode.stateAfter() == null) {
 793                             FrameState stateAfterStart = createStateAfterStartOfReplacementGraph();
 794                             startNode.setStateAfter(stateAfterStart);
 795                         }
 796                     }
 797                 }
 798             }
 799 
 800             if (method.isSynchronized()) {
 801                 finishPrepare(lastInstr, BytecodeFrame.BEFORE_BCI);
 802 
 803                 // add a monitor enter to the start block
 804                 methodSynchronizedObject = synchronizedObject(frameState, method);
 805                 frameState.clearNonLiveLocals(startBlock, liveness, true);
 806                 assert bci() == 0;
 807                 genMonitorEnter(methodSynchronizedObject, bci());
 808             }
 809 
 810             ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin();
 811             if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
 812                 FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
 813                 profilingPlugin.profileInvoke(this, method, stateBefore);
 814             }
 815 
 816             finishPrepare(lastInstr, 0);
 817 
 818             genInfoPointNode(InfopointReason.METHOD_START, null);
 819 
 820             currentBlock = blockMap.getStartBlock();
 821             setEntryState(startBlock, frameState);
 822             if (startBlock.isLoopHeader) {
 823                 appendGoto(startBlock);
 824             } else {
 825                 setFirstInstruction(startBlock, lastInstr);
 826             }
 827 
 828             BciBlock[] blocks = blockMap.getBlocks();
 829             for (BciBlock block : blocks) {
 830                 processBlock(block);
 831             }
 832         }
 833     }
 834 
 835     private boolean computeKindVerification(FrameStateBuilder startFrameState) {
 836         if (blockMap.hasJsrBytecodes) {
 837             /*
 838              * The JSR return address is an int value, but stored using the astore bytecode. Instead
 839              * of weakening the kind assertion checking for all methods, we disable it completely
 840              * for methods that contain a JSR bytecode.
 841              */
 842             startFrameState.disableKindVerification();
 843         }
 844 
 845         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
 846             if (plugin.canChangeStackKind(this)) {
 847                 /*
 848                  * We have a plugin that can change the kind of values, so no kind assertion
 849                  * checking is possible.
 850                  */
 851                 startFrameState.disableKindVerification();
 852             }
 853         }
 854         return true;
 855     }
 856 
 857     /**
 858      * Hook for subclasses to modify synthetic code (start nodes and unwind nodes).
 859      *
 860      * @param instruction the current last instruction
 861      * @param bci the current bci
 862      */
 863     protected void finishPrepare(FixedWithNextNode instruction, int bci) {
 864     }
 865 
 866     protected void cleanupFinalGraph() {
 867         GraphUtil.normalizeLoops(graph);
 868 
 869         // Remove dead parameters.
 870         for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
 871             if (param.hasNoUsages()) {
 872                 assert param.inputs().isEmpty();
 873                 param.safeDelete();
 874             }
 875         }
 876 
 877         // Remove redundant begin nodes.
 878         for (BeginNode beginNode : graph.getNodes(BeginNode.TYPE)) {
 879             Node predecessor = beginNode.predecessor();
 880             if (predecessor instanceof ControlSplitNode) {
 881                 // The begin node is necessary.
 882             } else if (!beginNode.hasUsages()) {
 883                 GraphUtil.unlinkFixedNode(beginNode);
 884                 beginNode.safeDelete();
 885             }
 886         }
 887     }
 888 
 889     /**
 890      * Creates the frame state after the start node of a graph for an {@link IntrinsicContext
 891      * intrinsic} that is the parse root (either for root compiling or for post-parse inlining).
 892      */
 893     private FrameState createStateAfterStartOfReplacementGraph() {
 894         assert parent == null;
 895         assert frameState.getMethod().equals(intrinsicContext.getIntrinsicMethod());
 896         assert bci() == 0;
 897         assert frameState.stackSize() == 0;
 898         FrameState stateAfterStart;
 899         if (intrinsicContext.isPostParseInlined()) {
 900             stateAfterStart = graph.add(new FrameState(BytecodeFrame.BEFORE_BCI));
 901         } else {
 902             ResolvedJavaMethod original = intrinsicContext.getOriginalMethod();
 903             ValueNode[] locals;
 904             if (original.getMaxLocals() == frameState.localsSize() || original.isNative()) {
 905                 locals = new ValueNode[original.getMaxLocals()];
 906                 for (int i = 0; i < locals.length; i++) {
 907                     ValueNode node = frameState.locals[i];
 908                     if (node == FrameState.TWO_SLOT_MARKER) {
 909                         node = null;
 910                     }
 911                     locals[i] = node;
 912                 }
 913             } else {
 914                 locals = new ValueNode[original.getMaxLocals()];
 915                 int parameterCount = original.getSignature().getParameterCount(!original.isStatic());
 916                 for (int i = 0; i < parameterCount; i++) {
 917                     ValueNode param = frameState.locals[i];
 918                     if (param == FrameState.TWO_SLOT_MARKER) {
 919                         param = null;
 920                     }
 921                     locals[i] = param;
 922                     assert param == null || param instanceof ParameterNode || param.isConstant();
 923                 }
 924             }
 925             ValueNode[] stack = {};
 926             int stackSize = 0;
 927             ValueNode[] locks = {};
 928             List<MonitorIdNode> monitorIds = Collections.emptyList();
 929             stateAfterStart = graph.add(new FrameState(null, new ResolvedJavaMethodBytecode(original), 0, locals, stack, stackSize, locks, monitorIds, false, false));
 930         }
 931         return stateAfterStart;
 932     }
 933 
 934     /**
 935      * @param type the unresolved type of the constant
 936      */
 937     protected void handleUnresolvedLoadConstant(JavaType type) {
 938         assert !graphBuilderConfig.unresolvedIsError();
 939         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
 940         /*
 941          * Track source position for deopt nodes even if
 942          * GraphBuilderConfiguration.trackNodeSourcePosition is not set.
 943          */
 944         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
 945     }
 946 
 947     /**
 948      * @param type the unresolved type of the type check
 949      * @param object the object value whose type is being checked against {@code type}
 950      */
 951     protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) {
 952         assert !graphBuilderConfig.unresolvedIsError();
 953         append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), Unresolved, InvalidateRecompile));
 954         frameState.push(JavaKind.Object, appendConstant(JavaConstant.NULL_POINTER));
 955     }
 956 
 957     /**
 958      * @param type the unresolved type of the type check
 959      * @param object the object value whose type is being checked against {@code type}
 960      */
 961     protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) {
 962         assert !graphBuilderConfig.unresolvedIsError();
 963         AbstractBeginNode successor = graph.add(new BeginNode());
 964         DeoptimizeNode deopt = graph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved));
 965         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
 966         append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), successor, deopt, 1));
 967         lastInstr = successor;
 968         frameState.push(JavaKind.Int, appendConstant(JavaConstant.INT_0));
 969     }
 970 
 971     /**
 972      * @param type the type being instantiated
 973      */
 974     protected void handleUnresolvedNewInstance(JavaType type) {
 975         assert !graphBuilderConfig.unresolvedIsError();
 976         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
 977         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
 978     }
 979 
 980     /**
 981      * @param type the type of the array being instantiated
 982      * @param length the length of the array
 983      */
 984     protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) {
 985         assert !graphBuilderConfig.unresolvedIsError();
 986         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
 987         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
 988     }
 989 
 990     /**
 991      * @param type the type being instantiated
 992      * @param dims the dimensions for the multi-array
 993      */
 994     protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) {
 995         assert !graphBuilderConfig.unresolvedIsError();
 996         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
 997         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
 998     }
 999 
1000     /**
1001      * @param field the unresolved field
1002      * @param receiver the object containing the field or {@code null} if {@code field} is static
1003      */
1004     protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) {
1005         assert !graphBuilderConfig.unresolvedIsError();
1006         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1007         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
1008     }
1009 
1010     /**
1011      * @param field the unresolved field
1012      * @param value the value being stored to the field
1013      * @param receiver the object containing the field or {@code null} if {@code field} is static
1014      */
1015     protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) {
1016         assert !graphBuilderConfig.unresolvedIsError();
1017         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1018         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
1019     }
1020 
1021     /**
1022      * @param type
1023      */
1024     protected void handleUnresolvedExceptionType(JavaType type) {
1025         assert !graphBuilderConfig.unresolvedIsError();
1026         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1027         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
1028     }
1029 
1030     /**
1031      * @param javaMethod
1032      * @param invokeKind
1033      */
1034     protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) {
1035         assert !graphBuilderConfig.unresolvedIsError();
1036         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1037         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
1038     }
1039 
1040     private AbstractBeginNode handleException(ValueNode exceptionObject, int bci, boolean deoptimizeOnly) {
1041         assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci";
1042         debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci)));
1043 
1044         FrameStateBuilder dispatchState = frameState.copy();
1045         dispatchState.clearStack();
1046 
1047         AbstractBeginNode dispatchBegin;
1048         if (exceptionObject == null) {
1049             ExceptionObjectNode newExceptionObject = graph.add(new ExceptionObjectNode(metaAccess));
1050             dispatchBegin = newExceptionObject;
1051             dispatchState.push(JavaKind.Object, dispatchBegin);
1052             dispatchState.setRethrowException(true);
1053             newExceptionObject.setStateAfter(dispatchState.create(bci, newExceptionObject));
1054         } else {
1055             dispatchBegin = graph.add(new BeginNode());
1056             dispatchState.push(JavaKind.Object, exceptionObject);
1057             dispatchState.setRethrowException(true);
1058         }
1059         this.controlFlowSplit = true;
1060         FixedWithNextNode finishedDispatch = finishInstruction(dispatchBegin, dispatchState);
1061 
1062         if (deoptimizeOnly) {
1063             DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
1064             dispatchBegin.setNext(BeginNode.begin(deoptimizeNode));
1065         } else {
1066             createHandleExceptionTarget(finishedDispatch, bci, dispatchState);
1067         }
1068         return dispatchBegin;
1069     }
1070 
1071     protected void createHandleExceptionTarget(FixedWithNextNode finishedDispatch, int bci, FrameStateBuilder dispatchState) {
1072         BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
1073         /*
1074          * The exception dispatch block is always for the last bytecode of a block, so if we are not
1075          * at the endBci yet, there is no exception handler for this bci and we can unwind
1076          * immediately.
1077          */
1078         if (bci != currentBlock.endBci || dispatchBlock == null) {
1079             dispatchBlock = blockMap.getUnwindBlock();
1080         }
1081 
1082         FixedNode target = createTarget(dispatchBlock, dispatchState);
1083         finishedDispatch.setNext(target);
1084     }
1085 
1086     protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, JavaKind kind) {
1087         return LoadIndexedNode.create(graph.getAssumptions(), array, index, kind, metaAccess, constantReflection);
1088     }
1089 
1090     protected void genStoreIndexed(ValueNode array, ValueNode index, JavaKind kind, ValueNode value) {
1091         add(new StoreIndexedNode(array, index, kind, value));
1092     }
1093 
1094     protected ValueNode genIntegerAdd(ValueNode x, ValueNode y) {
1095         return AddNode.create(x, y);
1096     }
1097 
1098     protected ValueNode genIntegerSub(ValueNode x, ValueNode y) {
1099         return SubNode.create(x, y);
1100     }
1101 
1102     protected ValueNode genIntegerMul(ValueNode x, ValueNode y) {
1103         return MulNode.create(x, y);
1104     }
1105 
1106     protected ValueNode genFloatAdd(ValueNode x, ValueNode y) {
1107         return AddNode.create(x, y);
1108     }
1109 
1110     protected ValueNode genFloatSub(ValueNode x, ValueNode y) {
1111         return SubNode.create(x, y);
1112     }
1113 
1114     protected ValueNode genFloatMul(ValueNode x, ValueNode y) {
1115         return MulNode.create(x, y);
1116     }
1117 
1118     protected ValueNode genFloatDiv(ValueNode x, ValueNode y) {
1119         return FloatDivNode.create(x, y);
1120     }
1121 
1122     protected ValueNode genFloatRem(ValueNode x, ValueNode y) {
1123         return new RemNode(x, y);
1124     }
1125 
1126     protected ValueNode genIntegerDiv(ValueNode x, ValueNode y) {
1127         return new SignedDivNode(x, y);
1128     }
1129 
1130     protected ValueNode genIntegerRem(ValueNode x, ValueNode y) {
1131         return new SignedRemNode(x, y);
1132     }
1133 
1134     protected ValueNode genNegateOp(ValueNode x) {
1135         return NegateNode.create(x);
1136     }
1137 
1138     protected ValueNode genLeftShift(ValueNode x, ValueNode y) {
1139         return LeftShiftNode.create(x, y);
1140     }
1141 
1142     protected ValueNode genRightShift(ValueNode x, ValueNode y) {
1143         return RightShiftNode.create(x, y);
1144     }
1145 
1146     protected ValueNode genUnsignedRightShift(ValueNode x, ValueNode y) {
1147         return new UnsignedRightShiftNode(x, y);
1148     }
1149 
1150     protected ValueNode genAnd(ValueNode x, ValueNode y) {
1151         return AndNode.create(x, y);
1152     }
1153 
1154     protected ValueNode genOr(ValueNode x, ValueNode y) {
1155         return OrNode.create(x, y);
1156     }
1157 
1158     protected ValueNode genXor(ValueNode x, ValueNode y) {
1159         return XorNode.create(x, y);
1160     }
1161 
1162     protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) {
1163         return NormalizeCompareNode.create(x, y, isUnorderedLess, JavaKind.Int, constantReflection);
1164     }
1165 
1166     protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) {
1167         return FloatConvertNode.create(op, input);
1168     }
1169 
1170     protected ValueNode genNarrow(ValueNode input, int bitCount) {
1171         return NarrowNode.create(input, bitCount);
1172     }
1173 
1174     protected ValueNode genSignExtend(ValueNode input, int bitCount) {
1175         return SignExtendNode.create(input, bitCount);
1176     }
1177 
1178     protected ValueNode genZeroExtend(ValueNode input, int bitCount) {
1179         return ZeroExtendNode.create(input, bitCount);
1180     }
1181 
1182     protected void genGoto() {
1183         ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin();
1184         if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
1185             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
1186             int targetBci = currentBlock.getSuccessor(0).startBci;
1187             profilingPlugin.profileGoto(this, method, bci(), targetBci, stateBefore);
1188         }
1189         appendGoto(currentBlock.getSuccessor(0));
1190         assert currentBlock.numNormalSuccessors() == 1;
1191     }
1192 
1193     protected LogicNode genObjectEquals(ValueNode x, ValueNode y) {
1194         return ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y);
1195     }
1196 
1197     protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) {
1198         return IntegerEqualsNode.create(constantReflection, metaAccess, options, null, x, y);
1199     }
1200 
1201     protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) {
1202         return IntegerLessThanNode.create(constantReflection, metaAccess, options, null, x, y);
1203     }
1204 
1205     protected ValueNode genUnique(ValueNode x) {
1206         return graph.addOrUniqueWithInputs(x);
1207     }
1208 
1209     protected LogicNode genUnique(LogicNode x) {
1210         return graph.addOrUniqueWithInputs(x);
1211     }
1212 
1213     protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) {
1214         return new IfNode(condition, falseSuccessor, trueSuccessor, d);
1215     }
1216 
1217     protected void genThrow() {
1218         genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
1219 
1220         ValueNode exception = frameState.pop(JavaKind.Object);
1221         FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
1222         ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck));
1223         lastInstr.setNext(handleException(nonNullException, bci(), false));
1224     }
1225 
1226     protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
1227         return InstanceOfNode.create(type, object);
1228     }
1229 
1230     protected AnchoringNode createAnchor(JavaTypeProfile profile) {
1231         if (profile == null || profile.getNotRecordedProbability() > 0.0) {
1232             return null;
1233         } else {
1234             return append(new ValueAnchorNode(null));
1235         }
1236     }
1237 
1238     protected LogicNode createInstanceOf(TypeReference type, ValueNode object, JavaTypeProfile profile) {
1239         return InstanceOfNode.create(type, object, profile, createAnchor(profile));
1240     }
1241 
1242     protected LogicNode createInstanceOfAllowNull(TypeReference type, ValueNode object, JavaTypeProfile profile) {
1243         return InstanceOfNode.createAllowNull(type, object, profile, createAnchor(profile));
1244     }
1245 
1246     protected ValueNode genConditional(ValueNode x) {
1247         return ConditionalNode.create((LogicNode) x);
1248     }
1249 
1250     protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) {
1251         return new NewInstanceNode(type, fillContents);
1252     }
1253 
1254     protected NewArrayNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents) {
1255         return new NewArrayNode(elementType, length, fillContents);
1256     }
1257 
1258     protected NewMultiArrayNode createNewMultiArray(ResolvedJavaType type, ValueNode[] dimensions) {
1259         return new NewMultiArrayNode(type, dimensions);
1260     }
1261 
1262     protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) {
1263         StampPair stamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, field.getType(), false);
1264         if (stamp == null) {
1265             return LoadFieldNode.create(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(),
1266                             getAssumptions(), receiver, field, false, false);
1267         } else {
1268             return LoadFieldNode.createOverrideStamp(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(),
1269                             stamp, receiver, field, false, false);
1270         }
1271     }
1272 
1273     protected StateSplitProxyNode genVolatileFieldReadProxy(ValueNode fieldRead) {
1274         return new StateSplitProxyNode(fieldRead);
1275     }
1276 
1277     protected ValueNode emitExplicitNullCheck(ValueNode receiver) {
1278         if (StampTool.isPointerNonNull(receiver.stamp())) {
1279             return receiver;
1280         }
1281         BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
1282         AbstractBeginNode falseSucc = graph.add(new BeginNode());
1283         ValueNode nonNullReceiver = graph.addOrUniqueWithInputs(PiNode.create(receiver, objectNonNull(), falseSucc));
1284         append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY));
1285         lastInstr = falseSucc;
1286 
1287         exception.setStateAfter(createFrameState(bci(), exception));
1288         exception.setNext(handleException(exception, bci(), false));
1289         EXPLICIT_EXCEPTIONS.increment(debug);
1290         return nonNullReceiver;
1291     }
1292 
1293     protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
1294         AbstractBeginNode trueSucc = graph.add(new BeginNode());
1295         BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
1296         append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length)), trueSucc, exception, FAST_PATH_PROBABILITY));
1297         lastInstr = trueSucc;
1298 
1299         exception.setStateAfter(createFrameState(bci(), exception));
1300         exception.setNext(handleException(exception, bci(), false));
1301     }
1302 
1303     protected ValueNode genArrayLength(ValueNode x) {
1304         return ArrayLengthNode.create(x, constantReflection);
1305     }
1306 
1307     protected void genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value) {
1308         StoreFieldNode storeFieldNode = new StoreFieldNode(receiver, field, value);
1309         append(storeFieldNode);
1310         storeFieldNode.setStateAfter(this.createFrameState(stream.nextBCI(), storeFieldNode));
1311     }
1312 
1313     /**
1314      * Ensure that concrete classes are at least linked before generating an invoke. Interfaces may
1315      * never be linked so simply return true for them.
1316      *
1317      * @param target
1318      * @return true if the declared holder is an interface or is linked
1319      */
1320     private static boolean callTargetIsResolved(JavaMethod target) {
1321         if (target instanceof ResolvedJavaMethod) {
1322             ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
1323             ResolvedJavaType resolvedType = resolvedTarget.getDeclaringClass();
1324             return resolvedType.isInterface() || resolvedType.isLinked();
1325         }
1326         return false;
1327     }
1328 
1329     protected void genInvokeStatic(int cpi, int opcode) {
1330         JavaMethod target = lookupMethod(cpi, opcode);
1331         genInvokeStatic(target);
1332     }
1333 
1334     void genInvokeStatic(JavaMethod target) {
1335         if (callTargetIsResolved(target)) {
1336             ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
1337             ResolvedJavaType holder = resolvedTarget.getDeclaringClass();
1338             if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue(options)) {
1339                 handleUnresolvedInvoke(target, InvokeKind.Static);
1340             } else {
1341                 ValueNode classInit = null;
1342                 ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
1343                 if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedTarget.getDeclaringClass())) {
1344                     FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
1345                     classInit = classInitializationPlugin.apply(this, resolvedTarget.getDeclaringClass(), stateBefore);
1346                 }
1347 
1348                 ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterCount(false));
1349                 Invoke invoke = appendInvoke(InvokeKind.Static, resolvedTarget, args);
1350                 if (invoke != null) {
1351                     invoke.setClassInit(classInit);
1352                 }
1353             }
1354         } else {
1355             handleUnresolvedInvoke(target, InvokeKind.Static);
1356         }
1357     }
1358 
1359     protected void genInvokeInterface(int cpi, int opcode) {
1360         JavaMethod target = lookupMethod(cpi, opcode);
1361         genInvokeInterface(target);
1362     }
1363 
1364     protected void genInvokeInterface(JavaMethod target) {
1365         if (callTargetIsResolved(target)) {
1366             ValueNode[] args = frameState.popArguments(target.getSignature().getParameterCount(true));
1367             appendInvoke(InvokeKind.Interface, (ResolvedJavaMethod) target, args);
1368         } else {
1369             handleUnresolvedInvoke(target, InvokeKind.Interface);
1370         }
1371     }
1372 
1373     protected void genInvokeDynamic(int cpi, int opcode) {
1374         JavaMethod target = lookupMethod(cpi, opcode);
1375         genInvokeDynamic(target);
1376     }
1377 
1378     void genInvokeDynamic(JavaMethod target) {
1379         if (!(target instanceof ResolvedJavaMethod) || !genDynamicInvokeHelper((ResolvedJavaMethod) target, stream.readCPI4(), INVOKEDYNAMIC)) {
1380             handleUnresolvedInvoke(target, InvokeKind.Static);
1381         }
1382     }
1383 
1384     protected void genInvokeVirtual(int cpi, int opcode) {
1385         JavaMethod target = lookupMethod(cpi, opcode);
1386         genInvokeVirtual(target);
1387     }
1388 
1389     private boolean genDynamicInvokeHelper(ResolvedJavaMethod target, int cpi, int opcode) {
1390         assert opcode == INVOKEDYNAMIC || opcode == INVOKEVIRTUAL;
1391 
1392         InvokeDynamicPlugin invokeDynamicPlugin = graphBuilderConfig.getPlugins().getInvokeDynamicPlugin();
1393 
1394         if (opcode == INVOKEVIRTUAL && invokeDynamicPlugin != null && !invokeDynamicPlugin.isResolvedDynamicInvoke(this, cpi, opcode)) {
1395             // regular invokevirtual, let caller handle it
1396             return false;
1397         }
1398 
1399         if (GeneratePIC.getValue(options) && (invokeDynamicPlugin == null || !invokeDynamicPlugin.supportsDynamicInvoke(this, cpi, opcode))) {
1400             // bail out if static compiler and no dynamic type support
1401             append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1402             return true;
1403         }
1404 
1405         JavaConstant appendix = constantPool.lookupAppendix(cpi, opcode);
1406         ValueNode appendixNode = null;
1407 
1408         if (appendix != null) {
1409             if (invokeDynamicPlugin != null) {
1410                 invokeDynamicPlugin.recordDynamicMethod(this, cpi, opcode, target);
1411 
1412                 // Will perform runtime type checks and static initialization
1413                 FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
1414                 appendixNode = invokeDynamicPlugin.genAppendixNode(this, cpi, opcode, appendix, stateBefore);
1415             } else {
1416                 appendixNode = ConstantNode.forConstant(appendix, metaAccess, graph);
1417             }
1418 
1419             frameState.push(JavaKind.Object, appendixNode);
1420 
1421         } else if (GeneratePIC.getValue(options)) {
1422             // Need to emit runtime guard and perform static initialization.
1423             // Not implemented yet.
1424             append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1425             return true;
1426         }
1427 
1428         boolean hasReceiver = (opcode == INVOKEDYNAMIC) ? false : !target.isStatic();
1429         ValueNode[] args = frameState.popArguments(target.getSignature().getParameterCount(hasReceiver));
1430         if (hasReceiver) {
1431             appendInvoke(InvokeKind.Virtual, target, args);
1432         } else {
1433             appendInvoke(InvokeKind.Static, target, args);
1434         }
1435 
1436         return true;
1437     }
1438 
1439     void genInvokeVirtual(JavaMethod target) {
1440         if (!genInvokeVirtualHelper(target)) {
1441             handleUnresolvedInvoke(target, InvokeKind.Virtual);
1442         }
1443     }
1444 
1445     private boolean genInvokeVirtualHelper(JavaMethod target) {
1446         if (!callTargetIsResolved(target)) {
1447             return false;
1448         }
1449 
1450         ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
1451         int cpi = stream.readCPI();
1452 
1453         /*
1454          * Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...) or
1455          * MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see
1456          * https://wiki.openjdk.java.net/display/HotSpot/Method+handles+and+invokedynamic
1457          */
1458 
1459         if (genDynamicInvokeHelper(resolvedTarget, cpi, INVOKEVIRTUAL)) {
1460             return true;
1461         }
1462 
1463         ValueNode[] args = frameState.popArguments(target.getSignature().getParameterCount(true));
1464         appendInvoke(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
1465 
1466         return true;
1467     }
1468 
1469     protected void genInvokeSpecial(int cpi, int opcode) {
1470         JavaMethod target = lookupMethod(cpi, opcode);
1471         genInvokeSpecial(target);
1472     }
1473 
1474     void genInvokeSpecial(JavaMethod target) {
1475         if (callTargetIsResolved(target)) {
1476             assert target != null;
1477             assert target.getSignature() != null;
1478             ValueNode[] args = frameState.popArguments(target.getSignature().getParameterCount(true));
1479             appendInvoke(InvokeKind.Special, (ResolvedJavaMethod) target, args);
1480         } else {
1481             handleUnresolvedInvoke(target, InvokeKind.Special);
1482         }
1483     }
1484 
1485     static class CurrentInvoke {
1486         final ValueNode[] args;
1487         final InvokeKind kind;
1488         final JavaType returnType;
1489 
1490         CurrentInvoke(ValueNode[] args, InvokeKind kind, JavaType returnType) {
1491             this.args = args;
1492             this.kind = kind;
1493             this.returnType = returnType;
1494         }
1495     }
1496 
1497     private CurrentInvoke currentInvoke;
1498     protected FrameStateBuilder frameState;
1499     protected BciBlock currentBlock;
1500     protected final BytecodeStream stream;
1501     protected final GraphBuilderConfiguration graphBuilderConfig;
1502     protected final ResolvedJavaMethod method;
1503     protected final Bytecode code;
1504     protected final BytecodeProvider bytecodeProvider;
1505     protected final ProfilingInfo profilingInfo;
1506     protected final OptimisticOptimizations optimisticOpts;
1507     protected final ConstantPool constantPool;
1508     protected final MetaAccessProvider metaAccess;
1509     private final ConstantReflectionProvider constantReflection;
1510     private final ConstantFieldProvider constantFieldProvider;
1511     private final StampProvider stampProvider;
1512     protected final IntrinsicContext intrinsicContext;
1513 
1514     @Override
1515     public InvokeKind getInvokeKind() {
1516         return currentInvoke == null ? null : currentInvoke.kind;
1517     }
1518 
1519     @Override
1520     public JavaType getInvokeReturnType() {
1521         return currentInvoke == null ? null : currentInvoke.returnType;
1522     }
1523 
1524     private boolean forceInliningEverything;
1525 
1526     @Override
1527     public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) {
1528         boolean previous = forceInliningEverything;
1529         forceInliningEverything = previous || inlineEverything;
1530         try {
1531             appendInvoke(invokeKind, targetMethod, args);
1532         } finally {
1533             forceInliningEverything = previous;
1534         }
1535     }
1536 
1537     @Override
1538     public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
1539         BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1540         ExceptionEdgeAction exceptionEdgeAction = intrinsicCallSiteParser == null ? getActionForInvokeExceptionEdge(null) : intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null);
1541         createNonInlinedInvoke(exceptionEdgeAction, bci(), callTarget, resultType);
1542     }
1543 
1544     protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
1545         ResolvedJavaMethod targetMethod = initialTargetMethod;
1546         InvokeKind invokeKind = initialInvokeKind;
1547         if (initialInvokeKind.isIndirect()) {
1548             ResolvedJavaType contextType = this.frameState.getMethod().getDeclaringClass();
1549             ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(initialInvokeKind, args[0], initialTargetMethod, contextType);
1550             if (specialCallTarget != null) {
1551                 invokeKind = InvokeKind.Special;
1552                 targetMethod = specialCallTarget;
1553             }
1554         }
1555 
1556         JavaKind resultType = targetMethod.getSignature().getReturnKind();
1557         if (!parsingIntrinsic() && DeoptALot.getValue(options)) {
1558             append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
1559             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, graph));
1560             return null;
1561         }
1562 
1563         JavaType returnType = targetMethod.getSignature().getReturnType(method.getDeclaringClass());
1564         if (graphBuilderConfig.eagerResolving() || parsingIntrinsic()) {
1565             returnType = returnType.resolve(targetMethod.getDeclaringClass());
1566         }
1567         if (invokeKind.hasReceiver()) {
1568             args[0] = emitExplicitExceptions(args[0]);
1569         }
1570 
1571         if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) {
1572             emitCheckForInvokeSuperSpecial(args);
1573         }
1574 
1575         InlineInfo inlineInfo = null;
1576         try {
1577             currentInvoke = new CurrentInvoke(args, invokeKind, returnType);
1578             if (tryNodePluginForInvocation(args, targetMethod)) {
1579                 if (TraceParserPlugins.getValue(options)) {
1580                     traceWithContext("used node plugin for %s", targetMethod.format("%h.%n(%p)"));
1581                 }
1582                 return null;
1583             }
1584 
1585             if (invokeKind.hasReceiver() && args[0].isNullConstant()) {
1586                 append(new DeoptimizeNode(InvalidateRecompile, NullCheckException));
1587                 return null;
1588             }
1589 
1590             if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) {
1591                 if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) {
1592                     if (TraceParserPlugins.getValue(options)) {
1593                         traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
1594                     }
1595                     return null;
1596                 }
1597             }
1598             if (invokeKind.isDirect()) {
1599 
1600                 inlineInfo = tryInline(args, targetMethod);
1601                 if (inlineInfo == SUCCESSFULLY_INLINED) {
1602                     return null;
1603                 }
1604             }
1605         } finally {
1606             currentInvoke = null;
1607         }
1608 
1609         int invokeBci = bci();
1610         JavaTypeProfile profile = getProfileForInvoke(invokeKind);
1611         ExceptionEdgeAction edgeAction = getActionForInvokeExceptionEdge(inlineInfo);
1612         boolean partialIntrinsicExit = false;
1613         if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
1614             partialIntrinsicExit = true;
1615             ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod();
1616             BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1617             if (intrinsicCallSiteParser != null) {
1618                 // When exiting a partial intrinsic, the invoke to the original
1619                 // must use the same context as the call to the intrinsic.
1620                 invokeBci = intrinsicCallSiteParser.bci();
1621                 profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind);
1622                 edgeAction = intrinsicCallSiteParser.getActionForInvokeExceptionEdge(inlineInfo);
1623             } else {
1624                 // We are parsing the intrinsic for the root compilation or for inlining,
1625                 // This call is a partial intrinsic exit, and we do not have profile information
1626                 // for this callsite. We also have to assume that the call needs an exception
1627                 // edge. Finally, we know that this intrinsic is parsed for late inlining,
1628                 // so the bci must be set to unknown, so that the inliner patches it later.
1629                 assert intrinsicContext.isPostParseInlined();
1630                 invokeBci = BytecodeFrame.UNKNOWN_BCI;
1631                 profile = null;
1632                 edgeAction = graph.method().getAnnotation(Snippet.class) == null ? ExceptionEdgeAction.INCLUDE_AND_HANDLE : ExceptionEdgeAction.OMIT;
1633             }
1634 
1635             if (originalMethod.isStatic()) {
1636                 invokeKind = InvokeKind.Static;
1637             } else {
1638                 // The original call to the intrinsic must have been devirtualized
1639                 // otherwise we wouldn't be here.
1640                 invokeKind = InvokeKind.Special;
1641             }
1642             Signature sig = originalMethod.getSignature();
1643             returnType = sig.getReturnType(method.getDeclaringClass());
1644             resultType = sig.getReturnKind();
1645             assert intrinsicContext.allowPartialIntrinsicArgumentMismatch() || checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
1646             targetMethod = originalMethod;
1647         }
1648         Invoke invoke = createNonInlinedInvoke(edgeAction, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
1649         if (partialIntrinsicExit) {
1650             // This invoke must never be later inlined as it might select the intrinsic graph.
1651             // Until there is a mechanism to guarantee that any late inlining will not select
1652             // the intrinsic graph, prevent this invoke from being inlined.
1653             invoke.setUseForInlining(false);
1654         }
1655         return invoke;
1656     }
1657 
1658     /**
1659      * Checks that the class of the receiver of an {@link Bytecodes#INVOKESPECIAL} in a method
1660      * declared in an interface (i.e., a default method) is assignable to the interface. If not,
1661      * then deoptimize so that the interpreter can throw an {@link IllegalAccessError}.
1662      *
1663      * This is a check not performed by the verifier and so must be performed at runtime.
1664      *
1665      * @param args arguments to an {@link Bytecodes#INVOKESPECIAL} implementing a direct call to a
1666      *            method in a super class
1667      */
1668     protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) {
1669         ResolvedJavaType callingClass = method.getDeclaringClass();
1670         if (callingClass.getHostClass() != null) {
1671             callingClass = callingClass.getHostClass();
1672         }
1673         if (callingClass.isInterface()) {
1674             ValueNode receiver = args[0];
1675             TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), callingClass);
1676             LogicNode condition = genUnique(createInstanceOf(checkedType, receiver, null));
1677             FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, ClassCastException, None, false));
1678             args[0] = append(PiNode.create(receiver, StampFactory.object(checkedType, true), fixedGuard));
1679         }
1680     }
1681 
1682     protected JavaTypeProfile getProfileForInvoke(InvokeKind invokeKind) {
1683         if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
1684             return profilingInfo.getTypeProfile(bci());
1685         }
1686         return null;
1687     }
1688 
1689     /**
1690      * A partial intrinsic exits by (effectively) calling the intrinsified method. This call must
1691      * use exactly the arguments to the call being intrinsified.
1692      *
1693      * @param originalArgs arguments of original call to intrinsified method
1694      * @param recursiveArgs arguments of recursive call to intrinsified method
1695      */
1696     private static boolean checkPartialIntrinsicExit(ValueNode[] originalArgs, ValueNode[] recursiveArgs) {
1697         if (originalArgs != null) {
1698             for (int i = 0; i < originalArgs.length; i++) {
1699                 ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]);
1700                 ValueNode icArg = GraphUtil.unproxify(originalArgs[i]);
1701                 assert arg == icArg : String.format("argument %d of call denoting partial intrinsic exit should be %s, not %s", i, icArg, arg);
1702             }
1703         } else {
1704             for (int i = 0; i < recursiveArgs.length; i++) {
1705                 ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]);
1706                 assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s",
1707                                 i, ParameterNode.class.getSimpleName(), i, arg);
1708             }
1709         }
1710         return true;
1711     }
1712 
1713     protected Invoke createNonInlinedInvoke(ExceptionEdgeAction exceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod,
1714                     InvokeKind invokeKind, JavaKind resultType, JavaType returnType, JavaTypeProfile profile) {
1715 
1716         StampPair returnStamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, returnType, false);
1717         if (returnStamp == null) {
1718             returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false);
1719         }
1720 
1721         MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile));
1722         Invoke invoke = createNonInlinedInvoke(exceptionEdge, invokeBci, callTarget, resultType);
1723 
1724         for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
1725             plugin.notifyNotInlined(this, targetMethod, invoke);
1726         }
1727 
1728         return invoke;
1729     }
1730 
1731     protected Invoke createNonInlinedInvoke(ExceptionEdgeAction exceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
1732         if (exceptionEdge == ExceptionEdgeAction.OMIT) {
1733             return createInvoke(invokeBci, callTarget, resultType);
1734         } else {
1735             Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType, exceptionEdge);
1736             AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any()));
1737             invoke.setNext(beginNode);
1738             lastInstr = beginNode;
1739             return invoke;
1740         }
1741     }
1742 
1743     /**
1744      * Describes what should be done with the exception edge of an invocation. The edge can be
1745      * omitted or included. An included edge can handle the exception or transfer execution to the
1746      * interpreter for handling (deoptimize).
1747      */
1748     protected enum ExceptionEdgeAction {
1749         OMIT,
1750         INCLUDE_AND_HANDLE,
1751         INCLUDE_AND_DEOPTIMIZE
1752     }
1753 
1754     protected ExceptionEdgeAction getActionForInvokeExceptionEdge(InlineInfo lastInlineInfo) {
1755         if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) {
1756             return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
1757         } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) {
1758             return ExceptionEdgeAction.OMIT;
1759         } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION) {
1760             return ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE;
1761         } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) {
1762             return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
1763         } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) {
1764             return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
1765         } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) {
1766             return ExceptionEdgeAction.OMIT;
1767         } else {
1768             assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile;
1769             // be conservative if information was not recorded (could result in endless
1770             // recompiles otherwise)
1771             if (!StressInvokeWithExceptionNode.getValue(options)) {
1772                 if (optimisticOpts.useExceptionProbability(getOptions())) {
1773                     if (profilingInfo != null) {
1774                         TriState exceptionSeen = profilingInfo.getExceptionSeen(bci());
1775                         if (exceptionSeen == TriState.FALSE) {
1776                             return ExceptionEdgeAction.OMIT;
1777                         }
1778                     }
1779                 }
1780             }
1781             return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
1782         }
1783     }
1784 
1785     /**
1786      * Contains all the assertion checking logic around the application of an
1787      * {@link InvocationPlugin}. This class is only loaded when assertions are enabled.
1788      */
1789     class InvocationPluginAssertions {
1790         final InvocationPlugin plugin;
1791         final ValueNode[] args;
1792         final ResolvedJavaMethod targetMethod;
1793         final JavaKind resultType;
1794         final int beforeStackSize;
1795         final boolean needsNullCheck;
1796         final int nodeCount;
1797         final Mark mark;
1798 
1799         InvocationPluginAssertions(InvocationPlugin plugin, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) {
1800             guarantee(Assertions.assertionsEnabled(), "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName());
1801             this.plugin = plugin;
1802             this.targetMethod = targetMethod;
1803             this.args = args;
1804             this.resultType = resultType;
1805             this.beforeStackSize = frameState.stackSize();
1806             this.needsNullCheck = !targetMethod.isStatic() && args[0].getStackKind() == JavaKind.Object && !StampTool.isPointerNonNull(args[0].stamp());
1807             this.nodeCount = graph.getNodeCount();
1808             this.mark = graph.getMark();
1809         }
1810 
1811         String error(String format, Object... a) {
1812             return String.format(format, a) + String.format("%n\tplugin at %s", plugin.getApplySourceLocation(metaAccess));
1813         }
1814 
1815         boolean check(boolean pluginResult) {
1816             if (pluginResult == true) {
1817                 int expectedStackSize = beforeStackSize + resultType.getSlotCount();
1818                 assert expectedStackSize == frameState.stackSize() : error("plugin manipulated the stack incorrectly: expected=%d, actual=%d", expectedStackSize, frameState.stackSize());
1819                 NodeIterable<Node> newNodes = graph.getNewNodes(mark);
1820                 assert !needsNullCheck || isPointerNonNull(args[0].stamp()) : error("plugin needs to null check the receiver of %s: receiver=%s", targetMethod.format("%H.%n(%p)"), args[0]);
1821                 for (Node n : newNodes) {
1822                     if (n instanceof StateSplit) {
1823                         StateSplit stateSplit = (StateSplit) n;
1824                         assert stateSplit.stateAfter() != null || !stateSplit.hasSideEffect() : error("%s node added by plugin for %s need to have a non-null frame state: %s",
1825                                         StateSplit.class.getSimpleName(), targetMethod.format("%H.%n(%p)"), stateSplit);
1826                     }
1827                 }
1828                 try {
1829                     graphBuilderConfig.getPlugins().getInvocationPlugins().checkNewNodes(BytecodeParser.this, plugin, newNodes);
1830                 } catch (Throwable t) {
1831                     throw new AssertionError(error("Error in plugin"), t);
1832                 }
1833             } else {
1834                 assert nodeCount == graph.getNodeCount() : error("plugin that returns false must not create new nodes");
1835                 assert beforeStackSize == frameState.stackSize() : error("plugin that returns false must not modify the stack");
1836             }
1837             return true;
1838         }
1839     }
1840 
1841     protected static class IntrinsicGuard {
1842         final FixedWithNextNode lastInstr;
1843         final Mark mark;
1844         final AbstractBeginNode nonIntrinsicBranch;
1845         final ValueNode receiver;
1846         final JavaTypeProfile profile;
1847 
1848         public IntrinsicGuard(FixedWithNextNode lastInstr, ValueNode receiver, Mark mark, AbstractBeginNode nonIntrinsicBranch, JavaTypeProfile profile) {
1849             this.lastInstr = lastInstr;
1850             this.receiver = receiver;
1851             this.mark = mark;
1852             this.nonIntrinsicBranch = nonIntrinsicBranch;
1853             this.profile = profile;
1854         }
1855     }
1856 
1857     /**
1858      * Weaves a test of the receiver type to ensure the dispatch will select {@code targetMethod}
1859      * and not another method that overrides it. This should only be called if there is an intrinsic
1860      * (i.e., an {@link InvocationPlugin}) for {@code targetMethod} and the invocation is indirect.
1861      *
1862      * The control flow woven around the intrinsic is as follows:
1863      *
1864      * <pre>
1865      *  if (LoadMethod(LoadHub(receiver)) == targetMethod) {
1866      *       <intrinsic for targetMethod>
1867      *  } else {
1868      *       <virtual call to targetMethod>
1869      *  }
1870      * </pre>
1871      *
1872      * The {@code else} branch is woven by {@link #afterInvocationPluginExecution}.
1873      *
1874      * @return {@code null} if the intrinsic cannot be used otherwise an object to be used by
1875      *         {@link #afterInvocationPluginExecution} to weave code for the non-intrinsic branch
1876      */
1877     protected IntrinsicGuard guardIntrinsic(ValueNode[] args, ResolvedJavaMethod targetMethod, InvocationPluginReceiver pluginReceiver) {
1878         ValueNode intrinsicReceiver = args[0];
1879         ResolvedJavaType receiverType = StampTool.typeOrNull(intrinsicReceiver);
1880         if (receiverType == null) {
1881             // The verifier guarantees it to be at least type declaring targetMethod
1882             receiverType = targetMethod.getDeclaringClass();
1883         }
1884         ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass());
1885         if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) {
1886             assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass());
1887             Mark mark = graph.getMark();
1888             FixedWithNextNode currentLastInstr = lastInstr;
1889             ValueNode nonNullReceiver = pluginReceiver.get();
1890             Stamp methodStamp = stampProvider.createMethodStamp();
1891             LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
1892             LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
1893             ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
1894             LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected));
1895 
1896             JavaTypeProfile profile = null;
1897             if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
1898                 profile = profilingInfo.getTypeProfile(bci());
1899                 if (profile != null) {
1900                     JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
1901                     if (newProfile != profile) {
1902                         if (newProfile.getTypes().length == 0) {
1903                             // All profiled types select the intrinsic so
1904                             // emit a fixed guard instead of an if-then-else.
1905                             lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
1906                             return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
1907                         }
1908                     } else {
1909                         // No profiled types select the intrinsic so emit a virtual call
1910                         return null;
1911                     }
1912                     profile = newProfile;
1913                 }
1914             }
1915 
1916             AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
1917             AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
1918             append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY));
1919             lastInstr = intrinsicBranch;
1920             return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
1921         } else {
1922             // Receiver selects an overriding method so emit a virtual call
1923             return null;
1924         }
1925     }
1926 
1927     /**
1928      * Adjusts the profile for an indirect invocation of a virtual method for which there is an
1929      * intrinsic. The adjustment made by this method is to remove all types from the profile that do
1930      * not override {@code targetMethod}.
1931      *
1932      * @param profile the profile to adjust
1933      * @param targetMethod the virtual method for which there is an intrinsic
1934      * @return the adjusted profile or the original {@code profile} object if no adjustment was made
1935      */
1936     protected JavaTypeProfile adjustProfileForInvocationPlugin(JavaTypeProfile profile, ResolvedJavaMethod targetMethod) {
1937         if (profile.getTypes().length > 0) {
1938             List<ProfiledType> retained = new ArrayList<>();
1939             double notRecordedProbability = profile.getNotRecordedProbability();
1940             for (ProfiledType ptype : profile.getTypes()) {
1941                 if (!ptype.getType().resolveMethod(targetMethod, method.getDeclaringClass()).equals(targetMethod)) {
1942                     retained.add(ptype);
1943                 } else {
1944                     notRecordedProbability += ptype.getProbability();
1945                 }
1946             }
1947             if (!retained.isEmpty()) {
1948                 if (retained.size() != profile.getTypes().length) {
1949                     return new JavaTypeProfile(profile.getNullSeen(), notRecordedProbability, retained.toArray(new ProfiledType[retained.size()]));
1950                 }
1951             } else {
1952                 return new JavaTypeProfile(profile.getNullSeen(), notRecordedProbability, new ProfiledType[0]);
1953             }
1954         }
1955         return profile;
1956     }
1957 
1958     /**
1959      * Performs any action required after execution of an invocation plugin. This includes
1960      * {@linkplain InvocationPluginAssertions#check checking} invocation plugin invariants as well
1961      * as weaving the {@code else} branch of the code woven by {@link #guardIntrinsic} if
1962      * {@code guard != null}.
1963      */
1964     protected void afterInvocationPluginExecution(boolean pluginHandledInvoke, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard,
1965                     InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
1966         assert assertions.check(pluginHandledInvoke);
1967         if (intrinsicGuard != null) {
1968             if (pluginHandledInvoke) {
1969                 if (intrinsicGuard.nonIntrinsicBranch != null) {
1970                     // Intrinsic emitted: emit a virtual call to the target method and
1971                     // merge it with the intrinsic branch
1972                     EndNode intrinsicEnd = append(new EndNode());
1973 
1974                     FrameStateBuilder intrinsicState = null;
1975                     FrameStateBuilder nonIntrinisicState = null;
1976                     if (resultType != JavaKind.Void) {
1977                         intrinsicState = frameState.copy();
1978                         frameState.pop(resultType);
1979                         nonIntrinisicState = frameState;
1980                     }
1981 
1982                     lastInstr = intrinsicGuard.nonIntrinsicBranch;
1983                     createNonInlinedInvoke(getActionForInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
1984 
1985                     EndNode nonIntrinsicEnd = append(new EndNode());
1986                     AbstractMergeNode mergeNode = graph.add(new MergeNode());
1987 
1988                     mergeNode.addForwardEnd(intrinsicEnd);
1989                     if (intrinsicState != null) {
1990                         intrinsicState.merge(mergeNode, nonIntrinisicState);
1991                         frameState = intrinsicState;
1992                     }
1993                     mergeNode.addForwardEnd(nonIntrinsicEnd);
1994                     mergeNode.setStateAfter(frameState.create(stream.nextBCI(), mergeNode));
1995 
1996                     lastInstr = mergeNode;
1997                 }
1998             } else {
1999                 // Intrinsic was not applied: remove intrinsic guard
2000                 // and restore the original receiver node in the arguments array
2001                 intrinsicGuard.lastInstr.setNext(null);
2002                 GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
2003                 lastInstr = intrinsicGuard.lastInstr;
2004                 args[0] = intrinsicGuard.receiver;
2005             }
2006         }
2007     }
2008 
2009     protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
2010         InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
2011         if (plugin != null) {
2012 
2013             if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
2014                 // Self recursive intrinsic means the original
2015                 // method should be called.
2016                 assert !targetMethod.hasBytecodes() : "TODO: when does this happen?";
2017                 return false;
2018             }
2019 
2020             InvocationPluginReceiver pluginReceiver = invocationPluginReceiver.init(targetMethod, args);
2021 
2022             IntrinsicGuard intrinsicGuard = null;
2023             if (invokeKind.isIndirect()) {
2024                 intrinsicGuard = guardIntrinsic(args, targetMethod, pluginReceiver);
2025                 if (intrinsicGuard == null) {
2026                     return false;
2027                 } else if (intrinsicGuard.nonIntrinsicBranch == null) {
2028                     assert lastInstr instanceof FixedGuardNode;
2029                 }
2030             }
2031 
2032             InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
2033             if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
2034                 afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
2035                 return true;
2036             } else {
2037                 afterInvocationPluginExecution(false, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
2038             }
2039         }
2040         return false;
2041     }
2042 
2043     private boolean tryNodePluginForInvocation(ValueNode[] args, ResolvedJavaMethod targetMethod) {
2044         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
2045             if (plugin.handleInvoke(this, targetMethod, args)) {
2046                 return true;
2047             }
2048         }
2049         return false;
2050     }
2051 
2052     private static final InlineInfo SUCCESSFULLY_INLINED = InlineInfo.createStandardInlineInfo(null);
2053 
2054     /**
2055      * Try to inline a method. If the method was inlined, returns {@link #SUCCESSFULLY_INLINED}.
2056      * Otherwise, it returns the {@link InlineInfo} that lead to the decision to not inline it, or
2057      * {@code null} if there is no {@link InlineInfo} for this method.
2058      */
2059     private InlineInfo tryInline(ValueNode[] args, ResolvedJavaMethod targetMethod) {
2060         boolean canBeInlined = forceInliningEverything || parsingIntrinsic() || targetMethod.canBeInlined();
2061         if (!canBeInlined) {
2062             return null;
2063         }
2064 
2065         if (forceInliningEverything) {
2066             if (inline(targetMethod, targetMethod, null, args)) {
2067                 return SUCCESSFULLY_INLINED;
2068             } else {
2069                 return null;
2070             }
2071         }
2072 
2073         for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
2074             InlineInfo inlineInfo = plugin.shouldInlineInvoke(this, targetMethod, args);
2075             if (inlineInfo != null) {
2076                 if (inlineInfo.getMethodToInline() != null) {
2077                     if (inline(targetMethod, inlineInfo.getMethodToInline(), inlineInfo.getIntrinsicBytecodeProvider(), args)) {
2078                         return SUCCESSFULLY_INLINED;
2079                     }
2080                     inlineInfo = null;
2081                 }
2082                 /* Do not inline, and do not ask the remaining plugins. */
2083                 return inlineInfo;
2084             }
2085         }
2086 
2087         // There was no inline plugin with a definite answer to whether or not
2088         // to inline. If we're parsing an intrinsic, then we need to enforce the
2089         // invariant here that methods are always force inlined in intrinsics/snippets.
2090         if (parsingIntrinsic()) {
2091             if (inline(targetMethod, targetMethod, this.bytecodeProvider, args)) {
2092                 return SUCCESSFULLY_INLINED;
2093             }
2094         }
2095         return null;
2096     }
2097 
2098     private static final int ACCESSOR_BYTECODE_LENGTH = 5;
2099 
2100     /**
2101      * Tries to inline {@code targetMethod} if it is an instance field accessor. This avoids the
2102      * overhead of creating and using a nested {@link BytecodeParser} object.
2103      */
2104     private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targetMethod) {
2105         byte[] bytecode = targetMethod.getCode();
2106         if (bytecode != null && bytecode.length == ACCESSOR_BYTECODE_LENGTH &&
2107                         Bytes.beU1(bytecode, 0) == ALOAD_0 &&
2108                         Bytes.beU1(bytecode, 1) == GETFIELD) {
2109             int b4 = Bytes.beU1(bytecode, 4);
2110             if (b4 >= IRETURN && b4 <= ARETURN) {
2111                 int cpi = Bytes.beU2(bytecode, 2);
2112                 JavaField field = targetMethod.getConstantPool().lookupField(cpi, targetMethod, GETFIELD);
2113                 if (field instanceof ResolvedJavaField) {
2114                     ValueNode receiver = invocationPluginReceiver.init(targetMethod, args).get();
2115                     ResolvedJavaField resolvedField = (ResolvedJavaField) field;
2116                     genGetField(resolvedField, receiver);
2117                     notifyBeforeInline(targetMethod);
2118                     printInlining(targetMethod, targetMethod, true, "inline accessor method (bytecode parsing)");
2119                     notifyAfterInline(targetMethod);
2120                     return true;
2121                 }
2122             }
2123         }
2124         return false;
2125     }
2126 
2127     @Override
2128     public boolean intrinsify(BytecodeProvider intrinsicBytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) {
2129         if (receiver != null) {
2130             receiver.get();
2131         }
2132         boolean res = inline(targetMethod, substitute, intrinsicBytecodeProvider, args);
2133         assert res : "failed to inline " + substitute;
2134         return res;
2135     }
2136 
2137     private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) {
2138         IntrinsicContext intrinsic = this.intrinsicContext;
2139 
2140         if (intrinsic == null && !graphBuilderConfig.insertFullInfopoints() &&
2141                         targetMethod.equals(inlinedMethod) &&
2142                         (targetMethod.getModifiers() & (STATIC | SYNCHRONIZED)) == 0 &&
2143                         tryFastInlineAccessor(args, targetMethod)) {
2144             return true;
2145         }
2146 
2147         if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
2148             if (intrinsic.isCompilationRoot()) {
2149                 // A root compiled intrinsic needs to deoptimize
2150                 // if the slow path is taken. During frame state
2151                 // assignment, the deopt node will get its stateBefore
2152                 // from the start node of the intrinsic
2153                 append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
2154                 printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
2155                 return true;
2156             } else {
2157                 if (intrinsic.getOriginalMethod().isNative()) {
2158                     printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
2159                     return false;
2160                 }
2161                 if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) {
2162                     // Otherwise inline the original method. Any frame state created
2163                     // during the inlining will exclude frame(s) in the
2164                     // intrinsic method (see FrameStateBuilder.create(int bci)).
2165                     notifyBeforeInline(inlinedMethod);
2166                     printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
2167                     parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
2168                     notifyAfterInline(inlinedMethod);
2169                     return true;
2170                 } else {
2171                     printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)");
2172                     return false;
2173                 }
2174             }
2175         } else {
2176             boolean isIntrinsic = intrinsicBytecodeProvider != null;
2177             if (intrinsic == null && isIntrinsic) {
2178                 assert !inlinedMethod.equals(targetMethod);
2179                 intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING);
2180             }
2181             if (inlinedMethod.hasBytecodes()) {
2182                 notifyBeforeInline(inlinedMethod);
2183                 printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)");
2184                 parseAndInlineCallee(inlinedMethod, args, intrinsic);
2185                 notifyAfterInline(inlinedMethod);
2186             } else {
2187                 printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)");
2188                 return false;
2189             }
2190         }
2191         return true;
2192     }
2193 
2194     protected void notifyBeforeInline(ResolvedJavaMethod inlinedMethod) {
2195         for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
2196             plugin.notifyBeforeInline(inlinedMethod);
2197         }
2198     }
2199 
2200     protected void notifyAfterInline(ResolvedJavaMethod inlinedMethod) {
2201         for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
2202             plugin.notifyAfterInline(inlinedMethod);
2203         }
2204     }
2205 
2206     /**
2207      * Determines if a partial intrinsic exit (i.e., a call to the original method within an
2208      * intrinsic) can be inlined.
2209      */
2210     protected boolean canInlinePartialIntrinsicExit() {
2211         return true;
2212     }
2213 
2214     private void printInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, boolean success, String msg) {
2215         if (success) {
2216             if (TraceInlineDuringParsing.getValue(options) || TraceParserPlugins.getValue(options)) {
2217                 if (targetMethod.equals(inlinedMethod)) {
2218                     traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)"));
2219                 } else {
2220                     traceWithContext("inlining call to %s as intrinsic for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)"));
2221                 }
2222             }
2223         }
2224         if (HotSpotPrintInlining.getValue(options)) {
2225             if (targetMethod.equals(inlinedMethod)) {
2226                 Util.printInlining(inlinedMethod, bci(), getDepth(), success, "%s", msg);
2227             } else {
2228                 Util.printInlining(inlinedMethod, bci(), getDepth(), success, "%s intrinsic for %s", msg, targetMethod.format("%h.%n(%p)"));
2229             }
2230         }
2231     }
2232 
2233     /**
2234      * Prints a line to {@link TTY} with a prefix indicating the current parse context. The prefix
2235      * is of the form:
2236      *
2237      * <pre>
2238      * {SPACE * n} {name of method being parsed} "(" {file name} ":" {line number} ")"
2239      * </pre>
2240      *
2241      * where {@code n} is the current inlining depth.
2242      *
2243      * @param format a format string
2244      * @param args arguments to the format string
2245      */
2246 
2247     protected void traceWithContext(String format, Object... args) {
2248         StackTraceElement where = code.asStackTraceElement(bci());
2249         String s = format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(),
2250                         format(format, args));
2251         TTY.println(s);
2252     }
2253 
2254     protected RuntimeException throwParserError(Throwable e) {
2255         if (e instanceof BytecodeParserError) {
2256             throw (BytecodeParserError) e;
2257         }
2258         BytecodeParser bp = this;
2259         BytecodeParserError res = new BytecodeParserError(e);
2260         while (bp != null) {
2261             res.addContext("parsing " + bp.code.asStackTraceElement(bp.bci()));
2262             bp = bp.parent;
2263         }
2264         throw res;
2265     }
2266 
2267     protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) {
2268         try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) {
2269 
2270             BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
2271             FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph);
2272             if (!targetMethod.isStatic()) {
2273                 args[0] = nullCheckedValue(args[0]);
2274             }
2275             startFrameState.initializeFromArgumentsArray(args);
2276             parser.build(this.lastInstr, startFrameState);
2277 
2278             if (parser.returnDataList == null) {
2279                 /* Callee does not return. */
2280                 lastInstr = null;
2281             } else {
2282                 ValueNode calleeReturnValue;
2283                 MergeNode returnMergeNode = null;
2284                 if (s != null) {
2285                     s.returnDataList = parser.returnDataList;
2286                 }
2287                 if (parser.returnDataList.size() == 1) {
2288                     /* Callee has a single return, we can continue parsing at that point. */
2289                     ReturnToCallerData singleReturnData = parser.returnDataList.get(0);
2290                     lastInstr = singleReturnData.beforeReturnNode;
2291                     calleeReturnValue = singleReturnData.returnValue;
2292                 } else {
2293                     assert parser.returnDataList.size() > 1;
2294                     /* Callee has multiple returns, we need to insert a control flow merge. */
2295                     returnMergeNode = graph.add(new MergeNode());
2296                     calleeReturnValue = ValueMergeUtil.mergeValueProducers(returnMergeNode, parser.returnDataList, returnData -> returnData.beforeReturnNode, returnData -> returnData.returnValue);
2297                 }
2298 
2299                 if (calleeReturnValue != null) {
2300                     frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue);
2301                 }
2302                 if (returnMergeNode != null) {
2303                     returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode));
2304                     lastInstr = finishInstruction(returnMergeNode, frameState);
2305                 }
2306             }
2307             /*
2308              * Propagate any side effects into the caller when parsing intrinsics.
2309              */
2310             if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
2311                 for (StateSplit sideEffect : parser.frameState.sideEffects()) {
2312                     frameState.addSideEffect(sideEffect);
2313                 }
2314             }
2315 
2316             FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
2317             if (calleeBeforeUnwindNode != null) {
2318                 ValueNode calleeUnwindValue = parser.getUnwindValue();
2319                 assert calleeUnwindValue != null;
2320                 calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false));
2321             }
2322         }
2323     }
2324 
2325     public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) {
2326         return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, profile);
2327     }
2328 
2329     protected InvokeNode createInvoke(int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
2330         InvokeNode invoke = append(new InvokeNode(callTarget, invokeBci));
2331         frameState.pushReturn(resultType, invoke);
2332         invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
2333         return invoke;
2334     }
2335 
2336     protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType, ExceptionEdgeAction exceptionEdgeAction) {
2337         if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
2338             /*
2339              * Clear non-live locals early so that the exception handler entry gets the cleared
2340              * state.
2341              */
2342             frameState.clearNonLiveLocals(currentBlock, liveness, false);
2343         }
2344 
2345         AbstractBeginNode exceptionEdge = handleException(null, bci(), exceptionEdgeAction == ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE);
2346         InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci));
2347         frameState.pushReturn(resultType, invoke);
2348         invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
2349         return invoke;
2350     }
2351 
2352     protected void genReturn(ValueNode returnVal, JavaKind returnKind) {
2353         if (parsingIntrinsic() && returnVal != null) {
2354             if (returnVal instanceof StateSplit) {
2355                 StateSplit stateSplit = (StateSplit) returnVal;
2356                 FrameState stateAfter = stateSplit.stateAfter();
2357                 if (stateSplit.hasSideEffect()) {
2358                     assert stateSplit != null;
2359                     if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
2360                         assert stateAfter.usages().count() == 1;
2361                         assert stateAfter.usages().first() == stateSplit;
2362                         stateAfter.replaceAtUsages(graph.add(new FrameState(BytecodeFrame.AFTER_BCI, returnVal)));
2363                         GraphUtil.killWithUnusedFloatingInputs(stateAfter);
2364                     } else {
2365                         /*
2366                          * This must be the return value from within a partial intrinsification.
2367                          */
2368                         assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci);
2369                     }
2370                 } else {
2371                     assert stateAfter == null;
2372                 }
2373             }
2374         }
2375 
2376         ValueNode realReturnVal = processReturnValue(returnVal, returnKind);
2377 
2378         frameState.setRethrowException(false);
2379         frameState.clearStack();
2380         beforeReturn(realReturnVal, returnKind);
2381         if (parent == null) {
2382             append(new ReturnNode(realReturnVal));
2383         } else {
2384             if (returnDataList == null) {
2385                 returnDataList = new ArrayList<>();
2386             }
2387             returnDataList.add(new ReturnToCallerData(realReturnVal, lastInstr));
2388             lastInstr = null;
2389         }
2390     }
2391 
2392     private ValueNode processReturnValue(ValueNode value, JavaKind kind) {
2393         JavaKind returnKind = method.getSignature().getReturnKind();
2394         if (kind != returnKind) {
2395             // sub-word integer
2396             assert returnKind.isNumericInteger() && returnKind.getStackKind() == JavaKind.Int;
2397             IntegerStamp stamp = (IntegerStamp) value.stamp();
2398 
2399             // the bytecode verifier doesn't check that the value is in the correct range
2400             if (stamp.lowerBound() < returnKind.getMinValue() || returnKind.getMaxValue() < stamp.upperBound()) {
2401                 ValueNode narrow = append(genNarrow(value, returnKind.getBitCount()));
2402                 if (returnKind.isUnsigned()) {
2403                     return append(genZeroExtend(narrow, 32));
2404                 } else {
2405                     return append(genSignExtend(narrow, 32));
2406                 }
2407             }
2408         }
2409 
2410         return value;
2411     }
2412 
2413     private void beforeReturn(ValueNode x, JavaKind kind) {
2414         if (graph.method() != null && graph.method().isJavaLangObjectInit()) {
2415             /*
2416              * Get the receiver from the initial state since bytecode rewriting could do arbitrary
2417              * things to the state of the locals.
2418              */
2419             ValueNode receiver = graph.start().stateAfter().localAt(0);
2420             assert receiver != null && receiver.getStackKind() == JavaKind.Object;
2421             if (RegisterFinalizerNode.mayHaveFinalizer(receiver, graph.getAssumptions())) {
2422                 append(new RegisterFinalizerNode(receiver));
2423             }
2424         }
2425         genInfoPointNode(InfopointReason.METHOD_END, x);
2426         if (finalBarrierRequired) {
2427             assert originalReceiver != null;
2428             /*
2429              * When compiling an OSR with a final field store, don't bother tracking the original
2430              * receiver since the receiver cannot be EA'ed.
2431              */
2432             append(new FinalFieldBarrierNode(entryBCI == INVOCATION_ENTRY_BCI ? originalReceiver : null));
2433         }
2434         synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x, kind);
2435     }
2436 
2437     protected MonitorEnterNode createMonitorEnterNode(ValueNode x, MonitorIdNode monitorId) {
2438         return new MonitorEnterNode(x, monitorId);
2439     }
2440 
2441     protected void genMonitorEnter(ValueNode x, int bci) {
2442         MonitorIdNode monitorId = graph.add(new MonitorIdNode(frameState.lockDepth(true)));
2443         MonitorEnterNode monitorEnter = append(createMonitorEnterNode(x, monitorId));
2444         frameState.pushLock(x, monitorId);
2445         monitorEnter.setStateAfter(createFrameState(bci, monitorEnter));
2446     }
2447 
2448     protected void genMonitorExit(ValueNode x, ValueNode escapedReturnValue, int bci) {
2449         if (frameState.lockDepth(false) == 0) {
2450             throw bailout("unbalanced monitors: too many exits");
2451         }
2452         MonitorIdNode monitorId = frameState.peekMonitorId();
2453         ValueNode lockedObject = frameState.popLock();
2454         if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) {
2455             throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)));
2456         }
2457         MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedReturnValue));
2458         monitorExit.setStateAfter(createFrameState(bci, monitorExit));
2459     }
2460 
2461     protected void genJsr(int dest) {
2462         BciBlock successor = currentBlock.getJsrSuccessor();
2463         assert successor.startBci == dest : successor.startBci + " != " + dest + " @" + bci();
2464         JsrScope scope = currentBlock.getJsrScope();
2465         int nextBci = getStream().nextBCI();
2466         if (!successor.getJsrScope().pop().equals(scope)) {
2467             throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)");
2468         }
2469         if (successor.getJsrScope().nextReturnAddress() != nextBci) {
2470             throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)");
2471         }
2472         ConstantNode nextBciNode = getJsrConstant(nextBci);
2473         frameState.push(JavaKind.Object, nextBciNode);
2474         appendGoto(successor);
2475     }
2476 
2477     protected void genRet(int localIndex) {
2478         BciBlock successor = currentBlock.getRetSuccessor();
2479         ValueNode local = frameState.loadLocal(localIndex, JavaKind.Object);
2480         JsrScope scope = currentBlock.getJsrScope();
2481         int retAddress = scope.nextReturnAddress();
2482         ConstantNode returnBciNode = getJsrConstant(retAddress);
2483         LogicNode guard = IntegerEqualsNode.create(constantReflection, metaAccess, options, null, local, returnBciNode);
2484         guard = graph.addOrUniqueWithInputs(guard);
2485         append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile));
2486         if (!successor.getJsrScope().equals(scope.pop())) {
2487             throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
2488         }
2489         appendGoto(successor);
2490     }
2491 
2492     private ConstantNode getJsrConstant(long bci) {
2493         JavaConstant nextBciConstant = new RawConstant(bci);
2494         Stamp nextBciStamp = StampFactory.forConstant(nextBciConstant);
2495         ConstantNode nextBciNode = new ConstantNode(nextBciConstant, nextBciStamp);
2496         return graph.unique(nextBciNode);
2497     }
2498 
2499     protected void genIntegerSwitch(ValueNode value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
2500         if (value.isConstant()) {
2501             JavaConstant constant = (JavaConstant) value.asConstant();
2502             int constantValue = constant.asInt();
2503             for (int i = 0; i < keys.length; ++i) {
2504                 if (keys[i] == constantValue) {
2505                     appendGoto(actualSuccessors.get(keySuccessors[i]));
2506                     return;
2507                 }
2508             }
2509             appendGoto(actualSuccessors.get(keySuccessors[keys.length]));
2510         } else {
2511             this.controlFlowSplit = true;
2512             double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities);
2513             IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors));
2514             for (int i = 0; i < actualSuccessors.size(); i++) {
2515                 switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState));
2516             }
2517         }
2518     }
2519 
2520     /**
2521      * Helper function that sums up the probabilities of all keys that lead to a specific successor.
2522      *
2523      * @return an array of size successorCount with the accumulated probability for each successor.
2524      */
2525     private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
2526         double[] probability = new double[successorCount];
2527         for (int i = 0; i < keySuccessors.length; i++) {
2528             probability[keySuccessors[i]] += keyProbabilities[i];
2529         }
2530         return probability;
2531     }
2532 
2533     protected ConstantNode appendConstant(JavaConstant constant) {
2534         assert constant != null;
2535         return ConstantNode.forConstant(constant, metaAccess, graph);
2536     }
2537 
2538     @Override
2539     public <T extends ValueNode> T append(T v) {
2540         if (v.graph() != null) {
2541             return v;
2542         }
2543         T added = graph.addOrUniqueWithInputs(v);
2544         if (added == v) {
2545             updateLastInstruction(v);
2546         }
2547         return added;
2548     }
2549 
2550     private <T extends ValueNode> void updateLastInstruction(T v) {
2551         if (v instanceof FixedNode) {
2552             FixedNode fixedNode = (FixedNode) v;
2553             lastInstr.setNext(fixedNode);
2554             if (fixedNode instanceof FixedWithNextNode) {
2555                 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode;
2556                 assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end";
2557                 lastInstr = fixedWithNextNode;
2558             } else {
2559                 lastInstr = null;
2560             }
2561         }
2562     }
2563 
2564     private Target checkLoopExit(FixedNode target, BciBlock targetBlock, FrameStateBuilder state) {
2565         if (currentBlock != null) {
2566             long exits = currentBlock.loops & ~targetBlock.loops;
2567             if (exits != 0) {
2568                 LoopExitNode firstLoopExit = null;
2569                 LoopExitNode lastLoopExit = null;
2570 
2571                 int pos = 0;
2572                 ArrayList<BciBlock> exitLoops = new ArrayList<>(Long.bitCount(exits));
2573                 do {
2574                     long lMask = 1L << pos;
2575                     if ((exits & lMask) != 0) {
2576                         exitLoops.add(blockMap.getLoopHeader(pos));
2577                         exits &= ~lMask;
2578                     }
2579                     pos++;
2580                 } while (exits != 0);
2581 
2582                 Collections.sort(exitLoops, new Comparator<BciBlock>() {
2583 
2584                     @Override
2585                     public int compare(BciBlock o1, BciBlock o2) {
2586                         return Long.bitCount(o2.loops) - Long.bitCount(o1.loops);
2587                     }
2588                 });
2589 
2590                 int bci = targetBlock.startBci;
2591                 if (targetBlock instanceof ExceptionDispatchBlock) {
2592                     bci = ((ExceptionDispatchBlock) targetBlock).deoptBci;
2593                 }
2594                 FrameStateBuilder newState = state.copy();
2595                 for (BciBlock loop : exitLoops) {
2596                     LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(loop);
2597                     LoopExitNode loopExit = graph.add(new LoopExitNode(loopBegin));
2598                     if (lastLoopExit != null) {
2599                         lastLoopExit.setNext(loopExit);
2600                     }
2601                     if (firstLoopExit == null) {
2602                         firstLoopExit = loopExit;
2603                     }
2604                     lastLoopExit = loopExit;
2605                     debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop);
2606                     newState.clearNonLiveLocals(targetBlock, liveness, true);
2607                     newState.insertLoopProxies(loopExit, getEntryState(loop));
2608                     loopExit.setStateAfter(newState.create(bci, loopExit));
2609                 }
2610 
2611                 lastLoopExit.setNext(target);
2612                 return new Target(firstLoopExit, newState);
2613             }
2614         }
2615         return new Target(target, state);
2616     }
2617 
2618     private FrameStateBuilder getEntryState(BciBlock block) {
2619         return entryStateArray[block.id];
2620     }
2621 
2622     private void setEntryState(BciBlock block, FrameStateBuilder entryState) {
2623         this.entryStateArray[block.id] = entryState;
2624     }
2625 
2626     private void setFirstInstruction(BciBlock block, FixedWithNextNode firstInstruction) {
2627         this.firstInstructionArray[block.id] = firstInstruction;
2628     }
2629 
2630     private FixedWithNextNode getFirstInstruction(BciBlock block) {
2631         return firstInstructionArray[block.id];
2632     }
2633 
2634     private FixedNode createTarget(double probability, BciBlock block, FrameStateBuilder stateAfter) {
2635         assert probability >= 0 && probability <= 1.01 : probability;
2636         if (isNeverExecutedCode(probability)) {
2637             return graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
2638         } else {
2639             assert block != null;
2640             return createTarget(block, stateAfter);
2641         }
2642     }
2643 
2644     private FixedNode createTarget(BciBlock block, FrameStateBuilder state) {
2645         return createTarget(block, state, false, false);
2646     }
2647 
2648     private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
2649         assert block != null && state != null;
2650         assert !block.isExceptionEntry || state.stackSize() == 1;
2651 
2652         if (getFirstInstruction(block) == null) {
2653             /*
2654              * This is the first time we see this block as a branch target. Create and return a
2655              * placeholder that later can be replaced with a MergeNode when we see this block again.
2656              */
2657             FixedNode targetNode;
2658             if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
2659                 setFirstInstruction(block, lastInstr);
2660                 lastInstr = null;
2661             } else {
2662                 setFirstInstruction(block, graph.add(new BeginNode()));
2663             }
2664             targetNode = getFirstInstruction(block);
2665             Target target = checkLoopExit(targetNode, block, state);
2666             FixedNode result = target.fixed;
2667             FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
2668             setEntryState(block, currentEntryState);
2669             currentEntryState.clearNonLiveLocals(block, liveness, true);
2670 
2671             debug.log("createTarget %s: first visit, result: %s", block, targetNode);
2672             return result;
2673         }
2674 
2675         // We already saw this block before, so we have to merge states.
2676         if (!getEntryState(block).isCompatibleWith(state)) {
2677             throw bailout("stacks do not match; bytecodes would not verify");
2678         }
2679 
2680         if (getFirstInstruction(block) instanceof LoopBeginNode) {
2681             assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
2682             /*
2683              * Backward loop edge. We need to create a special LoopEndNode and merge with the loop
2684              * begin node created before.
2685              */
2686             LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block);
2687             LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
2688             Target target = checkLoopExit(loopEnd, block, state);
2689             FixedNode result = target.fixed;
2690             getEntryState(block).merge(loopBegin, target.state);
2691 
2692             debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
2693             return result;
2694         }
2695         assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
2696         assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
2697 
2698         if (getFirstInstruction(block) instanceof AbstractBeginNode && !(getFirstInstruction(block) instanceof AbstractMergeNode)) {
2699             /*
2700              * This is the second time we see this block. Create the actual MergeNode and the End
2701              * Node for the already existing edge.
2702              */
2703             AbstractBeginNode beginNode = (AbstractBeginNode) getFirstInstruction(block);
2704 
2705             // The EndNode for the already existing edge.
2706             EndNode end = graph.add(new EndNode());
2707             // The MergeNode that replaces the placeholder.
2708             AbstractMergeNode mergeNode = graph.add(new MergeNode());
2709             FixedNode next = beginNode.next();
2710 
2711             if (beginNode.predecessor() instanceof ControlSplitNode) {
2712                 beginNode.setNext(end);
2713             } else {
2714                 beginNode.replaceAtPredecessor(end);
2715                 beginNode.safeDelete();
2716             }
2717 
2718             mergeNode.addForwardEnd(end);
2719             mergeNode.setNext(next);
2720 
2721             setFirstInstruction(block, mergeNode);
2722         }
2723 
2724         AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block);
2725 
2726         // The EndNode for the newly merged edge.
2727         EndNode newEnd = graph.add(new EndNode());
2728         Target target = checkLoopExit(newEnd, block, state);
2729         FixedNode result = target.fixed;
2730         getEntryState(block).merge(mergeNode, target.state);
2731         mergeNode.addForwardEnd(newEnd);
2732 
2733         debug.log("createTarget %s: merging state, result: %s", block, result);
2734         return result;
2735     }
2736 
2737     /**
2738      * Returns a block begin node with the specified state. If the specified probability is 0, the
2739      * block deoptimizes immediately.
2740      */
2741     private AbstractBeginNode createBlockTarget(double probability, BciBlock block, FrameStateBuilder stateAfter) {
2742         FixedNode target = createTarget(probability, block, stateAfter);
2743         AbstractBeginNode begin = BeginNode.begin(target);
2744 
2745         assert !(target instanceof DeoptimizeNode && begin instanceof BeginStateSplitNode &&
2746                         ((BeginStateSplitNode) begin).stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node," +
2747                                         " because we have to deoptimize to a bci _before_ the actual if, so that the interpreter can update the profiling information.";
2748         return begin;
2749     }
2750 
2751     private ValueNode synchronizedObject(FrameStateBuilder state, ResolvedJavaMethod target) {
2752         if (target.isStatic()) {
2753             return appendConstant(getConstantReflection().asJavaClass(target.getDeclaringClass()));
2754         } else {
2755             return state.loadLocal(0, JavaKind.Object);
2756         }
2757     }
2758 
2759     @SuppressWarnings("try")
2760     protected void processBlock(BciBlock block) {
2761         // Ignore blocks that have no predecessors by the time their bytecodes are parsed
2762         FixedWithNextNode firstInstruction = getFirstInstruction(block);
2763         if (firstInstruction == null) {
2764             debug.log("Ignoring block %s", block);
2765             return;
2766         }
2767         try (Indent indent = debug.logAndIndent("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, firstInstruction, block.isLoopHeader)) {
2768 
2769             lastInstr = firstInstruction;
2770             frameState = getEntryState(block);
2771             setCurrentFrameState(frameState);
2772             currentBlock = block;
2773 
2774             if (firstInstruction instanceof AbstractMergeNode) {
2775                 setMergeStateAfter(block, firstInstruction);
2776             }
2777 
2778             if (block == blockMap.getUnwindBlock()) {
2779                 handleUnwindBlock((ExceptionDispatchBlock) block);
2780             } else if (block instanceof ExceptionDispatchBlock) {
2781                 createExceptionDispatch((ExceptionDispatchBlock) block);
2782             } else {
2783                 frameState.setRethrowException(false);
2784                 iterateBytecodesForBlock(block);
2785             }
2786         }
2787     }
2788 
2789     private void handleUnwindBlock(ExceptionDispatchBlock block) {
2790         if (parent == null) {
2791             finishPrepare(lastInstr, block.deoptBci);
2792             frameState.setRethrowException(false);
2793             createUnwind();
2794         } else {
2795             ValueNode exception = frameState.pop(JavaKind.Object);
2796             this.unwindValue = exception;
2797             this.beforeUnwindNode = this.lastInstr;
2798         }
2799     }
2800 
2801     private void setMergeStateAfter(BciBlock block, FixedWithNextNode firstInstruction) {
2802         AbstractMergeNode abstractMergeNode = (AbstractMergeNode) firstInstruction;
2803         if (abstractMergeNode.stateAfter() == null) {
2804             int bci = block.startBci;
2805             if (block instanceof ExceptionDispatchBlock) {
2806                 bci = ((ExceptionDispatchBlock) block).deoptBci;
2807             }
2808             abstractMergeNode.setStateAfter(createFrameState(bci, abstractMergeNode));
2809         }
2810     }
2811 
2812     private void createUnwind() {
2813         assert frameState.stackSize() == 1 : frameState;
2814         synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null);
2815         ValueNode exception = frameState.pop(JavaKind.Object);
2816         append(new UnwindNode(exception));
2817     }
2818 
2819     private void synchronizedEpilogue(int bci, ValueNode currentReturnValue, JavaKind currentReturnValueKind) {
2820         if (method.isSynchronized()) {
2821             if (currentReturnValue != null) {
2822                 frameState.push(currentReturnValueKind, currentReturnValue);
2823             }
2824             genMonitorExit(methodSynchronizedObject, currentReturnValue, bci);
2825             assert !frameState.rethrowException();
2826             finishPrepare(lastInstr, bci);
2827         }
2828         if (frameState.lockDepth(false) != 0) {
2829             throw bailout("unbalanced monitors: too few exits exiting frame");
2830         }
2831     }
2832 
2833     private void createExceptionDispatch(ExceptionDispatchBlock block) {
2834         lastInstr = finishInstruction(lastInstr, frameState);
2835 
2836         assert frameState.stackSize() == 1 : frameState;
2837         if (block.handler.isCatchAll()) {
2838             assert block.getSuccessorCount() == 1;
2839             appendGoto(block.getSuccessor(0));
2840             return;
2841         }
2842 
2843         JavaType catchType = block.handler.getCatchType();
2844         if (graphBuilderConfig.eagerResolving()) {
2845             catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF);
2846         }
2847         if (catchType instanceof ResolvedJavaType) {
2848             TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType);
2849 
2850             if (graphBuilderConfig.getSkippedExceptionTypes() != null) {
2851                 for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
2852                     if (skippedType.isAssignableFrom(checkedCatchType.getType())) {
2853                         BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
2854                         ValueNode exception = frameState.stack[0];
2855                         FixedNode trueSuccessor = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
2856                         FixedNode nextDispatch = createTarget(nextBlock, frameState);
2857                         append(new IfNode(graph.addOrUniqueWithInputs(createInstanceOf(checkedCatchType, exception)), trueSuccessor, nextDispatch, 0));
2858                         return;
2859                     }
2860                 }
2861             }
2862 
2863             BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
2864             ValueNode exception = frameState.stack[0];
2865             /* Anchor for the piNode, which must be before any LoopExit inserted by createTarget. */
2866             BeginNode piNodeAnchor = graph.add(new BeginNode());
2867             ObjectStamp checkedStamp = StampFactory.objectNonNull(checkedCatchType);
2868             PiNode piNode = graph.addWithoutUnique(new PiNode(exception, checkedStamp));
2869             frameState.pop(JavaKind.Object);
2870             frameState.push(JavaKind.Object, piNode);
2871             FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState);
2872             frameState.pop(JavaKind.Object);
2873             frameState.push(JavaKind.Object, exception);
2874             FixedNode nextDispatch = createTarget(nextBlock, frameState);
2875             piNodeAnchor.setNext(catchSuccessor);
2876             IfNode ifNode = append(new IfNode(graph.unique(createInstanceOf(checkedCatchType, exception)), piNodeAnchor, nextDispatch, 0.5));
2877             assert ifNode.trueSuccessor() == piNodeAnchor;
2878             piNode.setGuard(ifNode.trueSuccessor());
2879         } else {
2880             handleUnresolvedExceptionType(catchType);
2881         }
2882     }
2883 
2884     private void appendGoto(BciBlock successor) {
2885         FixedNode targetInstr = createTarget(successor, frameState, true, true);
2886         if (lastInstr != null && lastInstr != targetInstr) {
2887             lastInstr.setNext(targetInstr);
2888         }
2889     }
2890 
2891     @SuppressWarnings("try")
2892     protected void iterateBytecodesForBlock(BciBlock block) {
2893         if (block.isLoopHeader) {
2894             // Create the loop header block, which later will merge the backward branches of
2895             // the loop.
2896             controlFlowSplit = true;
2897             LoopBeginNode loopBegin = appendLoopBegin(this.lastInstr);
2898             lastInstr = loopBegin;
2899 
2900             // Create phi functions for all local variables and operand stack slots.
2901             frameState.insertLoopPhis(liveness, block.loopId, loopBegin, forceLoopPhis(), stampFromValueForForcedPhis());
2902             loopBegin.setStateAfter(createFrameState(block.startBci, loopBegin));
2903 
2904             /*
2905              * We have seen all forward branches. All subsequent backward branches will merge to the
2906              * loop header. This ensures that the loop header has exactly one non-loop predecessor.
2907              */
2908             setFirstInstruction(block, loopBegin);
2909             /*
2910              * We need to preserve the frame state builder of the loop header so that we can merge
2911              * values for phi functions, so make a copy of it.
2912              */
2913             setEntryState(block, frameState.copy());
2914 
2915             debug.log("  created loop header %s", loopBegin);
2916         } else if (lastInstr instanceof MergeNode) {
2917             /*
2918              * All inputs of non-loop phi nodes are known by now. We can infer the stamp for the
2919              * phi, so that parsing continues with more precise type information.
2920              */
2921             frameState.inferPhiStamps((AbstractMergeNode) lastInstr);
2922         }
2923         assert lastInstr.next() == null : "instructions already appended at block " + block;
2924         debug.log("  frameState: %s", frameState);
2925 
2926         lastInstr = finishInstruction(lastInstr, frameState);
2927 
2928         int endBCI = stream.endBCI();
2929 
2930         stream.setBCI(block.startBci);
2931         int bci = block.startBci;
2932         BytecodesParsed.add(debug, block.endBci - bci);
2933 
2934         /* Reset line number for new block */
2935         if (graphBuilderConfig.insertFullInfopoints()) {
2936             previousLineNumber = -1;
2937         }
2938 
2939         while (bci < endBCI) {
2940             if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) {
2941                 currentLineNumber = lnt != null ? lnt.getLineNumber(bci) : -1;
2942                 if (currentLineNumber != previousLineNumber) {
2943                     genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
2944                     previousLineNumber = currentLineNumber;
2945                 }
2946             }
2947 
2948             // read the opcode
2949             int opcode = stream.currentBC();
2950             assert traceState();
2951             assert traceInstruction(bci, opcode, bci == block.startBci);
2952             if (parent == null && bci == entryBCI) {
2953                 if (block.getJsrScope() != JsrScope.EMPTY_SCOPE) {
2954                     throw new JsrNotSupportedBailout("OSR into a JSR scope is not supported");
2955                 }
2956                 EntryMarkerNode x = append(new EntryMarkerNode());
2957                 frameState.insertProxies(value -> graph.unique(new EntryProxyNode(value, x)));
2958                 x.setStateAfter(createFrameState(bci, x));
2959             }
2960 
2961             try (DebugCloseable context = openNodeContext()) {
2962                 processBytecode(bci, opcode);
2963             } catch (BailoutException e) {
2964                 // Don't wrap bailouts as parser errors
2965                 throw e;
2966             } catch (Throwable e) {
2967                 throw throwParserError(e);
2968             }
2969 
2970             if (lastInstr == null || lastInstr.next() != null) {
2971                 break;
2972             }
2973 
2974             stream.next();
2975             bci = stream.currentBCI();
2976 
2977             assert block == currentBlock;
2978             assert checkLastInstruction();
2979             lastInstr = finishInstruction(lastInstr, frameState);
2980             if (bci < endBCI) {
2981                 if (bci > block.endBci) {
2982                     assert !block.getSuccessor(0).isExceptionEntry;
2983                     assert block.numNormalSuccessors() == 1;
2984                     // we fell through to the next block, add a goto and break
2985                     appendGoto(block.getSuccessor(0));
2986                     break;
2987                 }
2988             }
2989         }
2990     }
2991 
2992     private DebugCloseable openNodeContext() {
2993         if ((graphBuilderConfig.trackNodeSourcePosition() || debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) {
2994             return graph.withNodeSourcePosition(createBytecodePosition());
2995         }
2996         return null;
2997     }
2998 
2999     /* Also a hook for subclasses. */
3000     protected boolean forceLoopPhis() {
3001         return graph.isOSR();
3002     }
3003 
3004     /* Hook for subclasses. */
3005     protected boolean stampFromValueForForcedPhis() {
3006         return false;
3007     }
3008 
3009     protected boolean checkLastInstruction() {
3010         if (lastInstr instanceof BeginNode) {
3011             // ignore
3012         } else if (lastInstr instanceof StateSplit) {
3013             StateSplit stateSplit = (StateSplit) lastInstr;
3014             if (stateSplit.hasSideEffect()) {
3015                 assert stateSplit.stateAfter() != null : "side effect " + lastInstr + " requires a non-null stateAfter";
3016             }
3017         }
3018         return true;
3019     }
3020 
3021     /* Also a hook for subclasses. */
3022     protected boolean disableLoopSafepoint() {
3023         return parsingIntrinsic();
3024     }
3025 
3026     private LoopBeginNode appendLoopBegin(FixedWithNextNode fixedWithNext) {
3027         EndNode preLoopEnd = graph.add(new EndNode());
3028         LoopBeginNode loopBegin = graph.add(new LoopBeginNode());
3029         if (disableLoopSafepoint()) {
3030             loopBegin.disableSafepoint();
3031         }
3032         fixedWithNext.setNext(preLoopEnd);
3033         // Add the single non-loop predecessor of the loop header.
3034         loopBegin.addForwardEnd(preLoopEnd);
3035         return loopBegin;
3036     }
3037 
3038     /**
3039      * Hook for subclasses to modify the last instruction or add other instructions.
3040      *
3041      * @param instr The last instruction (= fixed node) which was added.
3042      * @param state The current frame state.
3043      * @return Returns the (new) last instruction.
3044      */
3045     protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, FrameStateBuilder state) {
3046         return instr;
3047     }
3048 
3049     private void genInfoPointNode(InfopointReason reason, ValueNode escapedReturnValue) {
3050         if (!parsingIntrinsic() && graphBuilderConfig.insertFullInfopoints()) {
3051             append(new FullInfopointNode(reason, createFrameState(bci(), null), escapedReturnValue));
3052         }
3053     }
3054 
3055     private boolean traceState() {
3056         if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) {
3057             frameState.traceState();
3058         }
3059         return true;
3060     }
3061 
3062     protected void genIf(ValueNode x, Condition cond, ValueNode y) {
3063         assert x.getStackKind() == y.getStackKind();
3064         assert currentBlock.getSuccessorCount() == 2;
3065         BciBlock trueBlock = currentBlock.getSuccessor(0);
3066         BciBlock falseBlock = currentBlock.getSuccessor(1);
3067 
3068         if (trueBlock == falseBlock) {
3069             // The target block is the same independent of the condition.
3070             appendGoto(trueBlock);
3071             return;
3072         }
3073 
3074         ValueNode a = x;
3075         ValueNode b = y;
3076 
3077         // Check whether the condition needs to mirror the operands.
3078         if (cond.canonicalMirror()) {
3079             a = y;
3080             b = x;
3081         }
3082 
3083         // Create the logic node for the condition.
3084         LogicNode condition = createLogicNode(cond, a, b);
3085 
3086         // Check whether the condition needs to negate the result.
3087         boolean negate = cond.canonicalNegate();
3088         genIf(condition, negate, trueBlock, falseBlock);
3089     }
3090 
3091     protected void genIf(LogicNode conditionInput, boolean negateCondition, BciBlock trueBlockInput, BciBlock falseBlockInput) {
3092         BciBlock trueBlock = trueBlockInput;
3093         BciBlock falseBlock = falseBlockInput;
3094         LogicNode condition = conditionInput;
3095         FrameState stateBefore = null;
3096         ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin();
3097         if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3098             stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3099         }
3100 
3101         // Remove a logic negation node and fold it into the negate boolean.
3102         boolean negate = negateCondition;
3103         if (condition instanceof LogicNegationNode) {
3104             LogicNegationNode logicNegationNode = (LogicNegationNode) condition;
3105             negate = !negate;
3106             condition = logicNegationNode.getValue();
3107         }
3108 
3109         if (condition instanceof LogicConstantNode) {
3110             genConstantTargetIf(trueBlock, falseBlock, negate, condition);
3111         } else {
3112             if (condition.graph() == null) {
3113                 condition = genUnique(condition);
3114             }
3115 
3116             // Need to get probability based on current bci.
3117             double probability = branchProbability(condition);
3118 
3119             if (negate) {
3120                 BciBlock tmpBlock = trueBlock;
3121                 trueBlock = falseBlock;
3122                 falseBlock = tmpBlock;
3123                 probability = 1 - probability;
3124             }
3125 
3126             if (isNeverExecutedCode(probability)) {
3127                 append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
3128                 if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3129                     profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
3130                 }
3131                 appendGoto(falseBlock);
3132                 return;
3133             } else if (isNeverExecutedCode(1 - probability)) {
3134                 append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false));
3135                 if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3136                     profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
3137                 }
3138                 appendGoto(trueBlock);
3139                 return;
3140             }
3141 
3142             if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3143                 profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore);
3144             }
3145 
3146             int oldBci = stream.currentBCI();
3147             int trueBlockInt = checkPositiveIntConstantPushed(trueBlock);
3148             if (trueBlockInt != -1) {
3149                 int falseBlockInt = checkPositiveIntConstantPushed(falseBlock);
3150                 if (falseBlockInt != -1) {
3151                     if (tryGenConditionalForIf(trueBlock, falseBlock, condition, oldBci, trueBlockInt, falseBlockInt)) {
3152                         return;
3153                     }
3154                 }
3155             }
3156 
3157             this.controlFlowSplit = true;
3158             FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false);
3159             FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true);
3160             ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability);
3161             postProcessIfNode(ifNode);
3162             append(ifNode);
3163         }
3164     }
3165 
3166     /**
3167      * Hook for subclasses to generate custom nodes before an IfNode.
3168      */
3169     @SuppressWarnings("unused")
3170     protected void postProcessIfNode(ValueNode node) {
3171     }
3172 
3173     private boolean tryGenConditionalForIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt) {
3174         if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) {
3175             genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, false);
3176             return true;
3177         } else if (this.parent != null && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) {
3178             genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, true);
3179             return true;
3180         }
3181         return false;
3182     }
3183 
3184     private void genConditionalForIf(BciBlock trueBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt, boolean genReturn) {
3185         ConstantNode trueValue = graph.unique(ConstantNode.forInt(trueBlockInt));
3186         ConstantNode falseValue = graph.unique(ConstantNode.forInt(falseBlockInt));
3187         ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue);
3188         if (conditionalNode.graph() == null) {
3189             conditionalNode = graph.addOrUniqueWithInputs(conditionalNode);
3190         }
3191         if (genReturn) {
3192             JavaKind returnKind = method.getSignature().getReturnKind().getStackKind();
3193             this.genReturn(conditionalNode, returnKind);
3194         } else {
3195             frameState.push(JavaKind.Int, conditionalNode);
3196             appendGoto(trueBlock.getSuccessor(0));
3197             stream.setBCI(oldBci);
3198         }
3199     }
3200 
3201     private LogicNode createLogicNode(Condition cond, ValueNode a, ValueNode b) {
3202         LogicNode condition;
3203         assert !a.getStackKind().isNumericFloat();
3204         if (cond == Condition.EQ || cond == Condition.NE) {
3205             if (a.getStackKind() == JavaKind.Object) {
3206                 condition = genObjectEquals(a, b);
3207             } else {
3208                 condition = genIntegerEquals(a, b);
3209             }
3210         } else {
3211             assert a.getStackKind() != JavaKind.Object && !cond.isUnsigned();
3212             condition = genIntegerLessThan(a, b);
3213         }
3214         return condition;
3215     }
3216 
3217     private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, boolean negate, LogicNode condition) {
3218         LogicConstantNode constantLogicNode = (LogicConstantNode) condition;
3219         boolean value = constantLogicNode.getValue();
3220         if (negate) {
3221             value = !value;
3222         }
3223         BciBlock nextBlock = falseBlock;
3224         if (value) {
3225             nextBlock = trueBlock;
3226         }
3227         int startBci = nextBlock.startBci;
3228         int targetAtStart = stream.readUByte(startBci);
3229         if (targetAtStart == Bytecodes.GOTO && nextBlock.getPredecessorCount() == 1) {
3230             // This is an empty block. Skip it.
3231             BciBlock successorBlock = nextBlock.successors.get(0);
3232             ProfilingPlugin profilingPlugin = graphBuilderConfig.getPlugins().getProfilingPlugin();
3233             if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3234                 FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3235                 profilingPlugin.profileGoto(this, method, bci(), successorBlock.startBci, stateBefore);
3236             }
3237             appendGoto(successorBlock);
3238             assert nextBlock.numNormalSuccessors() == 1;
3239         } else {
3240             ProfilingPlugin profilingPlugin = graphBuilderConfig.getPlugins().getProfilingPlugin();
3241             if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3242                 FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3243                 profilingPlugin.profileGoto(this, method, bci(), nextBlock.startBci, stateBefore);
3244             }
3245             appendGoto(nextBlock);
3246         }
3247     }
3248 
3249     private int checkPositiveIntConstantPushed(BciBlock block) {
3250         stream.setBCI(block.startBci);
3251         int currentBC = stream.currentBC();
3252         if (currentBC >= Bytecodes.ICONST_0 && currentBC <= Bytecodes.ICONST_5) {
3253             int constValue = currentBC - Bytecodes.ICONST_0;
3254             return constValue;
3255         }
3256         return -1;
3257     }
3258 
3259     private boolean gotoOrFallThroughAfterConstant(BciBlock block) {
3260         stream.setBCI(block.startBci);
3261         int currentBCI = stream.nextBCI();
3262         stream.setBCI(currentBCI);
3263         int currentBC = stream.currentBC();
3264         return stream.currentBCI() > block.endBci || currentBC == Bytecodes.GOTO || currentBC == Bytecodes.GOTO_W;
3265     }
3266 
3267     private boolean returnAfterConstant(BciBlock block) {
3268         stream.setBCI(block.startBci);
3269         int currentBCI = stream.nextBCI();
3270         stream.setBCI(currentBCI);
3271         int currentBC = stream.currentBC();
3272         return currentBC == Bytecodes.IRETURN;
3273     }
3274 
3275     @Override
3276     public StampProvider getStampProvider() {
3277         return stampProvider;
3278     }
3279 
3280     @Override
3281     public MetaAccessProvider getMetaAccess() {
3282         return metaAccess;
3283     }
3284 
3285     @Override
3286     public void push(JavaKind slotKind, ValueNode value) {
3287         assert value.isAlive();
3288         frameState.push(slotKind, value);
3289     }
3290 
3291     @Override
3292     public ConstantReflectionProvider getConstantReflection() {
3293         return constantReflection;
3294     }
3295 
3296     @Override
3297     public ConstantFieldProvider getConstantFieldProvider() {
3298         return constantFieldProvider;
3299     }
3300 
3301     /**
3302      * Gets the graph being processed by this builder.
3303      */
3304     @Override
3305     public StructuredGraph getGraph() {
3306         return graph;
3307     }
3308 
3309     @Override
3310     public BytecodeParser getParent() {
3311         return parent;
3312     }
3313 
3314     @Override
3315     public IntrinsicContext getIntrinsic() {
3316         return intrinsicContext;
3317     }
3318 
3319     @Override
3320     public String toString() {
3321         Formatter fmt = new Formatter();
3322         BytecodeParser bp = this;
3323         String indent = "";
3324         while (bp != null) {
3325             if (bp != this) {
3326                 fmt.format("%n%s", indent);
3327             }
3328             fmt.format("%s [bci: %d, intrinsic: %s]", bp.code.asStackTraceElement(bp.bci()), bp.bci(), bp.parsingIntrinsic());
3329             fmt.format("%n%s", new BytecodeDisassembler().disassemble(bp.code, bp.bci(), bp.bci() + 10));
3330             bp = bp.parent;
3331             indent += " ";
3332         }
3333         return fmt.toString();
3334     }
3335 
3336     @Override
3337     public BailoutException bailout(String string) {
3338         FrameState currentFrameState = createFrameState(bci(), null);
3339         StackTraceElement[] elements = GraphUtil.approxSourceStackTraceElement(currentFrameState);
3340         BailoutException bailout = new PermanentBailoutException(string);
3341         throw GraphUtil.createBailoutException(string, bailout, elements);
3342     }
3343 
3344     private FrameState createFrameState(int bci, StateSplit forStateSplit) {
3345         if (currentBlock != null && bci > currentBlock.endBci) {
3346             frameState.clearNonLiveLocals(currentBlock, liveness, false);
3347         }
3348         return frameState.create(bci, forStateSplit);
3349     }
3350 
3351     @Override
3352     public void setStateAfter(StateSplit sideEffect) {
3353         assert sideEffect.hasSideEffect();
3354         FrameState stateAfter = createFrameState(stream.nextBCI(), sideEffect);
3355         sideEffect.setStateAfter(stateAfter);
3356     }
3357 
3358     protected NodeSourcePosition createBytecodePosition() {
3359         return frameState.createBytecodePosition(bci());
3360     }
3361 
3362     public void setCurrentFrameState(FrameStateBuilder frameState) {
3363         this.frameState = frameState;
3364     }
3365 
3366     protected final BytecodeStream getStream() {
3367         return stream;
3368     }
3369 
3370     @Override
3371     public int bci() {
3372         return stream.currentBCI();
3373     }
3374 
3375     public void loadLocal(int index, JavaKind kind) {
3376         ValueNode value = frameState.loadLocal(index, kind);
3377         frameState.push(kind, value);
3378     }
3379 
3380     public void loadLocalObject(int index) {
3381         ValueNode value = frameState.loadLocal(index, JavaKind.Object);
3382 
3383         int nextBCI = stream.nextBCI();
3384         int nextBC = stream.readUByte(nextBCI);
3385         if (nextBCI <= currentBlock.endBci && nextBC == Bytecodes.GETFIELD) {
3386             stream.next();
3387             genGetField(stream.readCPI(), Bytecodes.GETFIELD, value);
3388         } else {
3389             frameState.push(JavaKind.Object, value);
3390         }
3391     }
3392 
3393     public void storeLocal(JavaKind kind, int index) {
3394         ValueNode value = frameState.pop(kind);
3395         frameState.storeLocal(index, kind, value);
3396     }
3397 
3398     private void genLoadConstant(int cpi, int opcode) {
3399         Object con = lookupConstant(cpi, opcode);
3400 
3401         if (con instanceof JavaType) {
3402             // this is a load of class constant which might be unresolved
3403             JavaType type = (JavaType) con;
3404             if (type instanceof ResolvedJavaType) {
3405                 frameState.push(JavaKind.Object, appendConstant(getConstantReflection().asJavaClass((ResolvedJavaType) type)));
3406             } else {
3407                 handleUnresolvedLoadConstant(type);
3408             }
3409         } else if (con instanceof JavaConstant) {
3410             JavaConstant constant = (JavaConstant) con;
3411             frameState.push(constant.getJavaKind(), appendConstant(constant));
3412         } else {
3413             throw new Error("lookupConstant returned an object of incorrect type");
3414         }
3415     }
3416 
3417     private void genLoadIndexed(JavaKind kind) {
3418         ValueNode index = frameState.pop(JavaKind.Int);
3419         ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), index);
3420 
3421         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3422             if (plugin.handleLoadIndexed(this, array, index, kind)) {
3423                 return;
3424             }
3425         }
3426 
3427         frameState.push(kind, append(genLoadIndexed(array, index, kind)));
3428     }
3429 
3430     private void genStoreIndexed(JavaKind kind) {
3431         ValueNode value = frameState.pop(kind);
3432         ValueNode index = frameState.pop(JavaKind.Int);
3433         ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), index);
3434 
3435         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3436             if (plugin.handleStoreIndexed(this, array, index, kind, value)) {
3437                 return;
3438             }
3439         }
3440 
3441         genStoreIndexed(array, index, kind, value);
3442     }
3443 
3444     private void genArithmeticOp(JavaKind kind, int opcode) {
3445         ValueNode y = frameState.pop(kind);
3446         ValueNode x = frameState.pop(kind);
3447         ValueNode v;
3448         switch (opcode) {
3449             case IADD:
3450             case LADD:
3451                 v = genIntegerAdd(x, y);
3452                 break;
3453             case FADD:
3454             case DADD:
3455                 v = genFloatAdd(x, y);
3456                 break;
3457             case ISUB:
3458             case LSUB:
3459                 v = genIntegerSub(x, y);
3460                 break;
3461             case FSUB:
3462             case DSUB:
3463                 v = genFloatSub(x, y);
3464                 break;
3465             case IMUL:
3466             case LMUL:
3467                 v = genIntegerMul(x, y);
3468                 break;
3469             case FMUL:
3470             case DMUL:
3471                 v = genFloatMul(x, y);
3472                 break;
3473             case FDIV:
3474             case DDIV:
3475                 v = genFloatDiv(x, y);
3476                 break;
3477             case FREM:
3478             case DREM:
3479                 v = genFloatRem(x, y);
3480                 break;
3481             default:
3482                 throw shouldNotReachHere();
3483         }
3484         frameState.push(kind, append(v));
3485     }
3486 
3487     private void genIntegerDivOp(JavaKind kind, int opcode) {
3488         ValueNode y = frameState.pop(kind);
3489         ValueNode x = frameState.pop(kind);
3490         ValueNode v;
3491         switch (opcode) {
3492             case IDIV:
3493             case LDIV:
3494                 v = genIntegerDiv(x, y);
3495                 break;
3496             case IREM:
3497             case LREM:
3498                 v = genIntegerRem(x, y);
3499                 break;
3500             default:
3501                 throw shouldNotReachHere();
3502         }
3503         frameState.push(kind, append(v));
3504     }
3505 
3506     private void genNegateOp(JavaKind kind) {
3507         ValueNode x = frameState.pop(kind);
3508         frameState.push(kind, append(genNegateOp(x)));
3509     }
3510 
3511     private void genShiftOp(JavaKind kind, int opcode) {
3512         ValueNode s = frameState.pop(JavaKind.Int);
3513         ValueNode x = frameState.pop(kind);
3514         ValueNode v;
3515         switch (opcode) {
3516             case ISHL:
3517             case LSHL:
3518                 v = genLeftShift(x, s);
3519                 break;
3520             case ISHR:
3521             case LSHR:
3522                 v = genRightShift(x, s);
3523                 break;
3524             case IUSHR:
3525             case LUSHR:
3526                 v = genUnsignedRightShift(x, s);
3527                 break;
3528             default:
3529                 throw shouldNotReachHere();
3530         }
3531         frameState.push(kind, append(v));
3532     }
3533 
3534     private void genLogicOp(JavaKind kind, int opcode) {
3535         ValueNode y = frameState.pop(kind);
3536         ValueNode x = frameState.pop(kind);
3537         ValueNode v;
3538         switch (opcode) {
3539             case IAND:
3540             case LAND:
3541                 v = genAnd(x, y);
3542                 break;
3543             case IOR:
3544             case LOR:
3545                 v = genOr(x, y);
3546                 break;
3547             case IXOR:
3548             case LXOR:
3549                 v = genXor(x, y);
3550                 break;
3551             default:
3552                 throw shouldNotReachHere();
3553         }
3554         frameState.push(kind, append(v));
3555     }
3556 
3557     private void genCompareOp(JavaKind kind, boolean isUnorderedLess) {
3558         ValueNode y = frameState.pop(kind);
3559         ValueNode x = frameState.pop(kind);
3560         frameState.push(JavaKind.Int, append(genNormalizeCompare(x, y, isUnorderedLess)));
3561     }
3562 
3563     private void genFloatConvert(FloatConvert op, JavaKind from, JavaKind to) {
3564         ValueNode input = frameState.pop(from);
3565         frameState.push(to, append(genFloatConvert(op, input)));
3566     }
3567 
3568     private void genSignExtend(JavaKind from, JavaKind to) {
3569         ValueNode input = frameState.pop(from);
3570         if (from != from.getStackKind()) {
3571             input = append(genNarrow(input, from.getBitCount()));
3572         }
3573         frameState.push(to, append(genSignExtend(input, to.getBitCount())));
3574     }
3575 
3576     private void genZeroExtend(JavaKind from, JavaKind to) {
3577         ValueNode input = frameState.pop(from);
3578         if (from != from.getStackKind()) {
3579             input = append(genNarrow(input, from.getBitCount()));
3580         }
3581         frameState.push(to, append(genZeroExtend(input, to.getBitCount())));
3582     }
3583 
3584     private void genNarrow(JavaKind from, JavaKind to) {
3585         ValueNode input = frameState.pop(from);
3586         frameState.push(to, append(genNarrow(input, to.getBitCount())));
3587     }
3588 
3589     private void genIncrement() {
3590         int index = getStream().readLocalIndex();
3591         int delta = getStream().readIncrement();
3592         ValueNode x = frameState.loadLocal(index, JavaKind.Int);
3593         ValueNode y = appendConstant(JavaConstant.forInt(delta));
3594         frameState.storeLocal(index, JavaKind.Int, append(genIntegerAdd(x, y)));
3595     }
3596 
3597     private void genIfZero(Condition cond) {
3598         ValueNode y = appendConstant(JavaConstant.INT_0);
3599         ValueNode x = frameState.pop(JavaKind.Int);
3600         genIf(x, cond, y);
3601     }
3602 
3603     private void genIfNull(Condition cond) {
3604         ValueNode y = appendConstant(JavaConstant.NULL_POINTER);
3605         ValueNode x = frameState.pop(JavaKind.Object);
3606         genIf(x, cond, y);
3607     }
3608 
3609     private void genIfSame(JavaKind kind, Condition cond) {
3610         ValueNode y = frameState.pop(kind);
3611         ValueNode x = frameState.pop(kind);
3612         genIf(x, cond, y);
3613     }
3614 
3615     protected JavaType lookupType(int cpi, int bytecode) {
3616         maybeEagerlyResolve(cpi, bytecode);
3617         JavaType result = constantPool.lookupType(cpi, bytecode);
3618         assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
3619         return result;
3620     }
3621 
3622     private JavaMethod lookupMethod(int cpi, int opcode) {
3623         maybeEagerlyResolve(cpi, opcode);
3624         JavaMethod result = constantPool.lookupMethod(cpi, opcode);
3625         /*
3626          * In general, one cannot assume that the declaring class being initialized is useful, since
3627          * the actual concrete receiver may be a different class (except for static calls). Also,
3628          * interfaces are initialized only under special circumstances, so that this assertion would
3629          * often fail for interface calls.
3630          */
3631         assert !graphBuilderConfig.unresolvedIsError() ||
3632                         (result instanceof ResolvedJavaMethod && (opcode != INVOKESTATIC || ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized())) : result;
3633         return result;
3634     }
3635 
3636     protected JavaField lookupField(int cpi, int opcode) {
3637         maybeEagerlyResolve(cpi, opcode);
3638         JavaField result = constantPool.lookupField(cpi, method, opcode);
3639 
3640         if (graphBuilderConfig.eagerResolving()) {
3641             assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaField : "Not resolved: " + result;
3642             if (result instanceof ResolvedJavaField) {
3643                 ResolvedJavaType declaringClass = ((ResolvedJavaField) result).getDeclaringClass();
3644                 if (!declaringClass.isInitialized()) {
3645                     assert declaringClass.isInterface() : "Declaring class not initialized but not an interface? " + declaringClass;
3646                     declaringClass.initialize();
3647                 }
3648             }
3649         }
3650         assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
3651         return result;
3652     }
3653 
3654     private Object lookupConstant(int cpi, int opcode) {
3655         maybeEagerlyResolve(cpi, opcode);
3656         Object result = constantPool.lookupConstant(cpi);
3657         assert !graphBuilderConfig.unresolvedIsError() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType) : result;
3658         return result;
3659     }
3660 
3661     protected void maybeEagerlyResolve(int cpi, int bytecode) {
3662         if (intrinsicContext != null) {
3663             constantPool.loadReferencedType(cpi, bytecode);
3664         } else if (graphBuilderConfig.eagerResolving()) {
3665             /*
3666              * Since we're potentially triggering class initialization here, we need synchronization
3667              * to mitigate the potential for class initialization related deadlock being caused by
3668              * the compiler (e.g., https://github.com/graalvm/graal-core/pull/232/files#r90788550).
3669              */
3670             synchronized (BytecodeParser.class) {
3671                 constantPool.loadReferencedType(cpi, bytecode);
3672             }
3673         }
3674     }
3675 
3676     private JavaTypeProfile getProfileForTypeCheck(TypeReference type) {
3677         if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints(getOptions()) || type.isExact()) {
3678             return null;
3679         } else {
3680             return profilingInfo.getTypeProfile(bci());
3681         }
3682     }
3683 
3684     private void genCheckCast() {
3685         int cpi = getStream().readCPI();
3686         JavaType type = lookupType(cpi, CHECKCAST);
3687         ValueNode object = frameState.pop(JavaKind.Object);
3688 
3689         if (!(type instanceof ResolvedJavaType)) {
3690             handleUnresolvedCheckCast(type, object);
3691             return;
3692         }
3693         TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) type);
3694         JavaTypeProfile profile = getProfileForTypeCheck(checkedType);
3695 
3696         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3697             if (plugin.handleCheckCast(this, object, checkedType.getType(), profile)) {
3698                 return;
3699             }
3700         }
3701 
3702         ValueNode castNode = null;
3703         if (profile != null) {
3704             if (profile.getNullSeen().isFalse()) {
3705                 object = nullCheckedValue(object);
3706                 ResolvedJavaType singleType = profile.asSingleType();
3707                 if (singleType != null && checkedType.getType().isAssignableFrom(singleType)) {
3708                     LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile));
3709                     if (typeCheck.isTautology()) {
3710                         castNode = object;
3711                     } else {
3712                         FixedGuardNode fixedGuard = append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile, false));
3713                         castNode = append(PiNode.create(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard));
3714                     }
3715                 }
3716             }
3717         }
3718 
3719         boolean nonNull = ((ObjectStamp) object.stamp()).nonNull();
3720         if (castNode == null) {
3721             LogicNode condition = genUnique(createInstanceOfAllowNull(checkedType, object, null));
3722             if (condition.isTautology()) {
3723                 castNode = object;
3724             } else {
3725                 FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false));
3726                 castNode = append(PiNode.create(object, StampFactory.object(checkedType, nonNull), fixedGuard));
3727             }
3728         }
3729         frameState.push(JavaKind.Object, castNode);
3730     }
3731 
3732     private void genInstanceOf() {
3733         int cpi = getStream().readCPI();
3734         JavaType type = lookupType(cpi, INSTANCEOF);
3735         ValueNode object = frameState.pop(JavaKind.Object);
3736 
3737         if (!(type instanceof ResolvedJavaType)) {
3738             handleUnresolvedInstanceOf(type, object);
3739             return;
3740         }
3741         TypeReference resolvedType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) type);
3742         JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
3743 
3744         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3745             if (plugin.handleInstanceOf(this, object, resolvedType.getType(), profile)) {
3746                 return;
3747             }
3748         }
3749 
3750         LogicNode instanceOfNode = null;
3751         if (profile != null) {
3752             if (profile.getNullSeen().isFalse()) {
3753                 object = nullCheckedValue(object);
3754                 ResolvedJavaType singleType = profile.asSingleType();
3755                 if (singleType != null) {
3756                     LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile));
3757                     if (!typeCheck.isTautology()) {
3758                         append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
3759                     }
3760                     instanceOfNode = LogicConstantNode.forBoolean(resolvedType.getType().isAssignableFrom(singleType));
3761                 }
3762             }
3763         }
3764         if (instanceOfNode == null) {
3765             instanceOfNode = createInstanceOf(resolvedType, object, null);
3766         }
3767         LogicNode logicNode = genUnique(instanceOfNode);
3768 
3769         int next = getStream().nextBCI();
3770         int value = getStream().readUByte(next);
3771         if (next <= currentBlock.endBci && (value == Bytecodes.IFEQ || value == Bytecodes.IFNE)) {
3772             getStream().next();
3773             BciBlock firstSucc = currentBlock.getSuccessor(0);
3774             BciBlock secondSucc = currentBlock.getSuccessor(1);
3775             if (firstSucc != secondSucc) {
3776                 genIf(instanceOfNode, value != Bytecodes.IFNE, firstSucc, secondSucc);
3777             } else {
3778                 appendGoto(firstSucc);
3779             }
3780         } else {
3781             // Most frequent for value is IRETURN, followed by ISTORE.
3782             frameState.push(JavaKind.Int, append(genConditional(logicNode)));
3783         }
3784     }
3785 
3786     protected void genNewInstance(int cpi) {
3787         JavaType type = lookupType(cpi, NEW);
3788         genNewInstance(type);
3789     }
3790 
3791     void genNewInstance(JavaType type) {
3792         if (!(type instanceof ResolvedJavaType) || !((ResolvedJavaType) type).isInitialized()) {
3793             handleUnresolvedNewInstance(type);
3794             return;
3795         }
3796         ResolvedJavaType resolvedType = (ResolvedJavaType) type;
3797 
3798         ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
3799         if (skippedExceptionTypes != null) {
3800             for (ResolvedJavaType exceptionType : skippedExceptionTypes) {
3801                 if (exceptionType.isAssignableFrom(resolvedType)) {
3802                     append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, RuntimeConstraint));
3803                     return;
3804                 }
3805             }
3806         }
3807 
3808         ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
3809         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType)) {
3810             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3811             classInitializationPlugin.apply(this, resolvedType, stateBefore);
3812         }
3813 
3814         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3815             if (plugin.handleNewInstance(this, resolvedType)) {
3816                 return;
3817             }
3818         }
3819 
3820         frameState.push(JavaKind.Object, append(createNewInstance(resolvedType, true)));
3821     }
3822 
3823     /**
3824      * Gets the kind of array elements for the array type code that appears in a
3825      * {@link Bytecodes#NEWARRAY} bytecode.
3826      *
3827      * @param code the array type code
3828      * @return the kind from the array type code
3829      */
3830     private static Class<?> arrayTypeCodeToClass(int code) {
3831         switch (code) {
3832             case 4:
3833                 return boolean.class;
3834             case 5:
3835                 return char.class;
3836             case 6:
3837                 return float.class;
3838             case 7:
3839                 return double.class;
3840             case 8:
3841                 return byte.class;
3842             case 9:
3843                 return short.class;
3844             case 10:
3845                 return int.class;
3846             case 11:
3847                 return long.class;
3848             default:
3849                 throw new IllegalArgumentException("unknown array type code: " + code);
3850         }
3851     }
3852 
3853     private void genNewPrimitiveArray(int typeCode) {
3854         ResolvedJavaType elementType = metaAccess.lookupJavaType(arrayTypeCodeToClass(typeCode));
3855         ValueNode length = frameState.pop(JavaKind.Int);
3856 
3857         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3858             if (plugin.handleNewArray(this, elementType, length)) {
3859                 return;
3860             }
3861         }
3862 
3863         frameState.push(JavaKind.Object, append(createNewArray(elementType, length, true)));
3864     }
3865 
3866     private void genNewObjectArray(int cpi) {
3867         JavaType type = lookupType(cpi, ANEWARRAY);
3868 
3869         if (!(type instanceof ResolvedJavaType)) {
3870             ValueNode length = frameState.pop(JavaKind.Int);
3871             handleUnresolvedNewObjectArray(type, length);
3872             return;
3873         }
3874 
3875         ResolvedJavaType resolvedType = (ResolvedJavaType) type;
3876 
3877         ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
3878         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType.getArrayClass())) {
3879             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3880             classInitializationPlugin.apply(this, resolvedType.getArrayClass(), stateBefore);
3881         }
3882 
3883         ValueNode length = frameState.pop(JavaKind.Int);
3884         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3885             if (plugin.handleNewArray(this, resolvedType, length)) {
3886                 return;
3887             }
3888         }
3889 
3890         frameState.push(JavaKind.Object, append(createNewArray(resolvedType, length, true)));
3891     }
3892 
3893     private void genNewMultiArray(int cpi) {
3894         JavaType type = lookupType(cpi, MULTIANEWARRAY);
3895         int rank = getStream().readUByte(bci() + 3);
3896         ValueNode[] dims = new ValueNode[rank];
3897 
3898         if (!(type instanceof ResolvedJavaType)) {
3899             for (int i = rank - 1; i >= 0; i--) {
3900                 dims[i] = frameState.pop(JavaKind.Int);
3901             }
3902             handleUnresolvedNewMultiArray(type, dims);
3903             return;
3904         }
3905         ResolvedJavaType resolvedType = (ResolvedJavaType) type;
3906 
3907         ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
3908         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType)) {
3909             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3910             classInitializationPlugin.apply(this, resolvedType, stateBefore);
3911         }
3912 
3913         for (int i = rank - 1; i >= 0; i--) {
3914             dims[i] = frameState.pop(JavaKind.Int);
3915         }
3916 
3917         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3918             if (plugin.handleNewMultiArray(this, resolvedType, dims)) {
3919                 return;
3920             }
3921         }
3922 
3923         frameState.push(JavaKind.Object, append(createNewMultiArray(resolvedType, dims)));
3924     }
3925 
3926     protected void genGetField(int cpi, int opcode) {
3927         genGetField(cpi, opcode, frameState.pop(JavaKind.Object));
3928     }
3929 
3930     protected void genGetField(int cpi, int opcode, ValueNode receiverInput) {
3931         JavaField field = lookupField(cpi, opcode);
3932         genGetField(field, receiverInput);
3933     }
3934 
3935     private void genGetField(JavaField field, ValueNode receiverInput) {
3936         ValueNode receiver = emitExplicitExceptions(receiverInput);
3937         if (field instanceof ResolvedJavaField) {
3938             ResolvedJavaField resolvedField = (ResolvedJavaField) field;
3939             genGetField(resolvedField, receiver);
3940         } else {
3941             handleUnresolvedLoadField(field, receiver);
3942         }
3943     }
3944 
3945     private void genGetField(ResolvedJavaField resolvedField, ValueNode receiver) {
3946         if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
3947             graph.recordField(resolvedField);
3948         }
3949 
3950         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3951             if (plugin.handleLoadField(this, receiver, resolvedField)) {
3952                 return;
3953             }
3954         }
3955 
3956         ValueNode fieldRead = append(genLoadField(receiver, resolvedField));
3957 
3958         if (resolvedField.getDeclaringClass().getName().equals("Ljava/lang/ref/Reference;") && resolvedField.getName().equals("referent")) {
3959             LocationIdentity referentIdentity = new FieldLocationIdentity(resolvedField);
3960             append(new MembarNode(0, referentIdentity));
3961         }
3962 
3963         JavaKind fieldKind = resolvedField.getJavaKind();
3964 
3965         if (resolvedField.isVolatile() && fieldRead instanceof LoadFieldNode) {
3966             StateSplitProxyNode readProxy = append(genVolatileFieldReadProxy(fieldRead));
3967             frameState.push(fieldKind, readProxy);
3968             readProxy.setStateAfter(frameState.create(stream.nextBCI(), readProxy));
3969         } else {
3970             frameState.push(fieldKind, fieldRead);
3971         }
3972     }
3973 
3974     /**
3975      * @param receiver the receiver of an object based operation
3976      * @param index the index of an array based operation that is to be tested for out of bounds.
3977      *            This is null for a non-array operation.
3978      * @return the receiver value possibly modified to have a non-null stamp
3979      */
3980     protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) {
3981         if (needsExplicitException()) {
3982             ValueNode nonNullReceiver = emitExplicitNullCheck(receiver);
3983             ValueNode length = append(genArrayLength(nonNullReceiver));
3984             emitExplicitBoundsCheck(index, length);
3985             return nonNullReceiver;
3986         }
3987         return receiver;
3988     }
3989 
3990     protected ValueNode emitExplicitExceptions(ValueNode receiver) {
3991         if (StampTool.isPointerNonNull(receiver) || !needsExplicitException()) {
3992             return receiver;
3993         } else {
3994             return emitExplicitNullCheck(receiver);
3995         }
3996     }
3997 
3998     private boolean needsExplicitException() {
3999         BytecodeExceptionMode exceptionMode = graphBuilderConfig.getBytecodeExceptionMode();
4000         if (exceptionMode == BytecodeExceptionMode.CheckAll || StressExplicitExceptionCode.getValue(options)) {
4001             return true;
4002         } else if (exceptionMode == BytecodeExceptionMode.Profile && profilingInfo != null) {
4003             return profilingInfo.getExceptionSeen(bci()) == TriState.TRUE;
4004         }
4005         return false;
4006     }
4007 
4008     protected void genPutField(int cpi, int opcode) {
4009         JavaField field = lookupField(cpi, opcode);
4010         genPutField(field);
4011     }
4012 
4013     protected void genPutField(JavaField field) {
4014         genPutField(field, frameState.pop(field.getJavaKind()));
4015     }
4016 
4017     private void genPutField(JavaField field, ValueNode value) {
4018         ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object));
4019         if (field instanceof ResolvedJavaField) {
4020             ResolvedJavaField resolvedField = (ResolvedJavaField) field;
4021 
4022             if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
4023                 graph.recordField(resolvedField);
4024             }
4025 
4026             for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
4027                 if (plugin.handleStoreField(this, receiver, resolvedField, value)) {
4028                     return;
4029                 }
4030             }
4031 
4032             if (resolvedField.isFinal() && method.isConstructor()) {
4033                 finalBarrierRequired = true;
4034             }
4035             genStoreField(receiver, resolvedField, value);
4036         } else {
4037             handleUnresolvedStoreField(field, value, receiver);
4038         }
4039     }
4040 
4041     protected void genGetStatic(int cpi, int opcode) {
4042         JavaField field = lookupField(cpi, opcode);
4043         genGetStatic(field);
4044     }
4045 
4046     private void genGetStatic(JavaField field) {
4047         ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, null);
4048         if (resolvedField == null) {
4049             return;
4050         }
4051 
4052         if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
4053             graph.recordField(resolvedField);
4054         }
4055 
4056         /*
4057          * Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in
4058          * which case a suffix is added to the generated field.
4059          */
4060         if ((parsingIntrinsic() || graphBuilderConfig.omitAssertions()) && resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) {
4061             frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph));
4062             return;
4063         }
4064 
4065         ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
4066         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedField.getDeclaringClass())) {
4067             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
4068             classInitializationPlugin.apply(this, resolvedField.getDeclaringClass(), stateBefore);
4069         }
4070 
4071         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
4072             if (plugin.handleLoadStaticField(this, resolvedField)) {
4073                 return;
4074             }
4075         }
4076 
4077         frameState.push(field.getJavaKind(), append(genLoadField(null, resolvedField)));
4078     }
4079 
4080     private ResolvedJavaField resolveStaticFieldAccess(JavaField field, ValueNode value) {
4081         if (field instanceof ResolvedJavaField) {
4082             ResolvedJavaField resolvedField = (ResolvedJavaField) field;
4083             if (resolvedField.getDeclaringClass().isInitialized()) {
4084                 return resolvedField;
4085             }
4086             /*
4087              * Static fields have initialization semantics but may be safely accessed under certain
4088              * conditions while the class is being initialized. Executing in the clinit or init of
4089              * classes which are subtypes of the field holder are sure to be running in a context
4090              * where the access is safe.
4091              */
4092             if (resolvedField.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) {
4093                 if (method.isClassInitializer() || method.isConstructor()) {
4094                     return resolvedField;
4095                 }
4096             }
4097         }
4098         if (value == null) {
4099             handleUnresolvedLoadField(field, null);
4100         } else {
4101             handleUnresolvedStoreField(field, value, null);
4102 
4103         }
4104         return null;
4105     }
4106 
4107     protected void genPutStatic(int cpi, int opcode) {
4108         JavaField field = lookupField(cpi, opcode);
4109         genPutStatic(field);
4110     }
4111 
4112     protected void genPutStatic(JavaField field) {
4113         ValueNode value = frameState.pop(field.getJavaKind());
4114         ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, value);
4115         if (resolvedField == null) {
4116             return;
4117         }
4118 
4119         if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
4120             graph.recordField(resolvedField);
4121         }
4122 
4123         ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
4124         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedField.getDeclaringClass())) {
4125             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
4126             classInitializationPlugin.apply(this, resolvedField.getDeclaringClass(), stateBefore);
4127         }
4128 
4129         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
4130             if (plugin.handleStoreStaticField(this, resolvedField, value)) {
4131                 return;
4132             }
4133         }
4134 
4135         genStoreField(null, resolvedField, value);
4136     }
4137 
4138     private double[] switchProbability(int numberOfCases, int bci) {
4139         double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci));
4140         if (prob != null) {
4141             assert prob.length == numberOfCases;
4142         } else {
4143             debug.log("Missing probability (switch) in %s at bci %d", method, bci);
4144             prob = new double[numberOfCases];
4145             for (int i = 0; i < numberOfCases; i++) {
4146                 prob[i] = 1.0d / numberOfCases;
4147             }
4148         }
4149         assert allPositive(prob);
4150         return prob;
4151     }
4152 
4153     private static boolean allPositive(double[] a) {
4154         for (double d : a) {
4155             if (d < 0) {
4156                 return false;
4157             }
4158         }
4159         return true;
4160     }
4161 
4162     static class SuccessorInfo {
4163         final int blockIndex;
4164         int actualIndex;
4165 
4166         SuccessorInfo(int blockSuccessorIndex) {
4167             this.blockIndex = blockSuccessorIndex;
4168             actualIndex = -1;
4169         }
4170     }
4171 
4172     private void genSwitch(BytecodeSwitch bs) {
4173         int bci = bci();
4174         ValueNode value = frameState.pop(JavaKind.Int);
4175 
4176         int nofCases = bs.numberOfCases();
4177         double[] keyProbabilities = switchProbability(nofCases + 1, bci);
4178 
4179         EconomicMap<Integer, SuccessorInfo> bciToBlockSuccessorIndex = EconomicMap.create(Equivalence.DEFAULT);
4180         for (int i = 0; i < currentBlock.getSuccessorCount(); i++) {
4181             assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci);
4182             bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i));
4183         }
4184 
4185         ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
4186         int[] keys = new int[nofCases];
4187         int[] keySuccessors = new int[nofCases + 1];
4188         int deoptSuccessorIndex = -1;
4189         int nextSuccessorIndex = 0;
4190         boolean constantValue = value.isConstant();
4191         for (int i = 0; i < nofCases + 1; i++) {
4192             if (i < nofCases) {
4193                 keys[i] = bs.keyAt(i);
4194             }
4195 
4196             if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
4197                 if (deoptSuccessorIndex < 0) {
4198                     deoptSuccessorIndex = nextSuccessorIndex++;
4199                     actualSuccessors.add(null);
4200                 }
4201                 keySuccessors[i] = deoptSuccessorIndex;
4202             } else {
4203                 int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i);
4204                 SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
4205                 if (info.actualIndex < 0) {
4206                     info.actualIndex = nextSuccessorIndex++;
4207                     actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex));
4208                 }
4209                 keySuccessors[i] = info.actualIndex;
4210             }
4211         }
4212 
4213         genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors);
4214 
4215     }
4216 
4217     protected boolean isNeverExecutedCode(double probability) {
4218         return probability == 0 && optimisticOpts.removeNeverExecutedCode(getOptions());
4219     }
4220 
4221     private double rawBranchProbability(LogicNode conditionInput) {
4222         if (conditionInput instanceof IntegerEqualsNode) {
4223             // Propagate injected branch probability if any.
4224             IntegerEqualsNode condition = (IntegerEqualsNode) conditionInput;
4225             BranchProbabilityNode injectedProbability = null;
4226             ValueNode other = null;
4227             if (condition.getX() instanceof BranchProbabilityNode) {
4228                 injectedProbability = (BranchProbabilityNode) condition.getX();
4229                 other = condition.getY();
4230             } else if (condition.getY() instanceof BranchProbabilityNode) {
4231                 injectedProbability = (BranchProbabilityNode) condition.getY();
4232                 other = condition.getX();
4233             }
4234 
4235             if (injectedProbability != null && injectedProbability.getProbability().isConstant() && other != null && other.isConstant()) {
4236                 double probabilityValue = injectedProbability.getProbability().asJavaConstant().asDouble();
4237                 return other.asJavaConstant().asInt() == 0 ? 1.0 - probabilityValue : probabilityValue;
4238             }
4239         }
4240 
4241         if (profilingInfo == null) {
4242             return 0.5;
4243         }
4244         assert assertAtIfBytecode();
4245 
4246         return profilingInfo.getBranchTakenProbability(bci());
4247     }
4248 
4249     protected double branchProbability(LogicNode conditionInput) {
4250         double probability = rawBranchProbability(conditionInput);
4251         if (probability < 0) {
4252             assert probability == -1 : "invalid probability";
4253             debug.log("missing probability in %s at bci %d", code, bci());
4254             probability = 0.5;
4255         }
4256 
4257         if (!optimisticOpts.removeNeverExecutedCode(getOptions())) {
4258             if (probability == 0) {
4259                 probability = 0.0000001;
4260             } else if (probability == 1) {
4261                 probability = 0.999999;
4262             }
4263         }
4264         return probability;
4265     }
4266 
4267     private boolean assertAtIfBytecode() {
4268         int bytecode = stream.currentBC();
4269         switch (bytecode) {
4270             case IFEQ:
4271             case IFNE:
4272             case IFLT:
4273             case IFGE:
4274             case IFGT:
4275             case IFLE:
4276             case IF_ICMPEQ:
4277             case IF_ICMPNE:
4278             case IF_ICMPLT:
4279             case IF_ICMPGE:
4280             case IF_ICMPGT:
4281             case IF_ICMPLE:
4282             case IF_ACMPEQ:
4283             case IF_ACMPNE:
4284             case IFNULL:
4285             case IFNONNULL:
4286                 return true;
4287         }
4288         assert false : String.format("%x is not an if bytecode", bytecode);
4289         return true;
4290     }
4291 
4292     public final void processBytecode(int bci, int opcode) {
4293         int cpi;
4294 
4295         // @formatter:off
4296         // Checkstyle: stop
4297         switch (opcode) {
4298             case NOP            : /* nothing to do */ break;
4299             case ACONST_NULL    : frameState.push(JavaKind.Object, appendConstant(JavaConstant.NULL_POINTER)); break;
4300             case ICONST_M1      : // fall through
4301             case ICONST_0       : // fall through
4302             case ICONST_1       : // fall through
4303             case ICONST_2       : // fall through
4304             case ICONST_3       : // fall through
4305             case ICONST_4       : // fall through
4306             case ICONST_5       : frameState.push(JavaKind.Int, appendConstant(JavaConstant.forInt(opcode - ICONST_0))); break;
4307             case LCONST_0       : // fall through
4308             case LCONST_1       : frameState.push(JavaKind.Long, appendConstant(JavaConstant.forLong(opcode - LCONST_0))); break;
4309             case FCONST_0       : // fall through
4310             case FCONST_1       : // fall through
4311             case FCONST_2       : frameState.push(JavaKind.Float, appendConstant(JavaConstant.forFloat(opcode - FCONST_0))); break;
4312             case DCONST_0       : // fall through
4313             case DCONST_1       : frameState.push(JavaKind.Double, appendConstant(JavaConstant.forDouble(opcode - DCONST_0))); break;
4314             case BIPUSH         : frameState.push(JavaKind.Int, appendConstant(JavaConstant.forInt(stream.readByte()))); break;
4315             case SIPUSH         : frameState.push(JavaKind.Int, appendConstant(JavaConstant.forInt(stream.readShort()))); break;
4316             case LDC            : // fall through
4317             case LDC_W          : // fall through
4318             case LDC2_W         : genLoadConstant(stream.readCPI(), opcode); break;
4319             case ILOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Int); break;
4320             case LLOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Long); break;
4321             case FLOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Float); break;
4322             case DLOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Double); break;
4323             case ALOAD          : loadLocalObject(stream.readLocalIndex()); break;
4324             case ILOAD_0        : // fall through
4325             case ILOAD_1        : // fall through
4326             case ILOAD_2        : // fall through
4327             case ILOAD_3        : loadLocal(opcode - ILOAD_0, JavaKind.Int); break;
4328             case LLOAD_0        : // fall through
4329             case LLOAD_1        : // fall through
4330             case LLOAD_2        : // fall through
4331             case LLOAD_3        : loadLocal(opcode - LLOAD_0, JavaKind.Long); break;
4332             case FLOAD_0        : // fall through
4333             case FLOAD_1        : // fall through
4334             case FLOAD_2        : // fall through
4335             case FLOAD_3        : loadLocal(opcode - FLOAD_0, JavaKind.Float); break;
4336             case DLOAD_0        : // fall through
4337             case DLOAD_1        : // fall through
4338             case DLOAD_2        : // fall through
4339             case DLOAD_3        : loadLocal(opcode - DLOAD_0, JavaKind.Double); break;
4340             case ALOAD_0        : // fall through
4341             case ALOAD_1        : // fall through
4342             case ALOAD_2        : // fall through
4343             case ALOAD_3        : loadLocalObject(opcode - ALOAD_0); break;
4344             case IALOAD         : genLoadIndexed(JavaKind.Int   ); break;
4345             case LALOAD         : genLoadIndexed(JavaKind.Long  ); break;
4346             case FALOAD         : genLoadIndexed(JavaKind.Float ); break;
4347             case DALOAD         : genLoadIndexed(JavaKind.Double); break;
4348             case AALOAD         : genLoadIndexed(JavaKind.Object); break;
4349             case BALOAD         : genLoadIndexed(JavaKind.Byte  ); break;
4350             case CALOAD         : genLoadIndexed(JavaKind.Char  ); break;
4351             case SALOAD         : genLoadIndexed(JavaKind.Short ); break;
4352             case ISTORE         : storeLocal(JavaKind.Int, stream.readLocalIndex()); break;
4353             case LSTORE         : storeLocal(JavaKind.Long, stream.readLocalIndex()); break;
4354             case FSTORE         : storeLocal(JavaKind.Float, stream.readLocalIndex()); break;
4355             case DSTORE         : storeLocal(JavaKind.Double, stream.readLocalIndex()); break;
4356             case ASTORE         : storeLocal(JavaKind.Object, stream.readLocalIndex()); break;
4357             case ISTORE_0       : // fall through
4358             case ISTORE_1       : // fall through
4359             case ISTORE_2       : // fall through
4360             case ISTORE_3       : storeLocal(JavaKind.Int, opcode - ISTORE_0); break;
4361             case LSTORE_0       : // fall through
4362             case LSTORE_1       : // fall through
4363             case LSTORE_2       : // fall through
4364             case LSTORE_3       : storeLocal(JavaKind.Long, opcode - LSTORE_0); break;
4365             case FSTORE_0       : // fall through
4366             case FSTORE_1       : // fall through
4367             case FSTORE_2       : // fall through
4368             case FSTORE_3       : storeLocal(JavaKind.Float, opcode - FSTORE_0); break;
4369             case DSTORE_0       : // fall through
4370             case DSTORE_1       : // fall through
4371             case DSTORE_2       : // fall through
4372             case DSTORE_3       : storeLocal(JavaKind.Double, opcode - DSTORE_0); break;
4373             case ASTORE_0       : // fall through
4374             case ASTORE_1       : // fall through
4375             case ASTORE_2       : // fall through
4376             case ASTORE_3       : storeLocal(JavaKind.Object, opcode - ASTORE_0); break;
4377             case IASTORE        : genStoreIndexed(JavaKind.Int   ); break;
4378             case LASTORE        : genStoreIndexed(JavaKind.Long  ); break;
4379             case FASTORE        : genStoreIndexed(JavaKind.Float ); break;
4380             case DASTORE        : genStoreIndexed(JavaKind.Double); break;
4381             case AASTORE        : genStoreIndexed(JavaKind.Object); break;
4382             case BASTORE        : genStoreIndexed(JavaKind.Byte  ); break;
4383             case CASTORE        : genStoreIndexed(JavaKind.Char  ); break;
4384             case SASTORE        : genStoreIndexed(JavaKind.Short ); break;
4385             case POP            : // fall through
4386             case POP2           : // fall through
4387             case DUP            : // fall through
4388             case DUP_X1         : // fall through
4389             case DUP_X2         : // fall through
4390             case DUP2           : // fall through
4391             case DUP2_X1        : // fall through
4392             case DUP2_X2        : // fall through
4393             case SWAP           : frameState.stackOp(opcode); break;
4394             case IADD           : // fall through
4395             case ISUB           : // fall through
4396             case IMUL           : genArithmeticOp(JavaKind.Int, opcode); break;
4397             case IDIV           : // fall through
4398             case IREM           : genIntegerDivOp(JavaKind.Int, opcode); break;
4399             case LADD           : // fall through
4400             case LSUB           : // fall through
4401             case LMUL           : genArithmeticOp(JavaKind.Long, opcode); break;
4402             case LDIV           : // fall through
4403             case LREM           : genIntegerDivOp(JavaKind.Long, opcode); break;
4404             case FADD           : // fall through
4405             case FSUB           : // fall through
4406             case FMUL           : // fall through
4407             case FDIV           : // fall through
4408             case FREM           : genArithmeticOp(JavaKind.Float, opcode); break;
4409             case DADD           : // fall through
4410             case DSUB           : // fall through
4411             case DMUL           : // fall through
4412             case DDIV           : // fall through
4413             case DREM           : genArithmeticOp(JavaKind.Double, opcode); break;
4414             case INEG           : genNegateOp(JavaKind.Int); break;
4415             case LNEG           : genNegateOp(JavaKind.Long); break;
4416             case FNEG           : genNegateOp(JavaKind.Float); break;
4417             case DNEG           : genNegateOp(JavaKind.Double); break;
4418             case ISHL           : // fall through
4419             case ISHR           : // fall through
4420             case IUSHR          : genShiftOp(JavaKind.Int, opcode); break;
4421             case IAND           : // fall through
4422             case IOR            : // fall through
4423             case IXOR           : genLogicOp(JavaKind.Int, opcode); break;
4424             case LSHL           : // fall through
4425             case LSHR           : // fall through
4426             case LUSHR          : genShiftOp(JavaKind.Long, opcode); break;
4427             case LAND           : // fall through
4428             case LOR            : // fall through
4429             case LXOR           : genLogicOp(JavaKind.Long, opcode); break;
4430             case IINC           : genIncrement(); break;
4431             case I2F            : genFloatConvert(FloatConvert.I2F, JavaKind.Int, JavaKind.Float); break;
4432             case I2D            : genFloatConvert(FloatConvert.I2D, JavaKind.Int, JavaKind.Double); break;
4433             case L2F            : genFloatConvert(FloatConvert.L2F, JavaKind.Long, JavaKind.Float); break;
4434             case L2D            : genFloatConvert(FloatConvert.L2D, JavaKind.Long, JavaKind.Double); break;
4435             case F2I            : genFloatConvert(FloatConvert.F2I, JavaKind.Float, JavaKind.Int); break;
4436             case F2L            : genFloatConvert(FloatConvert.F2L, JavaKind.Float, JavaKind.Long); break;
4437             case F2D            : genFloatConvert(FloatConvert.F2D, JavaKind.Float, JavaKind.Double); break;
4438             case D2I            : genFloatConvert(FloatConvert.D2I, JavaKind.Double, JavaKind.Int); break;
4439             case D2L            : genFloatConvert(FloatConvert.D2L, JavaKind.Double, JavaKind.Long); break;
4440             case D2F            : genFloatConvert(FloatConvert.D2F, JavaKind.Double, JavaKind.Float); break;
4441             case L2I            : genNarrow(JavaKind.Long, JavaKind.Int); break;
4442             case I2L            : genSignExtend(JavaKind.Int, JavaKind.Long); break;
4443             case I2B            : genSignExtend(JavaKind.Byte, JavaKind.Int); break;
4444             case I2S            : genSignExtend(JavaKind.Short, JavaKind.Int); break;
4445             case I2C            : genZeroExtend(JavaKind.Char, JavaKind.Int); break;
4446             case LCMP           : genCompareOp(JavaKind.Long, false); break;
4447             case FCMPL          : genCompareOp(JavaKind.Float, true); break;
4448             case FCMPG          : genCompareOp(JavaKind.Float, false); break;
4449             case DCMPL          : genCompareOp(JavaKind.Double, true); break;
4450             case DCMPG          : genCompareOp(JavaKind.Double, false); break;
4451             case IFEQ           : genIfZero(Condition.EQ); break;
4452             case IFNE           : genIfZero(Condition.NE); break;
4453             case IFLT           : genIfZero(Condition.LT); break;
4454             case IFGE           : genIfZero(Condition.GE); break;
4455             case IFGT           : genIfZero(Condition.GT); break;
4456             case IFLE           : genIfZero(Condition.LE); break;
4457             case IF_ICMPEQ      : genIfSame(JavaKind.Int, Condition.EQ); break;
4458             case IF_ICMPNE      : genIfSame(JavaKind.Int, Condition.NE); break;
4459             case IF_ICMPLT      : genIfSame(JavaKind.Int, Condition.LT); break;
4460             case IF_ICMPGE      : genIfSame(JavaKind.Int, Condition.GE); break;
4461             case IF_ICMPGT      : genIfSame(JavaKind.Int, Condition.GT); break;
4462             case IF_ICMPLE      : genIfSame(JavaKind.Int, Condition.LE); break;
4463             case IF_ACMPEQ      : genIfSame(JavaKind.Object, Condition.EQ); break;
4464             case IF_ACMPNE      : genIfSame(JavaKind.Object, Condition.NE); break;
4465             case GOTO           : genGoto(); break;
4466             case JSR            : genJsr(stream.readBranchDest()); break;
4467             case RET            : genRet(stream.readLocalIndex()); break;
4468             case TABLESWITCH    : genSwitch(new BytecodeTableSwitch(getStream(), bci())); break;
4469             case LOOKUPSWITCH   : genSwitch(new BytecodeLookupSwitch(getStream(), bci())); break;
4470             case IRETURN        : genReturn(frameState.pop(JavaKind.Int), JavaKind.Int); break;
4471             case LRETURN        : genReturn(frameState.pop(JavaKind.Long), JavaKind.Long); break;
4472             case FRETURN        : genReturn(frameState.pop(JavaKind.Float), JavaKind.Float); break;
4473             case DRETURN        : genReturn(frameState.pop(JavaKind.Double), JavaKind.Double); break;
4474             case ARETURN        : genReturn(frameState.pop(JavaKind.Object), JavaKind.Object); break;
4475             case RETURN         : genReturn(null, JavaKind.Void); break;
4476             case GETSTATIC      : cpi = stream.readCPI(); genGetStatic(cpi, opcode); break;
4477             case PUTSTATIC      : cpi = stream.readCPI(); genPutStatic(cpi, opcode); break;
4478             case GETFIELD       : cpi = stream.readCPI(); genGetField(cpi, opcode); break;
4479             case PUTFIELD       : cpi = stream.readCPI(); genPutField(cpi, opcode); break;
4480             case INVOKEVIRTUAL  : cpi = stream.readCPI(); genInvokeVirtual(cpi, opcode); break;
4481             case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(cpi, opcode); break;
4482             case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(cpi, opcode); break;
4483             case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(cpi, opcode); break;
4484             case INVOKEDYNAMIC  : cpi = stream.readCPI4(); genInvokeDynamic(cpi, opcode); break;
4485             case NEW            : genNewInstance(stream.readCPI()); break;
4486             case NEWARRAY       : genNewPrimitiveArray(stream.readLocalIndex()); break;
4487             case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
4488             case ARRAYLENGTH    : genArrayLength(); break;
4489             case ATHROW         : genThrow(); break;
4490             case CHECKCAST      : genCheckCast(); break;
4491             case INSTANCEOF     : genInstanceOf(); break;
4492             case MONITORENTER   : genMonitorEnter(frameState.pop(JavaKind.Object), stream.nextBCI()); break;
4493             case MONITOREXIT    : genMonitorExit(frameState.pop(JavaKind.Object), null, stream.nextBCI()); break;
4494             case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
4495             case IFNULL         : genIfNull(Condition.EQ); break;
4496             case IFNONNULL      : genIfNull(Condition.NE); break;
4497             case GOTO_W         : genGoto(); break;
4498             case JSR_W          : genJsr(stream.readBranchDest()); break;
4499             case BREAKPOINT     : throw new PermanentBailoutException("concurrent setting of breakpoint");
4500             default             : throw new PermanentBailoutException("Unsupported opcode %d (%s) [bci=%d]", opcode, nameOf(opcode), bci);
4501         }
4502         // @formatter:on
4503         // Checkstyle: resume
4504     }
4505 
4506     private void genArrayLength() {
4507         ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object));
4508         frameState.push(JavaKind.Int, append(genArrayLength(array)));
4509     }
4510 
4511     @Override
4512     public ResolvedJavaMethod getMethod() {
4513         return method;
4514     }
4515 
4516     @Override
4517     public Bytecode getCode() {
4518         return code;
4519     }
4520 
4521     public FrameStateBuilder getFrameStateBuilder() {
4522         return frameState;
4523     }
4524 
4525     protected boolean traceInstruction(int bci, int opcode, boolean blockStart) {
4526         if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) {
4527             traceInstructionHelper(bci, opcode, blockStart);
4528         }
4529         return true;
4530     }
4531 
4532     private void traceInstructionHelper(int bci, int opcode, boolean blockStart) {
4533         StringBuilder sb = new StringBuilder(40);
4534         sb.append(blockStart ? '+' : '|');
4535         if (bci < 10) {
4536             sb.append("  ");
4537         } else if (bci < 100) {
4538             sb.append(' ');
4539         }
4540         sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode));
4541         for (int i = bci + 1; i < stream.nextBCI(); ++i) {
4542             sb.append(' ').append(stream.readUByte(i));
4543         }
4544         if (!currentBlock.getJsrScope().isEmpty()) {
4545             sb.append(' ').append(currentBlock.getJsrScope());
4546         }
4547         debug.log("%s", sb);
4548     }
4549 
4550     @Override
4551     public boolean parsingIntrinsic() {
4552         return intrinsicContext != null;
4553     }
4554 
4555     @Override
4556     public BytecodeParser getNonIntrinsicAncestor() {
4557         BytecodeParser ancestor = parent;
4558         while (ancestor != null && ancestor.parsingIntrinsic()) {
4559             ancestor = ancestor.parent;
4560         }
4561         return ancestor;
4562     }
4563 
4564     static String nSpaces(int n) {
4565         return n == 0 ? "" : format("%" + n + "s", "");
4566     }
4567 }