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