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