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