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