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