BytecodeParser.java revision 12651:6ef01bd40ce2
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 */
23package org.graalvm.compiler.java;
24
25import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
26import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE;
27import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL;
28import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD;
29import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_0;
30import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_1;
31import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_2;
32import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_3;
33import static org.graalvm.compiler.bytecode.Bytecodes.ANEWARRAY;
34import static org.graalvm.compiler.bytecode.Bytecodes.ARETURN;
35import static org.graalvm.compiler.bytecode.Bytecodes.ARRAYLENGTH;
36import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE;
37import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_0;
38import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_1;
39import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_2;
40import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_3;
41import static org.graalvm.compiler.bytecode.Bytecodes.ATHROW;
42import static org.graalvm.compiler.bytecode.Bytecodes.BALOAD;
43import static org.graalvm.compiler.bytecode.Bytecodes.BASTORE;
44import static org.graalvm.compiler.bytecode.Bytecodes.BIPUSH;
45import static org.graalvm.compiler.bytecode.Bytecodes.BREAKPOINT;
46import static org.graalvm.compiler.bytecode.Bytecodes.CALOAD;
47import static org.graalvm.compiler.bytecode.Bytecodes.CASTORE;
48import static org.graalvm.compiler.bytecode.Bytecodes.CHECKCAST;
49import static org.graalvm.compiler.bytecode.Bytecodes.D2F;
50import static org.graalvm.compiler.bytecode.Bytecodes.D2I;
51import static org.graalvm.compiler.bytecode.Bytecodes.D2L;
52import static org.graalvm.compiler.bytecode.Bytecodes.DADD;
53import static org.graalvm.compiler.bytecode.Bytecodes.DALOAD;
54import static org.graalvm.compiler.bytecode.Bytecodes.DASTORE;
55import static org.graalvm.compiler.bytecode.Bytecodes.DCMPG;
56import static org.graalvm.compiler.bytecode.Bytecodes.DCMPL;
57import static org.graalvm.compiler.bytecode.Bytecodes.DCONST_0;
58import static org.graalvm.compiler.bytecode.Bytecodes.DCONST_1;
59import static org.graalvm.compiler.bytecode.Bytecodes.DDIV;
60import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD;
61import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_0;
62import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_1;
63import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_2;
64import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_3;
65import static org.graalvm.compiler.bytecode.Bytecodes.DMUL;
66import static org.graalvm.compiler.bytecode.Bytecodes.DNEG;
67import static org.graalvm.compiler.bytecode.Bytecodes.DREM;
68import static org.graalvm.compiler.bytecode.Bytecodes.DRETURN;
69import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE;
70import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_0;
71import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_1;
72import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_2;
73import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_3;
74import static org.graalvm.compiler.bytecode.Bytecodes.DSUB;
75import static org.graalvm.compiler.bytecode.Bytecodes.DUP;
76import static org.graalvm.compiler.bytecode.Bytecodes.DUP2;
77import static org.graalvm.compiler.bytecode.Bytecodes.DUP2_X1;
78import static org.graalvm.compiler.bytecode.Bytecodes.DUP2_X2;
79import static org.graalvm.compiler.bytecode.Bytecodes.DUP_X1;
80import static org.graalvm.compiler.bytecode.Bytecodes.DUP_X2;
81import static org.graalvm.compiler.bytecode.Bytecodes.F2D;
82import static org.graalvm.compiler.bytecode.Bytecodes.F2I;
83import static org.graalvm.compiler.bytecode.Bytecodes.F2L;
84import static org.graalvm.compiler.bytecode.Bytecodes.FADD;
85import static org.graalvm.compiler.bytecode.Bytecodes.FALOAD;
86import static org.graalvm.compiler.bytecode.Bytecodes.FASTORE;
87import static org.graalvm.compiler.bytecode.Bytecodes.FCMPG;
88import static org.graalvm.compiler.bytecode.Bytecodes.FCMPL;
89import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_0;
90import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_1;
91import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_2;
92import static org.graalvm.compiler.bytecode.Bytecodes.FDIV;
93import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD;
94import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_0;
95import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_1;
96import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_2;
97import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_3;
98import static org.graalvm.compiler.bytecode.Bytecodes.FMUL;
99import static org.graalvm.compiler.bytecode.Bytecodes.FNEG;
100import static org.graalvm.compiler.bytecode.Bytecodes.FREM;
101import static org.graalvm.compiler.bytecode.Bytecodes.FRETURN;
102import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE;
103import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_0;
104import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_1;
105import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_2;
106import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_3;
107import static org.graalvm.compiler.bytecode.Bytecodes.FSUB;
108import static org.graalvm.compiler.bytecode.Bytecodes.GETFIELD;
109import static org.graalvm.compiler.bytecode.Bytecodes.GETSTATIC;
110import static org.graalvm.compiler.bytecode.Bytecodes.GOTO;
111import static org.graalvm.compiler.bytecode.Bytecodes.GOTO_W;
112import static org.graalvm.compiler.bytecode.Bytecodes.I2B;
113import static org.graalvm.compiler.bytecode.Bytecodes.I2C;
114import static org.graalvm.compiler.bytecode.Bytecodes.I2D;
115import static org.graalvm.compiler.bytecode.Bytecodes.I2F;
116import static org.graalvm.compiler.bytecode.Bytecodes.I2L;
117import static org.graalvm.compiler.bytecode.Bytecodes.I2S;
118import static org.graalvm.compiler.bytecode.Bytecodes.IADD;
119import static org.graalvm.compiler.bytecode.Bytecodes.IALOAD;
120import static org.graalvm.compiler.bytecode.Bytecodes.IAND;
121import static org.graalvm.compiler.bytecode.Bytecodes.IASTORE;
122import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_0;
123import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_1;
124import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_2;
125import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_3;
126import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_4;
127import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_5;
128import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_M1;
129import static org.graalvm.compiler.bytecode.Bytecodes.IDIV;
130import static org.graalvm.compiler.bytecode.Bytecodes.IFEQ;
131import static org.graalvm.compiler.bytecode.Bytecodes.IFGE;
132import static org.graalvm.compiler.bytecode.Bytecodes.IFGT;
133import static org.graalvm.compiler.bytecode.Bytecodes.IFLE;
134import static org.graalvm.compiler.bytecode.Bytecodes.IFLT;
135import static org.graalvm.compiler.bytecode.Bytecodes.IFNE;
136import static org.graalvm.compiler.bytecode.Bytecodes.IFNONNULL;
137import static org.graalvm.compiler.bytecode.Bytecodes.IFNULL;
138import static org.graalvm.compiler.bytecode.Bytecodes.IF_ACMPEQ;
139import static org.graalvm.compiler.bytecode.Bytecodes.IF_ACMPNE;
140import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPEQ;
141import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPGE;
142import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPGT;
143import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPLE;
144import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPLT;
145import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPNE;
146import static org.graalvm.compiler.bytecode.Bytecodes.IINC;
147import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD;
148import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_0;
149import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_1;
150import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_2;
151import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_3;
152import static org.graalvm.compiler.bytecode.Bytecodes.IMUL;
153import static org.graalvm.compiler.bytecode.Bytecodes.INEG;
154import static org.graalvm.compiler.bytecode.Bytecodes.INSTANCEOF;
155import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEDYNAMIC;
156import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEINTERFACE;
157import static org.graalvm.compiler.bytecode.Bytecodes.INVOKESPECIAL;
158import static org.graalvm.compiler.bytecode.Bytecodes.INVOKESTATIC;
159import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEVIRTUAL;
160import static org.graalvm.compiler.bytecode.Bytecodes.IOR;
161import static org.graalvm.compiler.bytecode.Bytecodes.IREM;
162import static org.graalvm.compiler.bytecode.Bytecodes.IRETURN;
163import static org.graalvm.compiler.bytecode.Bytecodes.ISHL;
164import static org.graalvm.compiler.bytecode.Bytecodes.ISHR;
165import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE;
166import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_0;
167import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_1;
168import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_2;
169import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_3;
170import static org.graalvm.compiler.bytecode.Bytecodes.ISUB;
171import static org.graalvm.compiler.bytecode.Bytecodes.IUSHR;
172import static org.graalvm.compiler.bytecode.Bytecodes.IXOR;
173import static org.graalvm.compiler.bytecode.Bytecodes.JSR;
174import static org.graalvm.compiler.bytecode.Bytecodes.JSR_W;
175import static org.graalvm.compiler.bytecode.Bytecodes.L2D;
176import static org.graalvm.compiler.bytecode.Bytecodes.L2F;
177import static org.graalvm.compiler.bytecode.Bytecodes.L2I;
178import static org.graalvm.compiler.bytecode.Bytecodes.LADD;
179import static org.graalvm.compiler.bytecode.Bytecodes.LALOAD;
180import static org.graalvm.compiler.bytecode.Bytecodes.LAND;
181import static org.graalvm.compiler.bytecode.Bytecodes.LASTORE;
182import static org.graalvm.compiler.bytecode.Bytecodes.LCMP;
183import static org.graalvm.compiler.bytecode.Bytecodes.LCONST_0;
184import static org.graalvm.compiler.bytecode.Bytecodes.LCONST_1;
185import static org.graalvm.compiler.bytecode.Bytecodes.LDC;
186import static org.graalvm.compiler.bytecode.Bytecodes.LDC2_W;
187import static org.graalvm.compiler.bytecode.Bytecodes.LDC_W;
188import static org.graalvm.compiler.bytecode.Bytecodes.LDIV;
189import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD;
190import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_0;
191import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_1;
192import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_2;
193import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_3;
194import static org.graalvm.compiler.bytecode.Bytecodes.LMUL;
195import static org.graalvm.compiler.bytecode.Bytecodes.LNEG;
196import static org.graalvm.compiler.bytecode.Bytecodes.LOOKUPSWITCH;
197import static org.graalvm.compiler.bytecode.Bytecodes.LOR;
198import static org.graalvm.compiler.bytecode.Bytecodes.LREM;
199import static org.graalvm.compiler.bytecode.Bytecodes.LRETURN;
200import static org.graalvm.compiler.bytecode.Bytecodes.LSHL;
201import static org.graalvm.compiler.bytecode.Bytecodes.LSHR;
202import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE;
203import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_0;
204import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_1;
205import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_2;
206import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_3;
207import static org.graalvm.compiler.bytecode.Bytecodes.LSUB;
208import static org.graalvm.compiler.bytecode.Bytecodes.LUSHR;
209import static org.graalvm.compiler.bytecode.Bytecodes.LXOR;
210import static org.graalvm.compiler.bytecode.Bytecodes.MONITORENTER;
211import static org.graalvm.compiler.bytecode.Bytecodes.MONITOREXIT;
212import static org.graalvm.compiler.bytecode.Bytecodes.MULTIANEWARRAY;
213import static org.graalvm.compiler.bytecode.Bytecodes.NEW;
214import static org.graalvm.compiler.bytecode.Bytecodes.NEWARRAY;
215import static org.graalvm.compiler.bytecode.Bytecodes.NOP;
216import static org.graalvm.compiler.bytecode.Bytecodes.POP;
217import static org.graalvm.compiler.bytecode.Bytecodes.POP2;
218import static org.graalvm.compiler.bytecode.Bytecodes.PUTFIELD;
219import static org.graalvm.compiler.bytecode.Bytecodes.PUTSTATIC;
220import static org.graalvm.compiler.bytecode.Bytecodes.RET;
221import static org.graalvm.compiler.bytecode.Bytecodes.RETURN;
222import static org.graalvm.compiler.bytecode.Bytecodes.SALOAD;
223import static org.graalvm.compiler.bytecode.Bytecodes.SASTORE;
224import static org.graalvm.compiler.bytecode.Bytecodes.SIPUSH;
225import static org.graalvm.compiler.bytecode.Bytecodes.SWAP;
226import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH;
227import static org.graalvm.compiler.bytecode.Bytecodes.nameOf;
228import static org.graalvm.compiler.core.common.GraalOptions.DeoptALot;
229import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
230import static org.graalvm.compiler.core.common.GraalOptions.PrintProfilingInformation;
231import static org.graalvm.compiler.core.common.GraalOptions.ResolveClassBeforeStaticInvoke;
232import static org.graalvm.compiler.core.common.GraalOptions.StressInvokeWithExceptionNode;
233import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation;
234import static org.graalvm.compiler.core.common.type.StampFactory.objectNonNull;
235import static org.graalvm.compiler.debug.GraalError.guarantee;
236import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
237import static org.graalvm.compiler.java.BytecodeParserOptions.DumpDuringGraphBuilding;
238import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
239import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
240import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics;
241import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING;
242import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull;
243import static java.lang.String.format;
244import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile;
245import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
246import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
247import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
248import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
249import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated;
250import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
251import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved;
252import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
253
254import java.lang.ref.Reference;
255import java.util.ArrayList;
256import java.util.Collections;
257import java.util.Comparator;
258import java.util.Formatter;
259import java.util.HashMap;
260import java.util.List;
261import java.util.Map;
262
263import org.graalvm.compiler.bytecode.Bytecode;
264import org.graalvm.compiler.bytecode.BytecodeDisassembler;
265import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
266import org.graalvm.compiler.bytecode.BytecodeProvider;
267import org.graalvm.compiler.bytecode.BytecodeStream;
268import org.graalvm.compiler.bytecode.BytecodeSwitch;
269import org.graalvm.compiler.bytecode.BytecodeTableSwitch;
270import org.graalvm.compiler.bytecode.Bytecodes;
271import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
272import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
273import org.graalvm.compiler.common.PermanentBailoutException;
274import org.graalvm.compiler.core.common.GraalOptions;
275import org.graalvm.compiler.core.common.LocationIdentity;
276import org.graalvm.compiler.core.common.calc.Condition;
277import org.graalvm.compiler.core.common.calc.FloatConvert;
278import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
279import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
280import org.graalvm.compiler.core.common.type.ObjectStamp;
281import org.graalvm.compiler.core.common.type.Stamp;
282import org.graalvm.compiler.core.common.type.StampFactory;
283import org.graalvm.compiler.core.common.type.StampPair;
284import org.graalvm.compiler.core.common.type.TypeReference;
285import org.graalvm.compiler.core.common.util.Util;
286import org.graalvm.compiler.debug.Debug;
287import org.graalvm.compiler.debug.Debug.Scope;
288import org.graalvm.compiler.debug.DebugCloseable;
289import org.graalvm.compiler.debug.DebugCounter;
290import org.graalvm.compiler.debug.GraalError;
291import org.graalvm.compiler.debug.Indent;
292import org.graalvm.compiler.debug.TTY;
293import org.graalvm.compiler.graph.Graph.Mark;
294import org.graalvm.compiler.graph.Node;
295import org.graalvm.compiler.graph.NodeSourcePosition;
296import org.graalvm.compiler.graph.iterators.NodeIterable;
297import org.graalvm.compiler.java.BciBlockMapping.BciBlock;
298import org.graalvm.compiler.java.BciBlockMapping.ExceptionDispatchBlock;
299import org.graalvm.compiler.nodeinfo.InputType;
300import org.graalvm.compiler.nodes.AbstractBeginNode;
301import org.graalvm.compiler.nodes.AbstractMergeNode;
302import org.graalvm.compiler.nodes.BeginNode;
303import org.graalvm.compiler.nodes.BeginStateSplitNode;
304import org.graalvm.compiler.nodes.CallTargetNode;
305import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
306import org.graalvm.compiler.nodes.ConstantNode;
307import org.graalvm.compiler.nodes.ControlSplitNode;
308import org.graalvm.compiler.nodes.DeoptimizeNode;
309import org.graalvm.compiler.nodes.EndNode;
310import org.graalvm.compiler.nodes.EntryMarkerNode;
311import org.graalvm.compiler.nodes.EntryProxyNode;
312import org.graalvm.compiler.nodes.FieldLocationIdentity;
313import org.graalvm.compiler.nodes.FixedGuardNode;
314import org.graalvm.compiler.nodes.FixedNode;
315import org.graalvm.compiler.nodes.FixedWithNextNode;
316import org.graalvm.compiler.nodes.FrameState;
317import org.graalvm.compiler.nodes.FullInfopointNode;
318import org.graalvm.compiler.nodes.IfNode;
319import org.graalvm.compiler.nodes.Invoke;
320import org.graalvm.compiler.nodes.InvokeNode;
321import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
322import org.graalvm.compiler.nodes.KillingBeginNode;
323import org.graalvm.compiler.nodes.LogicConstantNode;
324import org.graalvm.compiler.nodes.LogicNegationNode;
325import org.graalvm.compiler.nodes.LogicNode;
326import org.graalvm.compiler.nodes.LoopBeginNode;
327import org.graalvm.compiler.nodes.LoopEndNode;
328import org.graalvm.compiler.nodes.LoopExitNode;
329import org.graalvm.compiler.nodes.MergeNode;
330import org.graalvm.compiler.nodes.ParameterNode;
331import org.graalvm.compiler.nodes.PiNode;
332import org.graalvm.compiler.nodes.ReturnNode;
333import org.graalvm.compiler.nodes.StartNode;
334import org.graalvm.compiler.nodes.StateSplit;
335import org.graalvm.compiler.nodes.StructuredGraph;
336import org.graalvm.compiler.nodes.UnwindNode;
337import org.graalvm.compiler.nodes.ValueNode;
338import org.graalvm.compiler.nodes.calc.AddNode;
339import org.graalvm.compiler.nodes.calc.AndNode;
340import org.graalvm.compiler.nodes.calc.CompareNode;
341import org.graalvm.compiler.nodes.calc.ConditionalNode;
342import org.graalvm.compiler.nodes.calc.DivNode;
343import org.graalvm.compiler.nodes.calc.FloatConvertNode;
344import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
345import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
346import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
347import org.graalvm.compiler.nodes.calc.IsNullNode;
348import org.graalvm.compiler.nodes.calc.LeftShiftNode;
349import org.graalvm.compiler.nodes.calc.MulNode;
350import org.graalvm.compiler.nodes.calc.NarrowNode;
351import org.graalvm.compiler.nodes.calc.NegateNode;
352import org.graalvm.compiler.nodes.calc.NormalizeCompareNode;
353import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
354import org.graalvm.compiler.nodes.calc.OrNode;
355import org.graalvm.compiler.nodes.calc.RemNode;
356import org.graalvm.compiler.nodes.calc.RightShiftNode;
357import org.graalvm.compiler.nodes.calc.SignExtendNode;
358import org.graalvm.compiler.nodes.calc.SignedDivNode;
359import org.graalvm.compiler.nodes.calc.SignedRemNode;
360import org.graalvm.compiler.nodes.calc.SubNode;
361import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
362import org.graalvm.compiler.nodes.calc.XorNode;
363import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
364import org.graalvm.compiler.nodes.debug.instrumentation.InstrumentationBeginNode;
365import org.graalvm.compiler.nodes.extended.AnchoringNode;
366import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
367import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode;
368import org.graalvm.compiler.nodes.extended.GuardedNode;
369import org.graalvm.compiler.nodes.extended.GuardingNode;
370import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
371import org.graalvm.compiler.nodes.extended.LoadHubNode;
372import org.graalvm.compiler.nodes.extended.LoadMethodNode;
373import org.graalvm.compiler.nodes.extended.MembarNode;
374import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
375import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
376import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
377import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
378import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
379import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
380import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo;
381import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
382import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
383import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
384import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
385import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin;
386import org.graalvm.compiler.nodes.java.ArrayLengthNode;
387import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
388import org.graalvm.compiler.nodes.java.FinalFieldBarrierNode;
389import org.graalvm.compiler.nodes.java.InstanceOfNode;
390import org.graalvm.compiler.nodes.java.LoadFieldNode;
391import org.graalvm.compiler.nodes.java.LoadIndexedNode;
392import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
393import org.graalvm.compiler.nodes.java.MonitorEnterNode;
394import org.graalvm.compiler.nodes.java.MonitorExitNode;
395import org.graalvm.compiler.nodes.java.MonitorIdNode;
396import org.graalvm.compiler.nodes.java.NewArrayNode;
397import org.graalvm.compiler.nodes.java.NewInstanceNode;
398import org.graalvm.compiler.nodes.java.NewMultiArrayNode;
399import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
400import org.graalvm.compiler.nodes.java.StoreFieldNode;
401import org.graalvm.compiler.nodes.java.StoreIndexedNode;
402import org.graalvm.compiler.nodes.spi.StampProvider;
403import org.graalvm.compiler.nodes.type.StampTool;
404import org.graalvm.compiler.nodes.util.GraphUtil;
405import org.graalvm.compiler.phases.OptimisticOptimizations;
406
407import jdk.vm.ci.code.BailoutException;
408import jdk.vm.ci.code.BytecodeFrame;
409import jdk.vm.ci.code.CodeUtil;
410import jdk.vm.ci.code.site.InfopointReason;
411import jdk.vm.ci.meta.ConstantPool;
412import jdk.vm.ci.meta.ConstantReflectionProvider;
413import jdk.vm.ci.meta.DeoptimizationAction;
414import jdk.vm.ci.meta.DeoptimizationReason;
415import jdk.vm.ci.meta.JavaConstant;
416import jdk.vm.ci.meta.JavaField;
417import jdk.vm.ci.meta.JavaKind;
418import jdk.vm.ci.meta.JavaMethod;
419import jdk.vm.ci.meta.JavaType;
420import jdk.vm.ci.meta.JavaTypeProfile;
421import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
422import jdk.vm.ci.meta.LineNumberTable;
423import jdk.vm.ci.meta.MetaAccessProvider;
424import jdk.vm.ci.meta.ProfilingInfo;
425import jdk.vm.ci.meta.RawConstant;
426import jdk.vm.ci.meta.ResolvedJavaField;
427import jdk.vm.ci.meta.ResolvedJavaMethod;
428import jdk.vm.ci.meta.ResolvedJavaType;
429import jdk.vm.ci.meta.TriState;
430
431/**
432 * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
433 */
434public 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                intrinsicGuard.lastInstr.setNext(null);
1742                GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
1743                lastInstr = intrinsicGuard.lastInstr;
1744                args[0] = intrinsicGuard.receiver;
1745            }
1746        }
1747    }
1748
1749    protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
1750        InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
1751        if (plugin != null) {
1752
1753            if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
1754                // Self recursive intrinsic means the original
1755                // method should be called.
1756                assert !targetMethod.hasBytecodes() : "TODO: when does this happen?";
1757                return false;
1758            }
1759
1760            InvocationPluginReceiver pluginReceiver = invocationPluginReceiver.init(targetMethod, args);
1761
1762            IntrinsicGuard intrinsicGuard = null;
1763            if (invokeKind.isIndirect()) {
1764                intrinsicGuard = guardIntrinsic(args, targetMethod, pluginReceiver);
1765                if (intrinsicGuard == null) {
1766                    return false;
1767                } else if (intrinsicGuard.nonIntrinsicBranch == null) {
1768                    assert lastInstr instanceof FixedGuardNode;
1769                }
1770            }
1771
1772            InvocationPluginAssertions assertions = assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
1773            if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
1774                afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
1775                return true;
1776            } else {
1777                afterInvocationPluginExecution(false, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
1778            }
1779        }
1780        return false;
1781    }
1782
1783    private boolean tryNodePluginForInvocation(ValueNode[] args, ResolvedJavaMethod targetMethod) {
1784        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
1785            if (plugin.handleInvoke(this, targetMethod, args)) {
1786                return true;
1787            }
1788        }
1789        return false;
1790    }
1791
1792    private static final InlineInfo SUCCESSFULLY_INLINED = InlineInfo.createStandardInlineInfo(null);
1793
1794    /**
1795     * Try to inline a method. If the method was inlined, returns {@link #SUCCESSFULLY_INLINED}.
1796     * Otherwise, it returns the {@link InlineInfo} that lead to the decision to not inline it, or
1797     * {@code null} if there is no {@link InlineInfo} for this method.
1798     */
1799    private InlineInfo tryInline(ValueNode[] args, ResolvedJavaMethod targetMethod) {
1800        boolean canBeInlined = forceInliningEverything || parsingIntrinsic() || targetMethod.canBeInlined();
1801        if (!canBeInlined) {
1802            return null;
1803        }
1804
1805        if (forceInliningEverything) {
1806            if (inline(targetMethod, targetMethod, null, args)) {
1807                return SUCCESSFULLY_INLINED;
1808            } else {
1809                return null;
1810            }
1811        }
1812
1813        for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
1814            InlineInfo inlineInfo = plugin.shouldInlineInvoke(this, targetMethod, args);
1815            if (inlineInfo != null) {
1816                if (inlineInfo.getMethodToInline() != null) {
1817                    if (inline(targetMethod, inlineInfo.getMethodToInline(), inlineInfo.getIntrinsicBytecodeProvider(), args)) {
1818                        return SUCCESSFULLY_INLINED;
1819                    }
1820                }
1821                /* Do not inline, and do not ask the remaining plugins. */
1822                return inlineInfo;
1823            }
1824        }
1825        return null;
1826    }
1827
1828    @Override
1829    public boolean intrinsify(BytecodeProvider intrinsicBytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) {
1830        if (receiver != null) {
1831            receiver.get();
1832        }
1833        boolean res = inline(targetMethod, substitute, intrinsicBytecodeProvider, args);
1834        assert res : "failed to inline " + substitute;
1835        return res;
1836    }
1837
1838    private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) {
1839        if (TraceInlineDuringParsing.getValue() || TraceParserPlugins.getValue()) {
1840            if (targetMethod.equals(inlinedMethod)) {
1841                traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)"));
1842            } else {
1843                traceWithContext("inlining call to %s as intrinsic for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)"));
1844            }
1845        }
1846        IntrinsicContext intrinsic = this.intrinsicContext;
1847        if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
1848            if (intrinsic.isCompilationRoot()) {
1849                // A root compiled intrinsic needs to deoptimize
1850                // if the slow path is taken. During frame state
1851                // assignment, the deopt node will get its stateBefore
1852                // from the start node of the intrinsic
1853                append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
1854                printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
1855                return true;
1856            } else {
1857                // Otherwise inline the original method. Any frame state created
1858                // during the inlining will exclude frame(s) in the
1859                // intrinsic method (see HIRFrameStateBuilder.create(int bci)).
1860                if (intrinsic.getOriginalMethod().isNative()) {
1861                    printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
1862                    return false;
1863                }
1864                printInlining(targetMethod, inlinedMethod, true, "inline intrinsic (bytecode parsing)");
1865                parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
1866                return true;
1867            }
1868        } else {
1869            boolean isIntrinsic = intrinsicBytecodeProvider != null;
1870            if (intrinsic == null && isIntrinsic) {
1871                assert !inlinedMethod.equals(targetMethod);
1872                intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING);
1873            }
1874            if (inlinedMethod.hasBytecodes()) {
1875                for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
1876                    plugin.notifyBeforeInline(inlinedMethod);
1877                }
1878                printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)");
1879                parseAndInlineCallee(inlinedMethod, args, intrinsic);
1880                for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
1881                    plugin.notifyAfterInline(inlinedMethod);
1882                }
1883            } else {
1884                printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)");
1885                return false;
1886            }
1887        }
1888        return true;
1889    }
1890
1891    private void printInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, boolean success, String msg) {
1892        if (GraalOptions.HotSpotPrintInlining.getValue()) {
1893            if (targetMethod.equals(inlinedMethod)) {
1894                Util.printInlining(inlinedMethod, bci(), getDepth(), success, "%s", msg);
1895            } else {
1896                Util.printInlining(inlinedMethod, bci(), getDepth(), success, "%s intrinsic for %s", msg, targetMethod.format("%h.%n(%p)"));
1897            }
1898        }
1899    }
1900
1901    /**
1902     * Prints a line to {@link TTY} with a prefix indicating the current parse context. The prefix
1903     * is of the form:
1904     *
1905     * <pre>
1906     * {SPACE * n} {name of method being parsed} "(" {file name} ":" {line number} ")"
1907     * </pre>
1908     *
1909     * where {@code n} is the current inlining depth.
1910     *
1911     * @param format a format string
1912     * @param args arguments to the format string
1913     */
1914
1915    protected void traceWithContext(String format, Object... args) {
1916        StackTraceElement where = code.asStackTraceElement(bci());
1917        TTY.println(format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(),
1918                        format(format, args)));
1919    }
1920
1921    protected BytecodeParserError asParserError(Throwable e) {
1922        if (e instanceof BytecodeParserError) {
1923            return (BytecodeParserError) e;
1924        }
1925        BytecodeParser bp = this;
1926        BytecodeParserError res = new BytecodeParserError(e);
1927        while (bp != null) {
1928            res.addContext("parsing " + bp.code.asStackTraceElement(bp.bci()));
1929            bp = bp.parent;
1930        }
1931        return res;
1932    }
1933
1934    @SuppressWarnings("try")
1935    protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) {
1936        try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) {
1937
1938            BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
1939            FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph);
1940            if (!targetMethod.isStatic()) {
1941                args[0] = nullCheckedValue(args[0]);
1942            }
1943            startFrameState.initializeFromArgumentsArray(args);
1944            parser.build(this.lastInstr, startFrameState);
1945
1946            FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode();
1947            this.lastInstr = calleeBeforeReturnNode;
1948            JavaKind calleeReturnKind = targetMethod.getSignature().getReturnKind();
1949            if (calleeBeforeReturnNode != null) {
1950                ValueNode calleeReturnValue = parser.getReturnValue();
1951                if (calleeReturnValue != null) {
1952                    frameState.push(calleeReturnKind.getStackKind(), calleeReturnValue);
1953                }
1954            }
1955
1956            FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
1957            if (calleeBeforeUnwindNode != null) {
1958                ValueNode calleeUnwindValue = parser.getUnwindValue();
1959                assert calleeUnwindValue != null;
1960                calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
1961            }
1962        }
1963    }
1964
1965    public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) {
1966        return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, profile);
1967    }
1968
1969    protected InvokeNode createInvoke(CallTargetNode callTarget, JavaKind resultType) {
1970        InvokeNode invoke = append(new InvokeNode(callTarget, bci()));
1971        frameState.pushReturn(resultType, invoke);
1972        invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
1973        return invoke;
1974    }
1975
1976    protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, JavaKind resultType) {
1977        if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
1978            /*
1979             * Clear non-live locals early so that the exception handler entry gets the cleared
1980             * state.
1981             */
1982            frameState.clearNonLiveLocals(currentBlock, liveness, false);
1983        }
1984
1985        AbstractBeginNode exceptionEdge = handleException(null, bci());
1986        InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci()));
1987        frameState.pushReturn(resultType, invoke);
1988        invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
1989        return invoke;
1990    }
1991
1992    protected void genReturn(ValueNode returnVal, JavaKind returnKind) {
1993        if (parsingIntrinsic() && returnVal != null) {
1994            if (returnVal instanceof StateSplit) {
1995                StateSplit stateSplit = (StateSplit) returnVal;
1996                FrameState stateAfter = stateSplit.stateAfter();
1997                if (stateSplit.hasSideEffect()) {
1998                    assert stateSplit != null;
1999                    if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
2000                        assert stateAfter.usages().count() == 1;
2001                        assert stateAfter.usages().first() == stateSplit;
2002                        stateAfter.replaceAtUsages(graph.add(new FrameState(BytecodeFrame.AFTER_BCI, returnVal)));
2003                        GraphUtil.killWithUnusedFloatingInputs(stateAfter);
2004                    } else {
2005                        /*
2006                         * This must be the return value from within a partial intrinsification.
2007                         */
2008                        assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci);
2009                    }
2010                } else {
2011                    assert stateAfter == null;
2012                }
2013            }
2014        }
2015        if (parent == null) {
2016            frameState.setRethrowException(false);
2017            frameState.clearStack();
2018            beforeReturn(returnVal, returnKind);
2019            append(new ReturnNode(returnVal));
2020        } else {
2021            if (blockMap.getReturnCount() == 1 || !controlFlowSplit) {
2022                // There is only a single return.
2023                beforeReturn(returnVal, returnKind);
2024                this.returnValue = returnVal;
2025                this.beforeReturnNode = this.lastInstr;
2026                this.lastInstr = null;
2027            } else {
2028                frameState.setRethrowException(false);
2029                frameState.clearStack();
2030                if (returnVal != null) {
2031                    frameState.push(returnKind, returnVal);
2032                }
2033                assert blockMap.getReturnCount() > 1;
2034                appendGoto(blockMap.getReturnBlock());
2035            }
2036        }
2037    }
2038
2039    private void beforeReturn(ValueNode x, JavaKind kind) {
2040        if (graph.method() != null && graph.method().isJavaLangObjectInit()) {
2041            /*
2042             * Get the receiver from the initial state since bytecode rewriting could do arbitrary
2043             * things to the state of the locals.
2044             */
2045            ValueNode receiver = graph.start().stateAfter().localAt(0);
2046            assert receiver != null && receiver.getStackKind() == JavaKind.Object;
2047            if (RegisterFinalizerNode.mayHaveFinalizer(receiver, graph.getAssumptions())) {
2048                append(new RegisterFinalizerNode(receiver));
2049            }
2050        }
2051        genInfoPointNode(InfopointReason.METHOD_END, x);
2052        if (finalBarrierRequired) {
2053            assert originalReceiver != null;
2054            append(new FinalFieldBarrierNode(originalReceiver));
2055        }
2056        synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x, kind);
2057    }
2058
2059    protected MonitorEnterNode createMonitorEnterNode(ValueNode x, MonitorIdNode monitorId) {
2060        return new MonitorEnterNode(x, monitorId);
2061    }
2062
2063    protected void genMonitorEnter(ValueNode x, int bci) {
2064        MonitorIdNode monitorId = graph.add(new MonitorIdNode(frameState.lockDepth(true)));
2065        MonitorEnterNode monitorEnter = append(createMonitorEnterNode(x, monitorId));
2066        frameState.pushLock(x, monitorId);
2067        monitorEnter.setStateAfter(createFrameState(bci, monitorEnter));
2068    }
2069
2070    protected void genMonitorExit(ValueNode x, ValueNode escapedReturnValue, int bci) {
2071        if (frameState.lockDepth(false) == 0) {
2072            throw bailout("unbalanced monitors: too many exits");
2073        }
2074        MonitorIdNode monitorId = frameState.peekMonitorId();
2075        ValueNode lockedObject = frameState.popLock();
2076        if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) {
2077            throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)));
2078        }
2079        MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, escapedReturnValue));
2080        monitorExit.setStateAfter(createFrameState(bci, monitorExit));
2081    }
2082
2083    protected void genJsr(int dest) {
2084        BciBlock successor = currentBlock.getJsrSuccessor();
2085        assert successor.startBci == dest : successor.startBci + " != " + dest + " @" + bci();
2086        JsrScope scope = currentBlock.getJsrScope();
2087        int nextBci = getStream().nextBCI();
2088        if (!successor.getJsrScope().pop().equals(scope)) {
2089            throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)");
2090        }
2091        if (successor.getJsrScope().nextReturnAddress() != nextBci) {
2092            throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)");
2093        }
2094        ConstantNode nextBciNode = getJsrConstant(nextBci);
2095        frameState.push(JavaKind.Object, nextBciNode);
2096        appendGoto(successor);
2097    }
2098
2099    protected void genRet(int localIndex) {
2100        BciBlock successor = currentBlock.getRetSuccessor();
2101        ValueNode local = frameState.loadLocal(localIndex, JavaKind.Object);
2102        JsrScope scope = currentBlock.getJsrScope();
2103        int retAddress = scope.nextReturnAddress();
2104        ConstantNode returnBciNode = getJsrConstant(retAddress);
2105        LogicNode guard = IntegerEqualsNode.create(local, returnBciNode, constantReflection);
2106        guard = graph.unique(guard);
2107        append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile));
2108        if (!successor.getJsrScope().equals(scope.pop())) {
2109            throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
2110        }
2111        appendGoto(successor);
2112    }
2113
2114    private ConstantNode getJsrConstant(long bci) {
2115        JavaConstant nextBciConstant = new RawConstant(bci);
2116        Stamp nextBciStamp = StampFactory.forConstant(nextBciConstant);
2117        ConstantNode nextBciNode = new ConstantNode(nextBciConstant, nextBciStamp);
2118        return graph.unique(nextBciNode);
2119    }
2120
2121    protected void genIntegerSwitch(ValueNode value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
2122        if (value.isConstant()) {
2123            JavaConstant constant = (JavaConstant) value.asConstant();
2124            int constantValue = constant.asInt();
2125            for (int i = 0; i < keys.length; ++i) {
2126                if (keys[i] == constantValue) {
2127                    appendGoto(actualSuccessors.get(keySuccessors[i]));
2128                    return;
2129                }
2130            }
2131            appendGoto(actualSuccessors.get(keySuccessors[keys.length]));
2132        } else {
2133            this.controlFlowSplit = true;
2134            double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities);
2135            IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors));
2136            for (int i = 0; i < actualSuccessors.size(); i++) {
2137                switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState));
2138            }
2139        }
2140    }
2141
2142    /**
2143     * Helper function that sums up the probabilities of all keys that lead to a specific successor.
2144     *
2145     * @return an array of size successorCount with the accumulated probability for each successor.
2146     */
2147    private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
2148        double[] probability = new double[successorCount];
2149        for (int i = 0; i < keySuccessors.length; i++) {
2150            probability[keySuccessors[i]] += keyProbabilities[i];
2151        }
2152        return probability;
2153    }
2154
2155    protected ConstantNode appendConstant(JavaConstant constant) {
2156        assert constant != null;
2157        return ConstantNode.forConstant(constant, metaAccess, graph);
2158    }
2159
2160    @Override
2161    public <T extends ValueNode> T append(T v) {
2162        if (v.graph() != null) {
2163            return v;
2164        }
2165        T added = graph.addOrUnique(v);
2166        if (added == v) {
2167            updateLastInstruction(v);
2168        }
2169        return added;
2170    }
2171
2172    @Override
2173    public <T extends ValueNode> T recursiveAppend(T v) {
2174        if (v.graph() != null) {
2175            return v;
2176        }
2177        T added = graph.addOrUniqueWithInputs(v);
2178        if (added == v) {
2179            updateLastInstruction(v);
2180        }
2181        return added;
2182    }
2183
2184    private <T extends ValueNode> void updateLastInstruction(T v) {
2185        if (UseGraalInstrumentation.getValue()) {
2186            // resolve instrumentation target
2187            if (v instanceof InstrumentationBeginNode) {
2188                InstrumentationBeginNode begin = (InstrumentationBeginNode) v;
2189                if (!begin.isAnchored() && lastBCI != -1) {
2190                    int currentBCI = stream.currentBCI();
2191                    // temporarily set the bytecode stream to lastBCI
2192                    stream.setBCI(lastBCI);
2193                    // The instrumentation should be associated with the predecessor. In case of the
2194                    // predecessor being optimized away, e.g., inlining, we should not set the
2195                    // target.
2196                    if (stream.nextBCI() == currentBCI) {
2197                        begin.setTarget(lastInstr);
2198                    }
2199                    // restore the current BCI
2200                    stream.setBCI(currentBCI);
2201                }
2202            }
2203        }
2204        if (v instanceof FixedNode) {
2205            FixedNode fixedNode = (FixedNode) v;
2206            lastInstr.setNext(fixedNode);
2207            if (fixedNode instanceof FixedWithNextNode) {
2208                FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode;
2209                assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end";
2210                lastInstr = fixedWithNextNode;
2211                lastBCI = stream.currentBCI();
2212            } else {
2213                lastInstr = null;
2214                lastBCI = -1;
2215            }
2216        }
2217    }
2218
2219    private Target checkLoopExit(FixedNode target, BciBlock targetBlock, FrameStateBuilder state) {
2220        if (currentBlock != null) {
2221            long exits = currentBlock.loops & ~targetBlock.loops;
2222            if (exits != 0) {
2223                LoopExitNode firstLoopExit = null;
2224                LoopExitNode lastLoopExit = null;
2225
2226                int pos = 0;
2227                ArrayList<BciBlock> exitLoops = new ArrayList<>(Long.bitCount(exits));
2228                do {
2229                    long lMask = 1L << pos;
2230                    if ((exits & lMask) != 0) {
2231                        exitLoops.add(blockMap.getLoopHeader(pos));
2232                        exits &= ~lMask;
2233                    }
2234                    pos++;
2235                } while (exits != 0);
2236
2237                Collections.sort(exitLoops, new Comparator<BciBlock>() {
2238
2239                    @Override
2240                    public int compare(BciBlock o1, BciBlock o2) {
2241                        return Long.bitCount(o2.loops) - Long.bitCount(o1.loops);
2242                    }
2243                });
2244
2245                int bci = targetBlock.startBci;
2246                if (targetBlock instanceof ExceptionDispatchBlock) {
2247                    bci = ((ExceptionDispatchBlock) targetBlock).deoptBci;
2248                }
2249                FrameStateBuilder newState = state.copy();
2250                for (BciBlock loop : exitLoops) {
2251                    LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(loop);
2252                    LoopExitNode loopExit = graph.add(new LoopExitNode(loopBegin));
2253                    if (lastLoopExit != null) {
2254                        lastLoopExit.setNext(loopExit);
2255                    }
2256                    if (firstLoopExit == null) {
2257                        firstLoopExit = loopExit;
2258                    }
2259                    lastLoopExit = loopExit;
2260                    Debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop);
2261                    newState.clearNonLiveLocals(targetBlock, liveness, true);
2262                    newState.insertLoopProxies(loopExit, getEntryState(loop));
2263                    loopExit.setStateAfter(newState.create(bci, loopExit));
2264                }
2265
2266                lastLoopExit.setNext(target);
2267                return new Target(firstLoopExit, newState);
2268            }
2269        }
2270        return new Target(target, state);
2271    }
2272
2273    private FrameStateBuilder getEntryState(BciBlock block) {
2274        return entryStateArray[block.id];
2275    }
2276
2277    private void setEntryState(BciBlock block, FrameStateBuilder entryState) {
2278        this.entryStateArray[block.id] = entryState;
2279    }
2280
2281    private void setFirstInstruction(BciBlock block, FixedWithNextNode firstInstruction) {
2282        this.firstInstructionArray[block.id] = firstInstruction;
2283    }
2284
2285    private FixedWithNextNode getFirstInstruction(BciBlock block) {
2286        return firstInstructionArray[block.id];
2287    }
2288
2289    private FixedNode createTarget(double probability, BciBlock block, FrameStateBuilder stateAfter) {
2290        assert probability >= 0 && probability <= 1.01 : probability;
2291        if (isNeverExecutedCode(probability)) {
2292            return graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
2293        } else {
2294            assert block != null;
2295            return createTarget(block, stateAfter);
2296        }
2297    }
2298
2299    private FixedNode createTarget(BciBlock block, FrameStateBuilder state) {
2300        return createTarget(block, state, false, false);
2301    }
2302
2303    private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
2304        assert block != null && state != null;
2305        assert !block.isExceptionEntry || state.stackSize() == 1;
2306
2307        if (getFirstInstruction(block) == null) {
2308            /*
2309             * This is the first time we see this block as a branch target. Create and return a
2310             * placeholder that later can be replaced with a MergeNode when we see this block again.
2311             */
2312            FixedNode targetNode;
2313            if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
2314                setFirstInstruction(block, lastInstr);
2315                lastInstr = null;
2316            } else {
2317                setFirstInstruction(block, graph.add(new BeginNode()));
2318            }
2319            targetNode = getFirstInstruction(block);
2320            Target target = checkLoopExit(targetNode, block, state);
2321            FixedNode result = target.fixed;
2322            FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
2323            setEntryState(block, currentEntryState);
2324            currentEntryState.clearNonLiveLocals(block, liveness, true);
2325
2326            Debug.log("createTarget %s: first visit, result: %s", block, targetNode);
2327            return result;
2328        }
2329
2330        // We already saw this block before, so we have to merge states.
2331        if (!getEntryState(block).isCompatibleWith(state)) {
2332            throw bailout("stacks do not match; bytecodes would not verify");
2333        }
2334
2335        if (getFirstInstruction(block) instanceof LoopBeginNode) {
2336            assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
2337            /*
2338             * Backward loop edge. We need to create a special LoopEndNode and merge with the loop
2339             * begin node created before.
2340             */
2341            LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block);
2342            LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
2343            Target target = checkLoopExit(loopEnd, block, state);
2344            FixedNode result = target.fixed;
2345            getEntryState(block).merge(loopBegin, target.state);
2346
2347            Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
2348            return result;
2349        }
2350        assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
2351        assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
2352
2353        if (getFirstInstruction(block) instanceof AbstractBeginNode && !(getFirstInstruction(block) instanceof AbstractMergeNode)) {
2354            /*
2355             * This is the second time we see this block. Create the actual MergeNode and the End
2356             * Node for the already existing edge.
2357             */
2358            AbstractBeginNode beginNode = (AbstractBeginNode) getFirstInstruction(block);
2359
2360            // The EndNode for the already existing edge.
2361            EndNode end = graph.add(new EndNode());
2362            // The MergeNode that replaces the placeholder.
2363            AbstractMergeNode mergeNode = graph.add(new MergeNode());
2364            FixedNode next = beginNode.next();
2365
2366            if (beginNode.predecessor() instanceof ControlSplitNode) {
2367                beginNode.setNext(end);
2368            } else {
2369                beginNode.replaceAtPredecessor(end);
2370                beginNode.safeDelete();
2371            }
2372
2373            mergeNode.addForwardEnd(end);
2374            mergeNode.setNext(next);
2375
2376            setFirstInstruction(block, mergeNode);
2377        }
2378
2379        AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block);
2380
2381        // The EndNode for the newly merged edge.
2382        EndNode newEnd = graph.add(new EndNode());
2383        Target target = checkLoopExit(newEnd, block, state);
2384        FixedNode result = target.fixed;
2385        getEntryState(block).merge(mergeNode, target.state);
2386        mergeNode.addForwardEnd(newEnd);
2387
2388        Debug.log("createTarget %s: merging state, result: %s", block, result);
2389        return result;
2390    }
2391
2392    /**
2393     * Returns a block begin node with the specified state. If the specified probability is 0, the
2394     * block deoptimizes immediately.
2395     */
2396    private AbstractBeginNode createBlockTarget(double probability, BciBlock block, FrameStateBuilder stateAfter) {
2397        FixedNode target = createTarget(probability, block, stateAfter);
2398        AbstractBeginNode begin = BeginNode.begin(target);
2399
2400        assert !(target instanceof DeoptimizeNode && begin instanceof BeginStateSplitNode &&
2401                        ((BeginStateSplitNode) begin).stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node," +
2402                                        " because we have to deoptimize to a bci _before_ the actual if, so that the interpreter can update the profiling information.";
2403        return begin;
2404    }
2405
2406    private ValueNode synchronizedObject(FrameStateBuilder state, ResolvedJavaMethod target) {
2407        if (target.isStatic()) {
2408            return appendConstant(getConstantReflection().asJavaClass(target.getDeclaringClass()));
2409        } else {
2410            return state.loadLocal(0, JavaKind.Object);
2411        }
2412    }
2413
2414    @SuppressWarnings("try")
2415    protected void processBlock(BciBlock block) {
2416        // Ignore blocks that have no predecessors by the time their bytecodes are parsed
2417        FixedWithNextNode firstInstruction = getFirstInstruction(block);
2418        if (firstInstruction == null) {
2419            Debug.log("Ignoring block %s", block);
2420            return;
2421        }
2422        try (Indent indent = Debug.logAndIndent("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, firstInstruction, block.isLoopHeader)) {
2423
2424            lastInstr = firstInstruction;
2425            frameState = getEntryState(block);
2426            setCurrentFrameState(frameState);
2427            currentBlock = block;
2428
2429            if (firstInstruction instanceof AbstractMergeNode) {
2430                setMergeStateAfter(block, firstInstruction);
2431            }
2432
2433            if (block == blockMap.getReturnBlock()) {
2434                handleReturnBlock();
2435            } else if (block == blockMap.getUnwindBlock()) {
2436                handleUnwindBlock();
2437            } else if (block instanceof ExceptionDispatchBlock) {
2438                createExceptionDispatch((ExceptionDispatchBlock) block);
2439            } else {
2440                frameState.setRethrowException(false);
2441                iterateBytecodesForBlock(block);
2442            }
2443        }
2444    }
2445
2446    private void handleUnwindBlock() {
2447        if (parent == null) {
2448            frameState.setRethrowException(false);
2449            createUnwind();
2450        } else {
2451            ValueNode exception = frameState.pop(JavaKind.Object);
2452            this.unwindValue = exception;
2453            this.beforeUnwindNode = this.lastInstr;
2454        }
2455    }
2456
2457    private void handleReturnBlock() {
2458        JavaKind returnKind = method.getSignature().getReturnKind().getStackKind();
2459        ValueNode x = returnKind == JavaKind.Void ? null : frameState.pop(returnKind);
2460        assert frameState.stackSize() == 0;
2461        beforeReturn(x, returnKind);
2462        this.returnValue = x;
2463        this.beforeReturnNode = this.lastInstr;
2464    }
2465
2466    private void setMergeStateAfter(BciBlock block, FixedWithNextNode firstInstruction) {
2467        AbstractMergeNode abstractMergeNode = (AbstractMergeNode) firstInstruction;
2468        if (abstractMergeNode.stateAfter() == null) {
2469            int bci = block.startBci;
2470            if (block instanceof ExceptionDispatchBlock) {
2471                bci = ((ExceptionDispatchBlock) block).deoptBci;
2472            }
2473            abstractMergeNode.setStateAfter(createFrameState(bci, abstractMergeNode));
2474        }
2475    }
2476
2477    private void createUnwind() {
2478        assert frameState.stackSize() == 1 : frameState;
2479        ValueNode exception = frameState.pop(JavaKind.Object);
2480        synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null);
2481        append(new UnwindNode(exception));
2482    }
2483
2484    private void synchronizedEpilogue(int bci, ValueNode currentReturnValue, JavaKind currentReturnValueKind) {
2485        if (method.isSynchronized()) {
2486            if (currentReturnValue != null) {
2487                frameState.push(currentReturnValueKind, currentReturnValue);
2488            }
2489            genMonitorExit(methodSynchronizedObject, currentReturnValue, bci);
2490            assert !frameState.rethrowException();
2491        }
2492        if (frameState.lockDepth(false) != 0) {
2493            throw bailout("unbalanced monitors: too few exits exiting frame");
2494        }
2495    }
2496
2497    private void createExceptionDispatch(ExceptionDispatchBlock block) {
2498        assert frameState.stackSize() == 1 : frameState;
2499        if (block.handler.isCatchAll()) {
2500            assert block.getSuccessorCount() == 1;
2501            appendGoto(block.getSuccessor(0));
2502            return;
2503        }
2504
2505        JavaType catchType = block.handler.getCatchType();
2506        if (graphBuilderConfig.eagerResolving()) {
2507            catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF);
2508        }
2509        if (catchType instanceof ResolvedJavaType) {
2510            TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType);
2511
2512            if (graphBuilderConfig.getSkippedExceptionTypes() != null) {
2513                for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
2514                    if (skippedType.isAssignableFrom(checkedCatchType.getType())) {
2515                        BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
2516                        ValueNode exception = frameState.stack[0];
2517                        FixedNode trueSuccessor = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
2518                        FixedNode nextDispatch = createTarget(nextBlock, frameState);
2519                        append(new IfNode(graph.addOrUniqueWithInputs(createInstanceOf(checkedCatchType, exception)), trueSuccessor, nextDispatch, 0));
2520                        return;
2521                    }
2522                }
2523            }
2524
2525            BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
2526            ValueNode exception = frameState.stack[0];
2527            /* Anchor for the piNode, which must be before any LoopExit inserted by createTarget. */
2528            BeginNode piNodeAnchor = graph.add(new BeginNode());
2529            ObjectStamp checkedStamp = StampFactory.objectNonNull(checkedCatchType);
2530            PiNode piNode = graph.addWithoutUnique(new PiNode(exception, checkedStamp));
2531            frameState.pop(JavaKind.Object);
2532            frameState.push(JavaKind.Object, piNode);
2533            FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState);
2534            frameState.pop(JavaKind.Object);
2535            frameState.push(JavaKind.Object, exception);
2536            FixedNode nextDispatch = createTarget(nextBlock, frameState);
2537            piNodeAnchor.setNext(catchSuccessor);
2538            IfNode ifNode = append(new IfNode(graph.unique(createInstanceOf(checkedCatchType, exception)), piNodeAnchor, nextDispatch, 0.5));
2539            assert ifNode.trueSuccessor() == piNodeAnchor;
2540            piNode.setGuard(ifNode.trueSuccessor());
2541        } else {
2542            handleUnresolvedExceptionType(catchType);
2543        }
2544    }
2545
2546    private void appendGoto(BciBlock successor) {
2547        FixedNode targetInstr = createTarget(successor, frameState, true, true);
2548        if (lastInstr != null && lastInstr != targetInstr) {
2549            lastInstr.setNext(targetInstr);
2550        }
2551    }
2552
2553    @SuppressWarnings("try")
2554    protected void iterateBytecodesForBlock(BciBlock block) {
2555        if (block.isLoopHeader) {
2556            // Create the loop header block, which later will merge the backward branches of
2557            // the loop.
2558            controlFlowSplit = true;
2559            LoopBeginNode loopBegin = appendLoopBegin(this.lastInstr);
2560            lastInstr = loopBegin;
2561
2562            // Create phi functions for all local variables and operand stack slots.
2563            frameState.insertLoopPhis(liveness, block.loopId, loopBegin, forceLoopPhis(), stampFromValueForForcedPhis());
2564            loopBegin.setStateAfter(createFrameState(block.startBci, loopBegin));
2565
2566            /*
2567             * We have seen all forward branches. All subsequent backward branches will merge to the
2568             * loop header. This ensures that the loop header has exactly one non-loop predecessor.
2569             */
2570            setFirstInstruction(block, loopBegin);
2571            /*
2572             * We need to preserve the frame state builder of the loop header so that we can merge
2573             * values for phi functions, so make a copy of it.
2574             */
2575            setEntryState(block, frameState.copy());
2576
2577            Debug.log("  created loop header %s", loopBegin);
2578        } else if (lastInstr instanceof MergeNode) {
2579            /*
2580             * All inputs of non-loop phi nodes are known by now. We can infer the stamp for the
2581             * phi, so that parsing continues with more precise type information.
2582             */
2583            frameState.inferPhiStamps((AbstractMergeNode) lastInstr);
2584        }
2585        assert lastInstr.next() == null : "instructions already appended at block " + block;
2586        Debug.log("  frameState: %s", frameState);
2587
2588        lastInstr = finishInstruction(lastInstr, frameState);
2589
2590        int endBCI = stream.endBCI();
2591
2592        stream.setBCI(block.startBci);
2593        int bci = block.startBci;
2594        BytecodesParsed.add(block.endBci - bci);
2595
2596        /* Reset line number for new block */
2597        if (graphBuilderConfig.insertFullInfopoints()) {
2598            previousLineNumber = -1;
2599        }
2600
2601        while (bci < endBCI) {
2602            if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) {
2603                currentLineNumber = lnt != null ? lnt.getLineNumber(bci) : -1;
2604                if (currentLineNumber != previousLineNumber) {
2605                    genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
2606                    previousLineNumber = currentLineNumber;
2607                }
2608            }
2609
2610            // read the opcode
2611            int opcode = stream.currentBC();
2612            assert traceState();
2613            assert traceInstruction(bci, opcode, bci == block.startBci);
2614            if (parent == null && bci == entryBCI) {
2615                if (block.getJsrScope() != JsrScope.EMPTY_SCOPE) {
2616                    throw new JsrNotSupportedBailout("OSR into a JSR scope is not supported");
2617                }
2618                EntryMarkerNode x = append(new EntryMarkerNode());
2619                frameState.insertProxies(value -> graph.unique(new EntryProxyNode(value, x)));
2620                x.setStateAfter(createFrameState(bci, x));
2621            }
2622
2623            try (DebugCloseable context = openNodeContext()) {
2624                processBytecode(bci, opcode);
2625            } catch (BailoutException e) {
2626                // Don't wrap bailouts as parser errors
2627                throw e;
2628            } catch (Throwable e) {
2629                throw asParserError(e);
2630            }
2631
2632            if (lastInstr == null || lastInstr.next() != null) {
2633                break;
2634            }
2635
2636            stream.next();
2637            bci = stream.currentBCI();
2638
2639            assert block == currentBlock;
2640            assert checkLastInstruction();
2641            lastInstr = finishInstruction(lastInstr, frameState);
2642            if (bci < endBCI) {
2643                if (bci > block.endBci) {
2644                    assert !block.getSuccessor(0).isExceptionEntry;
2645                    assert block.numNormalSuccessors() == 1;
2646                    // we fell through to the next block, add a goto and break
2647                    appendGoto(block.getSuccessor(0));
2648                    break;
2649                }
2650            }
2651        }
2652    }
2653
2654    private DebugCloseable openNodeContext() {
2655        if (graphBuilderConfig.trackNodeSourcePosition() && !parsingIntrinsic()) {
2656            return graph.withNodeSourcePosition(createBytecodePosition());
2657        }
2658        return null;
2659    }
2660
2661    /* Also a hook for subclasses. */
2662    protected boolean forceLoopPhis() {
2663        return graph.isOSR();
2664    }
2665
2666    /* Hook for subclasses. */
2667    protected boolean stampFromValueForForcedPhis() {
2668        return false;
2669    }
2670
2671    protected boolean checkLastInstruction() {
2672        if (lastInstr instanceof BeginNode) {
2673            // ignore
2674        } else if (lastInstr instanceof StateSplit) {
2675            StateSplit stateSplit = (StateSplit) lastInstr;
2676            if (stateSplit.hasSideEffect()) {
2677                assert stateSplit.stateAfter() != null : "side effect " + lastInstr + " requires a non-null stateAfter";
2678            }
2679        }
2680        return true;
2681    }
2682
2683    /* Also a hook for subclasses. */
2684    protected boolean disableLoopSafepoint() {
2685        return parsingIntrinsic();
2686    }
2687
2688    private LoopBeginNode appendLoopBegin(FixedWithNextNode fixedWithNext) {
2689        EndNode preLoopEnd = graph.add(new EndNode());
2690        LoopBeginNode loopBegin = graph.add(new LoopBeginNode());
2691        if (disableLoopSafepoint()) {
2692            loopBegin.disableSafepoint();
2693        }
2694        fixedWithNext.setNext(preLoopEnd);
2695        // Add the single non-loop predecessor of the loop header.
2696        loopBegin.addForwardEnd(preLoopEnd);
2697        return loopBegin;
2698    }
2699
2700    /**
2701     * Hook for subclasses to modify the last instruction or add other instructions.
2702     *
2703     * @param instr The last instruction (= fixed node) which was added.
2704     * @param state The current frame state.
2705     * @return Returns the (new) last instruction.
2706     */
2707    protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, FrameStateBuilder state) {
2708        return instr;
2709    }
2710
2711    private void genInfoPointNode(InfopointReason reason, ValueNode escapedReturnValue) {
2712        if (!parsingIntrinsic() && graphBuilderConfig.insertFullInfopoints()) {
2713            append(new FullInfopointNode(reason, createFrameState(bci(), null), escapedReturnValue));
2714        }
2715    }
2716
2717    private boolean traceState() {
2718        if (Debug.isEnabled() && BytecodeParserOptions.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_STATE && Debug.isLogEnabled()) {
2719            frameState.traceState();
2720        }
2721        return true;
2722    }
2723
2724    protected void genIf(ValueNode x, Condition cond, ValueNode y) {
2725        assert x.getStackKind() == y.getStackKind();
2726        assert currentBlock.getSuccessorCount() == 2;
2727        BciBlock trueBlock = currentBlock.getSuccessor(0);
2728        BciBlock falseBlock = currentBlock.getSuccessor(1);
2729
2730        FrameState stateBefore = null;
2731        ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin();
2732        if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
2733            stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
2734        }
2735
2736        if (trueBlock == falseBlock) {
2737            // The target block is the same independent of the condition.
2738            appendGoto(trueBlock);
2739            return;
2740        }
2741
2742        ValueNode a = x;
2743        ValueNode b = y;
2744
2745        // Check whether the condition needs to mirror the operands.
2746        if (cond.canonicalMirror()) {
2747            a = y;
2748            b = x;
2749        }
2750
2751        // Create the logic node for the condition.
2752        LogicNode condition = createLogicNode(cond, a, b);
2753
2754        // Check whether the condition needs to negate the result.
2755        boolean negate = cond.canonicalNegate();
2756
2757        // Remove a logic negation node and fold it into the negate boolean.
2758        if (condition instanceof LogicNegationNode) {
2759            LogicNegationNode logicNegationNode = (LogicNegationNode) condition;
2760            negate = !negate;
2761            condition = logicNegationNode.getValue();
2762        }
2763
2764        if (condition instanceof LogicConstantNode) {
2765            genConstantTargetIf(trueBlock, falseBlock, negate, condition);
2766        } else {
2767            if (condition.graph() == null) {
2768                condition = graph.unique(condition);
2769            }
2770
2771            // Need to get probability based on current bci.
2772            double probability = branchProbability();
2773
2774            if (negate) {
2775                BciBlock tmpBlock = trueBlock;
2776                trueBlock = falseBlock;
2777                falseBlock = tmpBlock;
2778                probability = 1 - probability;
2779            }
2780
2781            if (isNeverExecutedCode(probability)) {
2782                append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
2783                if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
2784                    profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
2785                }
2786                appendGoto(falseBlock);
2787                return;
2788            } else if (isNeverExecutedCode(1 - probability)) {
2789                append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false));
2790                if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
2791                    profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
2792                }
2793                appendGoto(trueBlock);
2794                return;
2795            }
2796
2797            if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
2798                profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore);
2799            }
2800
2801            int oldBci = stream.currentBCI();
2802            int trueBlockInt = checkPositiveIntConstantPushed(trueBlock);
2803            if (trueBlockInt != -1) {
2804                int falseBlockInt = checkPositiveIntConstantPushed(falseBlock);
2805                if (falseBlockInt != -1) {
2806                    if (tryGenConditionalForIf(trueBlock, falseBlock, condition, oldBci, trueBlockInt, falseBlockInt)) {
2807                        return;
2808                    }
2809                }
2810            }
2811
2812            this.controlFlowSplit = true;
2813            FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false);
2814            FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true);
2815            ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability);
2816            postProcessIfNode(ifNode);
2817            append(ifNode);
2818            if (parsingIntrinsic()) {
2819                if (x instanceof BranchProbabilityNode) {
2820                    ((BranchProbabilityNode) x).simplify(null);
2821                } else if (y instanceof BranchProbabilityNode) {
2822                    ((BranchProbabilityNode) y).simplify(null);
2823                }
2824            }
2825        }
2826    }
2827
2828    /**
2829     * Hook for subclasses to generate custom nodes before an IfNode.
2830     */
2831    @SuppressWarnings("unused")
2832    protected void postProcessIfNode(ValueNode node) {
2833    }
2834
2835    private boolean tryGenConditionalForIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt) {
2836        if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) {
2837            genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, false);
2838            return true;
2839        } else if (this.parent != null && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) {
2840            genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, true);
2841            return true;
2842        }
2843        return false;
2844    }
2845
2846    private void genConditionalForIf(BciBlock trueBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt, boolean genReturn) {
2847        ConstantNode trueValue = graph.unique(ConstantNode.forInt(trueBlockInt));
2848        ConstantNode falseValue = graph.unique(ConstantNode.forInt(falseBlockInt));
2849        ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue);
2850        if (conditionalNode.graph() == null) {
2851            conditionalNode = graph.addOrUnique(conditionalNode);
2852        }
2853        if (genReturn) {
2854            JavaKind returnKind = method.getSignature().getReturnKind().getStackKind();
2855            this.genReturn(conditionalNode, returnKind);
2856        } else {
2857            frameState.push(JavaKind.Int, conditionalNode);
2858            appendGoto(trueBlock.getSuccessor(0));
2859            stream.setBCI(oldBci);
2860        }
2861    }
2862
2863    private LogicNode createLogicNode(Condition cond, ValueNode a, ValueNode b) {
2864        LogicNode condition;
2865        assert !a.getStackKind().isNumericFloat();
2866        if (cond == Condition.EQ || cond == Condition.NE) {
2867            if (a.getStackKind() == JavaKind.Object) {
2868                condition = genObjectEquals(a, b);
2869            } else {
2870                condition = genIntegerEquals(a, b);
2871            }
2872        } else {
2873            assert a.getStackKind() != JavaKind.Object && !cond.isUnsigned();
2874            condition = genIntegerLessThan(a, b);
2875        }
2876        return condition;
2877    }
2878
2879    private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, boolean negate, LogicNode condition) {
2880        LogicConstantNode constantLogicNode = (LogicConstantNode) condition;
2881        boolean value = constantLogicNode.getValue();
2882        if (negate) {
2883            value = !value;
2884        }
2885        BciBlock nextBlock = falseBlock;
2886        if (value) {
2887            nextBlock = trueBlock;
2888        }
2889        int startBci = nextBlock.startBci;
2890        int targetAtStart = stream.readUByte(startBci);
2891        if (targetAtStart == Bytecodes.GOTO && nextBlock.getPredecessorCount() == 1) {
2892            // This is an empty block. Skip it.
2893            BciBlock successorBlock = nextBlock.successors.get(0);
2894            ProfilingPlugin profilingPlugin = graphBuilderConfig.getPlugins().getProfilingPlugin();
2895            if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
2896                FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
2897                profilingPlugin.profileGoto(this, method, bci(), successorBlock.startBci, stateBefore);
2898            }
2899            appendGoto(successorBlock);
2900            assert nextBlock.numNormalSuccessors() == 1;
2901        } else {
2902            ProfilingPlugin profilingPlugin = graphBuilderConfig.getPlugins().getProfilingPlugin();
2903            if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
2904                FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
2905                profilingPlugin.profileGoto(this, method, bci(), nextBlock.startBci, stateBefore);
2906            }
2907            appendGoto(nextBlock);
2908        }
2909    }
2910
2911    private int checkPositiveIntConstantPushed(BciBlock block) {
2912        stream.setBCI(block.startBci);
2913        int currentBC = stream.currentBC();
2914        if (currentBC >= Bytecodes.ICONST_0 && currentBC <= Bytecodes.ICONST_5) {
2915            int constValue = currentBC - Bytecodes.ICONST_0;
2916            return constValue;
2917        }
2918        return -1;
2919    }
2920
2921    private boolean gotoOrFallThroughAfterConstant(BciBlock block) {
2922        stream.setBCI(block.startBci);
2923        int currentBCI = stream.nextBCI();
2924        stream.setBCI(currentBCI);
2925        int currentBC = stream.currentBC();
2926        return stream.currentBCI() > block.endBci || currentBC == Bytecodes.GOTO || currentBC == Bytecodes.GOTO_W;
2927    }
2928
2929    private boolean returnAfterConstant(BciBlock block) {
2930        stream.setBCI(block.startBci);
2931        int currentBCI = stream.nextBCI();
2932        stream.setBCI(currentBCI);
2933        int currentBC = stream.currentBC();
2934        return currentBC == Bytecodes.IRETURN;
2935    }
2936
2937    @Override
2938    public StampProvider getStampProvider() {
2939        return stampProvider;
2940    }
2941
2942    @Override
2943    public MetaAccessProvider getMetaAccess() {
2944        return metaAccess;
2945    }
2946
2947    @Override
2948    public void push(JavaKind slotKind, ValueNode value) {
2949        assert value.isAlive();
2950        frameState.push(slotKind, value);
2951    }
2952
2953    @Override
2954    public ConstantReflectionProvider getConstantReflection() {
2955        return constantReflection;
2956    }
2957
2958    @Override
2959    public ConstantFieldProvider getConstantFieldProvider() {
2960        return constantFieldProvider;
2961    }
2962
2963    /**
2964     * Gets the graph being processed by this builder.
2965     */
2966    @Override
2967    public StructuredGraph getGraph() {
2968        return graph;
2969    }
2970
2971    @Override
2972    public BytecodeParser getParent() {
2973        return parent;
2974    }
2975
2976    @Override
2977    public IntrinsicContext getIntrinsic() {
2978        return intrinsicContext;
2979    }
2980
2981    @Override
2982    public String toString() {
2983        Formatter fmt = new Formatter();
2984        BytecodeParser bp = this;
2985        String indent = "";
2986        while (bp != null) {
2987            if (bp != this) {
2988                fmt.format("%n%s", indent);
2989            }
2990            fmt.format("%s [bci: %d, intrinsic: %s]", bp.code.asStackTraceElement(bp.bci()), bp.bci(), bp.parsingIntrinsic());
2991            fmt.format("%n%s", new BytecodeDisassembler().disassemble(bp.code, bp.bci(), bp.bci() + 10));
2992            bp = bp.parent;
2993            indent += " ";
2994        }
2995        return fmt.toString();
2996    }
2997
2998    @Override
2999    public BailoutException bailout(String string) {
3000        FrameState currentFrameState = createFrameState(bci(), null);
3001        StackTraceElement[] elements = GraphUtil.approxSourceStackTraceElement(currentFrameState);
3002        BailoutException bailout = new PermanentBailoutException(string);
3003        throw GraphUtil.createBailoutException(string, bailout, elements);
3004    }
3005
3006    private FrameState createFrameState(int bci, StateSplit forStateSplit) {
3007        if (currentBlock != null && bci > currentBlock.endBci) {
3008            frameState.clearNonLiveLocals(currentBlock, liveness, false);
3009        }
3010        return frameState.create(bci, forStateSplit);
3011    }
3012
3013    @Override
3014    public void setStateAfter(StateSplit sideEffect) {
3015        assert sideEffect.hasSideEffect();
3016        FrameState stateAfter = createFrameState(stream.nextBCI(), sideEffect);
3017        sideEffect.setStateAfter(stateAfter);
3018    }
3019
3020    protected NodeSourcePosition createBytecodePosition() {
3021        return frameState.createBytecodePosition(bci());
3022    }
3023
3024    public void setCurrentFrameState(FrameStateBuilder frameState) {
3025        this.frameState = frameState;
3026    }
3027
3028    protected final BytecodeStream getStream() {
3029        return stream;
3030    }
3031
3032    @Override
3033    public int bci() {
3034        return stream.currentBCI();
3035    }
3036
3037    public void loadLocal(int index, JavaKind kind) {
3038        ValueNode value = frameState.loadLocal(index, kind);
3039        frameState.push(kind, value);
3040    }
3041
3042    public void storeLocal(JavaKind kind, int index) {
3043        ValueNode value = frameState.pop(kind);
3044        frameState.storeLocal(index, kind, value);
3045    }
3046
3047    private void genLoadConstant(int cpi, int opcode) {
3048        Object con = lookupConstant(cpi, opcode);
3049
3050        if (con instanceof JavaType) {
3051            // this is a load of class constant which might be unresolved
3052            JavaType type = (JavaType) con;
3053            if (type instanceof ResolvedJavaType) {
3054                frameState.push(JavaKind.Object, appendConstant(getConstantReflection().asJavaClass((ResolvedJavaType) type)));
3055            } else {
3056                handleUnresolvedLoadConstant(type);
3057            }
3058        } else if (con instanceof JavaConstant) {
3059            JavaConstant constant = (JavaConstant) con;
3060            frameState.push(constant.getJavaKind(), appendConstant(constant));
3061        } else {
3062            throw new Error("lookupConstant returned an object of incorrect type");
3063        }
3064    }
3065
3066    private void genLoadIndexed(JavaKind kind) {
3067        ValueNode index = frameState.pop(JavaKind.Int);
3068        ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), index);
3069
3070        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3071            if (plugin.handleLoadIndexed(this, array, index, kind)) {
3072                return;
3073            }
3074        }
3075
3076        frameState.push(kind, append(genLoadIndexed(array, index, kind)));
3077    }
3078
3079    private void genStoreIndexed(JavaKind kind) {
3080        ValueNode value = frameState.pop(kind);
3081        ValueNode index = frameState.pop(JavaKind.Int);
3082        ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), index);
3083
3084        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3085            if (plugin.handleStoreIndexed(this, array, index, kind, value)) {
3086                return;
3087            }
3088        }
3089
3090        genStoreIndexed(array, index, kind, value);
3091    }
3092
3093    private void genArithmeticOp(JavaKind kind, int opcode) {
3094        ValueNode y = frameState.pop(kind);
3095        ValueNode x = frameState.pop(kind);
3096        ValueNode v;
3097        switch (opcode) {
3098            case IADD:
3099            case LADD:
3100                v = genIntegerAdd(x, y);
3101                break;
3102            case FADD:
3103            case DADD:
3104                v = genFloatAdd(x, y);
3105                break;
3106            case ISUB:
3107            case LSUB:
3108                v = genIntegerSub(x, y);
3109                break;
3110            case FSUB:
3111            case DSUB:
3112                v = genFloatSub(x, y);
3113                break;
3114            case IMUL:
3115            case LMUL:
3116                v = genIntegerMul(x, y);
3117                break;
3118            case FMUL:
3119            case DMUL:
3120                v = genFloatMul(x, y);
3121                break;
3122            case FDIV:
3123            case DDIV:
3124                v = genFloatDiv(x, y);
3125                break;
3126            case FREM:
3127            case DREM:
3128                v = genFloatRem(x, y);
3129                break;
3130            default:
3131                throw shouldNotReachHere();
3132        }
3133        frameState.push(kind, append(v));
3134    }
3135
3136    private void genIntegerDivOp(JavaKind kind, int opcode) {
3137        ValueNode y = frameState.pop(kind);
3138        ValueNode x = frameState.pop(kind);
3139        ValueNode v;
3140        switch (opcode) {
3141            case IDIV:
3142            case LDIV:
3143                v = genIntegerDiv(x, y);
3144                break;
3145            case IREM:
3146            case LREM:
3147                v = genIntegerRem(x, y);
3148                break;
3149            default:
3150                throw shouldNotReachHere();
3151        }
3152        frameState.push(kind, append(v));
3153    }
3154
3155    private void genNegateOp(JavaKind kind) {
3156        ValueNode x = frameState.pop(kind);
3157        frameState.push(kind, append(genNegateOp(x)));
3158    }
3159
3160    private void genShiftOp(JavaKind kind, int opcode) {
3161        ValueNode s = frameState.pop(JavaKind.Int);
3162        ValueNode x = frameState.pop(kind);
3163        ValueNode v;
3164        switch (opcode) {
3165            case ISHL:
3166            case LSHL:
3167                v = genLeftShift(x, s);
3168                break;
3169            case ISHR:
3170            case LSHR:
3171                v = genRightShift(x, s);
3172                break;
3173            case IUSHR:
3174            case LUSHR:
3175                v = genUnsignedRightShift(x, s);
3176                break;
3177            default:
3178                throw shouldNotReachHere();
3179        }
3180        frameState.push(kind, append(v));
3181    }
3182
3183    private void genLogicOp(JavaKind kind, int opcode) {
3184        ValueNode y = frameState.pop(kind);
3185        ValueNode x = frameState.pop(kind);
3186        ValueNode v;
3187        switch (opcode) {
3188            case IAND:
3189            case LAND:
3190                v = genAnd(x, y);
3191                break;
3192            case IOR:
3193            case LOR:
3194                v = genOr(x, y);
3195                break;
3196            case IXOR:
3197            case LXOR:
3198                v = genXor(x, y);
3199                break;
3200            default:
3201                throw shouldNotReachHere();
3202        }
3203        frameState.push(kind, append(v));
3204    }
3205
3206    private void genCompareOp(JavaKind kind, boolean isUnorderedLess) {
3207        ValueNode y = frameState.pop(kind);
3208        ValueNode x = frameState.pop(kind);
3209        frameState.push(JavaKind.Int, append(genNormalizeCompare(x, y, isUnorderedLess)));
3210    }
3211
3212    private void genFloatConvert(FloatConvert op, JavaKind from, JavaKind to) {
3213        ValueNode input = frameState.pop(from);
3214        frameState.push(to, append(genFloatConvert(op, input)));
3215    }
3216
3217    private void genSignExtend(JavaKind from, JavaKind to) {
3218        ValueNode input = frameState.pop(from);
3219        if (from != from.getStackKind()) {
3220            input = append(genNarrow(input, from.getBitCount()));
3221        }
3222        frameState.push(to, append(genSignExtend(input, to.getBitCount())));
3223    }
3224
3225    private void genZeroExtend(JavaKind from, JavaKind to) {
3226        ValueNode input = frameState.pop(from);
3227        if (from != from.getStackKind()) {
3228            input = append(genNarrow(input, from.getBitCount()));
3229        }
3230        frameState.push(to, append(genZeroExtend(input, to.getBitCount())));
3231    }
3232
3233    private void genNarrow(JavaKind from, JavaKind to) {
3234        ValueNode input = frameState.pop(from);
3235        frameState.push(to, append(genNarrow(input, to.getBitCount())));
3236    }
3237
3238    private void genIncrement() {
3239        int index = getStream().readLocalIndex();
3240        int delta = getStream().readIncrement();
3241        ValueNode x = frameState.loadLocal(index, JavaKind.Int);
3242        ValueNode y = appendConstant(JavaConstant.forInt(delta));
3243        frameState.storeLocal(index, JavaKind.Int, append(genIntegerAdd(x, y)));
3244    }
3245
3246    private void genIfZero(Condition cond) {
3247        ValueNode y = appendConstant(JavaConstant.INT_0);
3248        ValueNode x = frameState.pop(JavaKind.Int);
3249        genIf(x, cond, y);
3250    }
3251
3252    private void genIfNull(Condition cond) {
3253        ValueNode y = appendConstant(JavaConstant.NULL_POINTER);
3254        ValueNode x = frameState.pop(JavaKind.Object);
3255        genIf(x, cond, y);
3256    }
3257
3258    private void genIfSame(JavaKind kind, Condition cond) {
3259        ValueNode y = frameState.pop(kind);
3260        ValueNode x = frameState.pop(kind);
3261        genIf(x, cond, y);
3262    }
3263
3264    protected JavaType lookupType(int cpi, int bytecode) {
3265        maybeEagerlyResolve(cpi, bytecode);
3266        JavaType result = constantPool.lookupType(cpi, bytecode);
3267        assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
3268        return result;
3269    }
3270
3271    private JavaMethod lookupMethod(int cpi, int opcode) {
3272        maybeEagerlyResolve(cpi, opcode);
3273        JavaMethod result = constantPool.lookupMethod(cpi, opcode);
3274        /*
3275         * In general, one cannot assume that the declaring class being initialized is useful, since
3276         * the actual concrete receiver may be a different class (except for static calls). Also,
3277         * interfaces are initialized only under special circumstances, so that this assertion would
3278         * often fail for interface calls.
3279         */
3280        assert !graphBuilderConfig.unresolvedIsError() ||
3281                        (result instanceof ResolvedJavaMethod && (opcode != INVOKESTATIC || ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized())) : result;
3282        return result;
3283    }
3284
3285    private JavaField lookupField(int cpi, int opcode) {
3286        maybeEagerlyResolve(cpi, opcode);
3287        JavaField result = constantPool.lookupField(cpi, method, opcode);
3288        if (graphBuilderConfig.eagerResolving()) {
3289            assert result instanceof ResolvedJavaField : "Not resolved: " + result;
3290            ResolvedJavaType declaringClass = ((ResolvedJavaField) result).getDeclaringClass();
3291            if (!declaringClass.isInitialized()) {
3292                assert declaringClass.isInterface() : "Declaring class not initialized but not an interface? " + declaringClass;
3293                declaringClass.initialize();
3294            }
3295        }
3296        assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
3297        return result;
3298    }
3299
3300    private Object lookupConstant(int cpi, int opcode) {
3301        maybeEagerlyResolve(cpi, opcode);
3302        Object result = constantPool.lookupConstant(cpi);
3303        assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType) : result;
3304        return result;
3305    }
3306
3307    private void maybeEagerlyResolve(int cpi, int bytecode) {
3308        if (intrinsicContext != null) {
3309            constantPool.loadReferencedType(cpi, bytecode);
3310        } else if (graphBuilderConfig.eagerResolving()) {
3311            /*
3312             * Since we're potentially triggering class initialization here, we need synchronization
3313             * to mitigate the potential for class initialization related deadlock being caused by
3314             * the compiler (e.g., https://github.com/graalvm/graal-core/pull/232/files#r90788550).
3315             */
3316            synchronized (BytecodeParser.class) {
3317                constantPool.loadReferencedType(cpi, bytecode);
3318            }
3319        }
3320    }
3321
3322    private JavaTypeProfile getProfileForTypeCheck(TypeReference type) {
3323        if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || type.isExact()) {
3324            return null;
3325        } else {
3326            return profilingInfo.getTypeProfile(bci());
3327        }
3328    }
3329
3330    private void genCheckCast() {
3331        int cpi = getStream().readCPI();
3332        JavaType type = lookupType(cpi, CHECKCAST);
3333        ValueNode object = frameState.pop(JavaKind.Object);
3334
3335        if (!(type instanceof ResolvedJavaType)) {
3336            handleUnresolvedCheckCast(type, object);
3337            return;
3338        }
3339        TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) type);
3340        JavaTypeProfile profile = getProfileForTypeCheck(checkedType);
3341
3342        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3343            if (plugin.handleCheckCast(this, object, checkedType.getType(), profile)) {
3344                return;
3345            }
3346        }
3347
3348        ValueNode castNode = null;
3349        if (profile != null) {
3350            if (profile.getNullSeen().isFalse()) {
3351                object = appendNullCheck(object);
3352                ResolvedJavaType singleType = profile.asSingleType();
3353                if (singleType != null && checkedType.getType().isAssignableFrom(singleType)) {
3354                    LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile));
3355                    if (typeCheck.isTautology()) {
3356                        castNode = object;
3357                    } else {
3358                        FixedGuardNode fixedGuard = append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile, false));
3359                        castNode = append(new PiNode(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard));
3360                    }
3361                }
3362            }
3363        }
3364        if (castNode == null) {
3365            LogicNode condition = genUnique(createInstanceOfAllowNull(checkedType, object, null));
3366            if (condition.isTautology()) {
3367                castNode = object;
3368            } else {
3369                FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false));
3370                castNode = append(new PiNode(object, StampFactory.object(checkedType), fixedGuard));
3371            }
3372        }
3373        frameState.push(JavaKind.Object, castNode);
3374    }
3375
3376    private ValueNode appendNullCheck(ValueNode object) {
3377        if (object.stamp() instanceof AbstractPointerStamp) {
3378            AbstractPointerStamp stamp = (AbstractPointerStamp) object.stamp();
3379            if (stamp.nonNull()) {
3380                return object;
3381            }
3382        }
3383
3384        LogicNode isNull = append(IsNullNode.create(object));
3385        FixedGuardNode fixedGuard = append(new FixedGuardNode(isNull, DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true));
3386        return append(new PiNode(object, object.stamp().join(StampFactory.objectNonNull()), fixedGuard));
3387    }
3388
3389    private void genInstanceOf() {
3390        int cpi = getStream().readCPI();
3391        JavaType type = lookupType(cpi, INSTANCEOF);
3392        ValueNode object = frameState.pop(JavaKind.Object);
3393
3394        if (!(type instanceof ResolvedJavaType)) {
3395            handleUnresolvedInstanceOf(type, object);
3396            return;
3397        }
3398        TypeReference resolvedType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) type);
3399        JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
3400
3401        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3402            if (plugin.handleInstanceOf(this, object, resolvedType.getType(), profile)) {
3403                return;
3404            }
3405        }
3406
3407        LogicNode instanceOfNode = null;
3408        if (profile != null) {
3409            if (profile.getNullSeen().isFalse()) {
3410                object = appendNullCheck(object);
3411                ResolvedJavaType singleType = profile.asSingleType();
3412                if (singleType != null) {
3413                    LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile));
3414                    if (!typeCheck.isTautology()) {
3415                        append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
3416                    }
3417                    instanceOfNode = LogicConstantNode.forBoolean(resolvedType.getType().isAssignableFrom(singleType));
3418                }
3419            }
3420        }
3421        if (instanceOfNode == null) {
3422            instanceOfNode = createInstanceOf(resolvedType, object, null);
3423        }
3424        frameState.push(JavaKind.Int, append(genConditional(genUnique(instanceOfNode))));
3425    }
3426
3427    void genNewInstance(int cpi) {
3428        JavaType type = lookupType(cpi, NEW);
3429
3430        if (!(type instanceof ResolvedJavaType) || !((ResolvedJavaType) type).isInitialized()) {
3431            handleUnresolvedNewInstance(type);
3432            return;
3433        }
3434        ResolvedJavaType resolvedType = (ResolvedJavaType) type;
3435
3436        ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
3437        if (skippedExceptionTypes != null) {
3438            for (ResolvedJavaType exceptionType : skippedExceptionTypes) {
3439                if (exceptionType.isAssignableFrom(resolvedType)) {
3440                    append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, RuntimeConstraint));
3441                    return;
3442                }
3443            }
3444        }
3445
3446        ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
3447        if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType)) {
3448            FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3449            classInitializationPlugin.apply(this, resolvedType, stateBefore);
3450        }
3451
3452        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3453            if (plugin.handleNewInstance(this, resolvedType)) {
3454                return;
3455            }
3456        }
3457
3458        frameState.push(JavaKind.Object, append(createNewInstance(resolvedType, true)));
3459    }
3460
3461    /**
3462     * Gets the kind of array elements for the array type code that appears in a
3463     * {@link Bytecodes#NEWARRAY} bytecode.
3464     *
3465     * @param code the array type code
3466     * @return the kind from the array type code
3467     */
3468    private static Class<?> arrayTypeCodeToClass(int code) {
3469        switch (code) {
3470            case 4:
3471                return boolean.class;
3472            case 5:
3473                return char.class;
3474            case 6:
3475                return float.class;
3476            case 7:
3477                return double.class;
3478            case 8:
3479                return byte.class;
3480            case 9:
3481                return short.class;
3482            case 10:
3483                return int.class;
3484            case 11:
3485                return long.class;
3486            default:
3487                throw new IllegalArgumentException("unknown array type code: " + code);
3488        }
3489    }
3490
3491    private void genNewPrimitiveArray(int typeCode) {
3492        ResolvedJavaType elementType = metaAccess.lookupJavaType(arrayTypeCodeToClass(typeCode));
3493        ValueNode length = frameState.pop(JavaKind.Int);
3494
3495        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3496            if (plugin.handleNewArray(this, elementType, length)) {
3497                return;
3498            }
3499        }
3500
3501        frameState.push(JavaKind.Object, append(createNewArray(elementType, length, true)));
3502    }
3503
3504    private void genNewObjectArray(int cpi) {
3505        JavaType type = lookupType(cpi, ANEWARRAY);
3506
3507        if (!(type instanceof ResolvedJavaType)) {
3508            ValueNode length = frameState.pop(JavaKind.Int);
3509            handleUnresolvedNewObjectArray(type, length);
3510            return;
3511        }
3512
3513        ResolvedJavaType resolvedType = (ResolvedJavaType) type;
3514
3515        ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
3516        if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType.getArrayClass())) {
3517            FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3518            classInitializationPlugin.apply(this, resolvedType.getArrayClass(), stateBefore);
3519        }
3520
3521        ValueNode length = frameState.pop(JavaKind.Int);
3522        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3523            if (plugin.handleNewArray(this, resolvedType, length)) {
3524                return;
3525            }
3526        }
3527
3528        frameState.push(JavaKind.Object, append(createNewArray(resolvedType, length, true)));
3529    }
3530
3531    private void genNewMultiArray(int cpi) {
3532        JavaType type = lookupType(cpi, MULTIANEWARRAY);
3533        int rank = getStream().readUByte(bci() + 3);
3534        ValueNode[] dims = new ValueNode[rank];
3535
3536        if (!(type instanceof ResolvedJavaType)) {
3537            for (int i = rank - 1; i >= 0; i--) {
3538                dims[i] = frameState.pop(JavaKind.Int);
3539            }
3540            handleUnresolvedNewMultiArray(type, dims);
3541            return;
3542        }
3543        ResolvedJavaType resolvedType = (ResolvedJavaType) type;
3544
3545        ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
3546        if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType.getArrayClass())) {
3547            FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3548            classInitializationPlugin.apply(this, resolvedType.getArrayClass(), stateBefore);
3549        }
3550
3551        for (int i = rank - 1; i >= 0; i--) {
3552            dims[i] = frameState.pop(JavaKind.Int);
3553        }
3554
3555        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3556            if (plugin.handleNewMultiArray(this, resolvedType, dims)) {
3557                return;
3558            }
3559        }
3560
3561        frameState.push(JavaKind.Object, append(createNewMultiArray(resolvedType, dims)));
3562    }
3563
3564    private void genGetField(JavaField field) {
3565        ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object), null);
3566
3567        if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
3568            handleUnresolvedLoadField(field, receiver);
3569            return;
3570        }
3571        ResolvedJavaField resolvedField = (ResolvedJavaField) field;
3572
3573        if (!parsingIntrinsic() && GeneratePIC.getValue()) {
3574            graph.recordField(resolvedField);
3575        }
3576
3577        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3578            if (plugin.handleLoadField(this, receiver, resolvedField)) {
3579                return;
3580            }
3581        }
3582
3583        frameState.push(field.getJavaKind(), append(genLoadField(receiver, resolvedField)));
3584        if (resolvedField.getName().equals("referent") && resolvedField.getDeclaringClass().equals(metaAccess.lookupJavaType(Reference.class))) {
3585            LocationIdentity referentIdentity = new FieldLocationIdentity(resolvedField);
3586            append(new MembarNode(0, referentIdentity));
3587        }
3588    }
3589
3590    /**
3591     * @param receiver the receiver of an object based operation
3592     * @param index the index of an array based operation that is to be tested for out of bounds.
3593     *            This is null for a non-array operation.
3594     * @return the receiver value possibly modified to have a tighter stamp
3595     */
3596    protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) {
3597        assert receiver != null;
3598        if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) {
3599            return receiver;
3600        }
3601        if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile && (profilingInfo == null ||
3602                        (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue()))) {
3603            return receiver;
3604        }
3605
3606        ValueNode nonNullReceiver = emitExplicitNullCheck(receiver);
3607        if (index != null) {
3608            ValueNode length = append(genArrayLength(nonNullReceiver));
3609            emitExplicitBoundsCheck(index, length);
3610        }
3611        EXPLICIT_EXCEPTIONS.increment();
3612        return nonNullReceiver;
3613    }
3614
3615    private void genPutField(JavaField field) {
3616        ValueNode value = frameState.pop(field.getJavaKind());
3617        ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object), null);
3618
3619        if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
3620            handleUnresolvedStoreField(field, value, receiver);
3621            return;
3622        }
3623        ResolvedJavaField resolvedField = (ResolvedJavaField) field;
3624
3625        if (!parsingIntrinsic() && GeneratePIC.getValue()) {
3626            graph.recordField(resolvedField);
3627        }
3628
3629        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3630            if (plugin.handleStoreField(this, receiver, resolvedField, value)) {
3631                return;
3632            }
3633        }
3634
3635        if (resolvedField.isFinal() && method.isConstructor()) {
3636            finalBarrierRequired = true;
3637        }
3638        genStoreField(receiver, resolvedField, value);
3639    }
3640
3641    private void genGetStatic(JavaField field) {
3642        if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
3643            handleUnresolvedLoadField(field, null);
3644            return;
3645        }
3646        ResolvedJavaField resolvedField = (ResolvedJavaField) field;
3647
3648        if (!parsingIntrinsic() && GeneratePIC.getValue()) {
3649            graph.recordField(resolvedField);
3650        }
3651
3652        /*
3653         * Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in
3654         * which case a suffix is added to the generated field.
3655         */
3656        if ((parsingIntrinsic() || graphBuilderConfig.omitAssertions()) && resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) {
3657            frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph));
3658            return;
3659        }
3660
3661        ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
3662        if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedField.getDeclaringClass())) {
3663            FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3664            classInitializationPlugin.apply(this, resolvedField.getDeclaringClass(), stateBefore);
3665        }
3666
3667        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3668            if (plugin.handleLoadStaticField(this, resolvedField)) {
3669                return;
3670            }
3671        }
3672
3673        frameState.push(field.getJavaKind(), append(genLoadField(null, resolvedField)));
3674    }
3675
3676    private void genPutStatic(JavaField field) {
3677        ValueNode value = frameState.pop(field.getJavaKind());
3678        if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
3679            handleUnresolvedStoreField(field, value, null);
3680            return;
3681        }
3682        ResolvedJavaField resolvedField = (ResolvedJavaField) field;
3683
3684        if (!parsingIntrinsic() && GeneratePIC.getValue()) {
3685            graph.recordField(resolvedField);
3686        }
3687
3688        ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
3689        if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedField.getDeclaringClass())) {
3690            FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
3691            classInitializationPlugin.apply(this, resolvedField.getDeclaringClass(), stateBefore);
3692        }
3693
3694        for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
3695            if (plugin.handleStoreStaticField(this, resolvedField, value)) {
3696                return;
3697            }
3698        }
3699
3700        genStoreField(null, resolvedField, value);
3701    }
3702
3703    private double[] switchProbability(int numberOfCases, int bci) {
3704        double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci));
3705        if (prob != null) {
3706            assert prob.length == numberOfCases;
3707        } else {
3708            Debug.log("Missing probability (switch) in %s at bci %d", method, bci);
3709            prob = new double[numberOfCases];
3710            for (int i = 0; i < numberOfCases; i++) {
3711                prob[i] = 1.0d / numberOfCases;
3712            }
3713        }
3714        assert allPositive(prob);
3715        return prob;
3716    }
3717
3718    private static boolean allPositive(double[] a) {
3719        for (double d : a) {
3720            if (d < 0) {
3721                return false;
3722            }
3723        }
3724        return true;
3725    }
3726
3727    static class SuccessorInfo {
3728        final int blockIndex;
3729        int actualIndex;
3730
3731        SuccessorInfo(int blockSuccessorIndex) {
3732            this.blockIndex = blockSuccessorIndex;
3733            actualIndex = -1;
3734        }
3735    }
3736
3737    private void genSwitch(BytecodeSwitch bs) {
3738        int bci = bci();
3739        ValueNode value = frameState.pop(JavaKind.Int);
3740
3741        int nofCases = bs.numberOfCases();
3742        double[] keyProbabilities = switchProbability(nofCases + 1, bci);
3743
3744        Map<Integer, SuccessorInfo> bciToBlockSuccessorIndex = new HashMap<>();
3745        for (int i = 0; i < currentBlock.getSuccessorCount(); i++) {
3746            assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci);
3747            if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) {
3748                bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i));
3749            }
3750        }
3751
3752        ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
3753        int[] keys = new int[nofCases];
3754        int[] keySuccessors = new int[nofCases + 1];
3755        int deoptSuccessorIndex = -1;
3756        int nextSuccessorIndex = 0;
3757        boolean constantValue = value.isConstant();
3758        for (int i = 0; i < nofCases + 1; i++) {
3759            if (i < nofCases) {
3760                keys[i] = bs.keyAt(i);
3761            }
3762
3763            if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
3764                if (deoptSuccessorIndex < 0) {
3765                    deoptSuccessorIndex = nextSuccessorIndex++;
3766                    actualSuccessors.add(null);
3767                }
3768                keySuccessors[i] = deoptSuccessorIndex;
3769            } else {
3770                int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i);
3771                SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
3772                if (info.actualIndex < 0) {
3773                    info.actualIndex = nextSuccessorIndex++;
3774                    actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex));
3775                }
3776                keySuccessors[i] = info.actualIndex;
3777            }
3778        }
3779
3780        genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors);
3781
3782    }
3783
3784    protected boolean isNeverExecutedCode(double probability) {
3785        return probability == 0 && optimisticOpts.removeNeverExecutedCode();
3786    }
3787
3788    protected double branchProbability() {
3789        if (profilingInfo == null) {
3790            return 0.5;
3791        }
3792        assert assertAtIfBytecode();
3793        double probability = profilingInfo.getBranchTakenProbability(bci());
3794        if (probability < 0) {
3795            assert probability == -1 : "invalid probability";
3796            Debug.log("missing probability in %s at bci %d", code, bci());
3797            probability = 0.5;
3798        }
3799
3800        if (!optimisticOpts.removeNeverExecutedCode()) {
3801            if (probability == 0) {
3802                probability = 0.0000001;
3803            } else if (probability == 1) {
3804                probability = 0.999999;
3805            }
3806        }
3807        return probability;
3808    }
3809
3810    private boolean assertAtIfBytecode() {
3811        int bytecode = stream.currentBC();
3812        switch (bytecode) {
3813            case IFEQ:
3814            case IFNE:
3815            case IFLT:
3816            case IFGE:
3817            case IFGT:
3818            case IFLE:
3819            case IF_ICMPEQ:
3820            case IF_ICMPNE:
3821            case IF_ICMPLT:
3822            case IF_ICMPGE:
3823            case IF_ICMPGT:
3824            case IF_ICMPLE:
3825            case IF_ACMPEQ:
3826            case IF_ACMPNE:
3827            case IFNULL:
3828            case IFNONNULL:
3829                return true;
3830        }
3831        assert false : String.format("%x is not an if bytecode", bytecode);
3832        return true;
3833    }
3834
3835    public final void processBytecode(int bci, int opcode) {
3836        int cpi;
3837
3838        // @formatter:off
3839        // Checkstyle: stop
3840        switch (opcode) {
3841            case NOP            : /* nothing to do */ break;
3842            case ACONST_NULL    : frameState.push(JavaKind.Object, appendConstant(JavaConstant.NULL_POINTER)); break;
3843            case ICONST_M1      : // fall through
3844            case ICONST_0       : // fall through
3845            case ICONST_1       : // fall through
3846            case ICONST_2       : // fall through
3847            case ICONST_3       : // fall through
3848            case ICONST_4       : // fall through
3849            case ICONST_5       : frameState.push(JavaKind.Int, appendConstant(JavaConstant.forInt(opcode - ICONST_0))); break;
3850            case LCONST_0       : // fall through
3851            case LCONST_1       : frameState.push(JavaKind.Long, appendConstant(JavaConstant.forLong(opcode - LCONST_0))); break;
3852            case FCONST_0       : // fall through
3853            case FCONST_1       : // fall through
3854            case FCONST_2       : frameState.push(JavaKind.Float, appendConstant(JavaConstant.forFloat(opcode - FCONST_0))); break;
3855            case DCONST_0       : // fall through
3856            case DCONST_1       : frameState.push(JavaKind.Double, appendConstant(JavaConstant.forDouble(opcode - DCONST_0))); break;
3857            case BIPUSH         : frameState.push(JavaKind.Int, appendConstant(JavaConstant.forInt(stream.readByte()))); break;
3858            case SIPUSH         : frameState.push(JavaKind.Int, appendConstant(JavaConstant.forInt(stream.readShort()))); break;
3859            case LDC            : // fall through
3860            case LDC_W          : // fall through
3861            case LDC2_W         : genLoadConstant(stream.readCPI(), opcode); break;
3862            case ILOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Int); break;
3863            case LLOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Long); break;
3864            case FLOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Float); break;
3865            case DLOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Double); break;
3866            case ALOAD          : loadLocal(stream.readLocalIndex(), JavaKind.Object); break;
3867            case ILOAD_0        : // fall through
3868            case ILOAD_1        : // fall through
3869            case ILOAD_2        : // fall through
3870            case ILOAD_3        : loadLocal(opcode - ILOAD_0, JavaKind.Int); break;
3871            case LLOAD_0        : // fall through
3872            case LLOAD_1        : // fall through
3873            case LLOAD_2        : // fall through
3874            case LLOAD_3        : loadLocal(opcode - LLOAD_0, JavaKind.Long); break;
3875            case FLOAD_0        : // fall through
3876            case FLOAD_1        : // fall through
3877            case FLOAD_2        : // fall through
3878            case FLOAD_3        : loadLocal(opcode - FLOAD_0, JavaKind.Float); break;
3879            case DLOAD_0        : // fall through
3880            case DLOAD_1        : // fall through
3881            case DLOAD_2        : // fall through
3882            case DLOAD_3        : loadLocal(opcode - DLOAD_0, JavaKind.Double); break;
3883            case ALOAD_0        : // fall through
3884            case ALOAD_1        : // fall through
3885            case ALOAD_2        : // fall through
3886            case ALOAD_3        : loadLocal(opcode - ALOAD_0, JavaKind.Object); break;
3887            case IALOAD         : genLoadIndexed(JavaKind.Int   ); break;
3888            case LALOAD         : genLoadIndexed(JavaKind.Long  ); break;
3889            case FALOAD         : genLoadIndexed(JavaKind.Float ); break;
3890            case DALOAD         : genLoadIndexed(JavaKind.Double); break;
3891            case AALOAD         : genLoadIndexed(JavaKind.Object); break;
3892            case BALOAD         : genLoadIndexed(JavaKind.Byte  ); break;
3893            case CALOAD         : genLoadIndexed(JavaKind.Char  ); break;
3894            case SALOAD         : genLoadIndexed(JavaKind.Short ); break;
3895            case ISTORE         : storeLocal(JavaKind.Int, stream.readLocalIndex()); break;
3896            case LSTORE         : storeLocal(JavaKind.Long, stream.readLocalIndex()); break;
3897            case FSTORE         : storeLocal(JavaKind.Float, stream.readLocalIndex()); break;
3898            case DSTORE         : storeLocal(JavaKind.Double, stream.readLocalIndex()); break;
3899            case ASTORE         : storeLocal(JavaKind.Object, stream.readLocalIndex()); break;
3900            case ISTORE_0       : // fall through
3901            case ISTORE_1       : // fall through
3902            case ISTORE_2       : // fall through
3903            case ISTORE_3       : storeLocal(JavaKind.Int, opcode - ISTORE_0); break;
3904            case LSTORE_0       : // fall through
3905            case LSTORE_1       : // fall through
3906            case LSTORE_2       : // fall through
3907            case LSTORE_3       : storeLocal(JavaKind.Long, opcode - LSTORE_0); break;
3908            case FSTORE_0       : // fall through
3909            case FSTORE_1       : // fall through
3910            case FSTORE_2       : // fall through
3911            case FSTORE_3       : storeLocal(JavaKind.Float, opcode - FSTORE_0); break;
3912            case DSTORE_0       : // fall through
3913            case DSTORE_1       : // fall through
3914            case DSTORE_2       : // fall through
3915            case DSTORE_3       : storeLocal(JavaKind.Double, opcode - DSTORE_0); break;
3916            case ASTORE_0       : // fall through
3917            case ASTORE_1       : // fall through
3918            case ASTORE_2       : // fall through
3919            case ASTORE_3       : storeLocal(JavaKind.Object, opcode - ASTORE_0); break;
3920            case IASTORE        : genStoreIndexed(JavaKind.Int   ); break;
3921            case LASTORE        : genStoreIndexed(JavaKind.Long  ); break;
3922            case FASTORE        : genStoreIndexed(JavaKind.Float ); break;
3923            case DASTORE        : genStoreIndexed(JavaKind.Double); break;
3924            case AASTORE        : genStoreIndexed(JavaKind.Object); break;
3925            case BASTORE        : genStoreIndexed(JavaKind.Byte  ); break;
3926            case CASTORE        : genStoreIndexed(JavaKind.Char  ); break;
3927            case SASTORE        : genStoreIndexed(JavaKind.Short ); break;
3928            case POP            : // fall through
3929            case POP2           : // fall through
3930            case DUP            : // fall through
3931            case DUP_X1         : // fall through
3932            case DUP_X2         : // fall through
3933            case DUP2           : // fall through
3934            case DUP2_X1        : // fall through
3935            case DUP2_X2        : // fall through
3936            case SWAP           : frameState.stackOp(opcode); break;
3937            case IADD           : // fall through
3938            case ISUB           : // fall through
3939            case IMUL           : genArithmeticOp(JavaKind.Int, opcode); break;
3940            case IDIV           : // fall through
3941            case IREM           : genIntegerDivOp(JavaKind.Int, opcode); break;
3942            case LADD           : // fall through
3943            case LSUB           : // fall through
3944            case LMUL           : genArithmeticOp(JavaKind.Long, opcode); break;
3945            case LDIV           : // fall through
3946            case LREM           : genIntegerDivOp(JavaKind.Long, opcode); break;
3947            case FADD           : // fall through
3948            case FSUB           : // fall through
3949            case FMUL           : // fall through
3950            case FDIV           : // fall through
3951            case FREM           : genArithmeticOp(JavaKind.Float, opcode); break;
3952            case DADD           : // fall through
3953            case DSUB           : // fall through
3954            case DMUL           : // fall through
3955            case DDIV           : // fall through
3956            case DREM           : genArithmeticOp(JavaKind.Double, opcode); break;
3957            case INEG           : genNegateOp(JavaKind.Int); break;
3958            case LNEG           : genNegateOp(JavaKind.Long); break;
3959            case FNEG           : genNegateOp(JavaKind.Float); break;
3960            case DNEG           : genNegateOp(JavaKind.Double); break;
3961            case ISHL           : // fall through
3962            case ISHR           : // fall through
3963            case IUSHR          : genShiftOp(JavaKind.Int, opcode); break;
3964            case IAND           : // fall through
3965            case IOR            : // fall through
3966            case IXOR           : genLogicOp(JavaKind.Int, opcode); break;
3967            case LSHL           : // fall through
3968            case LSHR           : // fall through
3969            case LUSHR          : genShiftOp(JavaKind.Long, opcode); break;
3970            case LAND           : // fall through
3971            case LOR            : // fall through
3972            case LXOR           : genLogicOp(JavaKind.Long, opcode); break;
3973            case IINC           : genIncrement(); break;
3974            case I2F            : genFloatConvert(FloatConvert.I2F, JavaKind.Int, JavaKind.Float); break;
3975            case I2D            : genFloatConvert(FloatConvert.I2D, JavaKind.Int, JavaKind.Double); break;
3976            case L2F            : genFloatConvert(FloatConvert.L2F, JavaKind.Long, JavaKind.Float); break;
3977            case L2D            : genFloatConvert(FloatConvert.L2D, JavaKind.Long, JavaKind.Double); break;
3978            case F2I            : genFloatConvert(FloatConvert.F2I, JavaKind.Float, JavaKind.Int); break;
3979            case F2L            : genFloatConvert(FloatConvert.F2L, JavaKind.Float, JavaKind.Long); break;
3980            case F2D            : genFloatConvert(FloatConvert.F2D, JavaKind.Float, JavaKind.Double); break;
3981            case D2I            : genFloatConvert(FloatConvert.D2I, JavaKind.Double, JavaKind.Int); break;
3982            case D2L            : genFloatConvert(FloatConvert.D2L, JavaKind.Double, JavaKind.Long); break;
3983            case D2F            : genFloatConvert(FloatConvert.D2F, JavaKind.Double, JavaKind.Float); break;
3984            case L2I            : genNarrow(JavaKind.Long, JavaKind.Int); break;
3985            case I2L            : genSignExtend(JavaKind.Int, JavaKind.Long); break;
3986            case I2B            : genSignExtend(JavaKind.Byte, JavaKind.Int); break;
3987            case I2S            : genSignExtend(JavaKind.Short, JavaKind.Int); break;
3988            case I2C            : genZeroExtend(JavaKind.Char, JavaKind.Int); break;
3989            case LCMP           : genCompareOp(JavaKind.Long, false); break;
3990            case FCMPL          : genCompareOp(JavaKind.Float, true); break;
3991            case FCMPG          : genCompareOp(JavaKind.Float, false); break;
3992            case DCMPL          : genCompareOp(JavaKind.Double, true); break;
3993            case DCMPG          : genCompareOp(JavaKind.Double, false); break;
3994            case IFEQ           : genIfZero(Condition.EQ); break;
3995            case IFNE           : genIfZero(Condition.NE); break;
3996            case IFLT           : genIfZero(Condition.LT); break;
3997            case IFGE           : genIfZero(Condition.GE); break;
3998            case IFGT           : genIfZero(Condition.GT); break;
3999            case IFLE           : genIfZero(Condition.LE); break;
4000            case IF_ICMPEQ      : genIfSame(JavaKind.Int, Condition.EQ); break;
4001            case IF_ICMPNE      : genIfSame(JavaKind.Int, Condition.NE); break;
4002            case IF_ICMPLT      : genIfSame(JavaKind.Int, Condition.LT); break;
4003            case IF_ICMPGE      : genIfSame(JavaKind.Int, Condition.GE); break;
4004            case IF_ICMPGT      : genIfSame(JavaKind.Int, Condition.GT); break;
4005            case IF_ICMPLE      : genIfSame(JavaKind.Int, Condition.LE); break;
4006            case IF_ACMPEQ      : genIfSame(JavaKind.Object, Condition.EQ); break;
4007            case IF_ACMPNE      : genIfSame(JavaKind.Object, Condition.NE); break;
4008            case GOTO           : genGoto(); break;
4009            case JSR            : genJsr(stream.readBranchDest()); break;
4010            case RET            : genRet(stream.readLocalIndex()); break;
4011            case TABLESWITCH    : genSwitch(new BytecodeTableSwitch(getStream(), bci())); break;
4012            case LOOKUPSWITCH   : genSwitch(new BytecodeLookupSwitch(getStream(), bci())); break;
4013            case IRETURN        : genReturn(frameState.pop(JavaKind.Int), JavaKind.Int); break;
4014            case LRETURN        : genReturn(frameState.pop(JavaKind.Long), JavaKind.Long); break;
4015            case FRETURN        : genReturn(frameState.pop(JavaKind.Float), JavaKind.Float); break;
4016            case DRETURN        : genReturn(frameState.pop(JavaKind.Double), JavaKind.Double); break;
4017            case ARETURN        : genReturn(frameState.pop(JavaKind.Object), JavaKind.Object); break;
4018            case RETURN         : genReturn(null, JavaKind.Void); break;
4019            case GETSTATIC      : cpi = stream.readCPI(); genGetStatic(lookupField(cpi, opcode)); break;
4020            case PUTSTATIC      : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break;
4021            case GETFIELD       : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break;
4022            case PUTFIELD       : cpi = stream.readCPI(); genPutField(lookupField(cpi, opcode)); break;
4023            case INVOKEVIRTUAL  : cpi = stream.readCPI(); genInvokeVirtual(lookupMethod(cpi, opcode)); break;
4024            case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break;
4025            case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break;
4026            case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break;
4027            case INVOKEDYNAMIC  : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break;
4028            case NEW            : genNewInstance(stream.readCPI()); break;
4029            case NEWARRAY       : genNewPrimitiveArray(stream.readLocalIndex()); break;
4030            case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
4031            case ARRAYLENGTH    : genArrayLength(); break;
4032            case ATHROW         : genThrow(); break;
4033            case CHECKCAST      : genCheckCast(); break;
4034            case INSTANCEOF     : genInstanceOf(); break;
4035            case MONITORENTER   : genMonitorEnter(frameState.pop(JavaKind.Object), stream.nextBCI()); break;
4036            case MONITOREXIT    : genMonitorExit(frameState.pop(JavaKind.Object), null, stream.nextBCI()); break;
4037            case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
4038            case IFNULL         : genIfNull(Condition.EQ); break;
4039            case IFNONNULL      : genIfNull(Condition.NE); break;
4040            case GOTO_W         : genGoto(); break;
4041            case JSR_W          : genJsr(stream.readBranchDest()); break;
4042            case BREAKPOINT     : throw new PermanentBailoutException("concurrent setting of breakpoint");
4043            default             : throw new PermanentBailoutException("Unsupported opcode %d (%s) [bci=%d]", opcode, nameOf(opcode), bci);
4044        }
4045        // @formatter:on
4046        // Checkstyle: resume
4047    }
4048
4049    private void genArrayLength() {
4050        ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), null);
4051        frameState.push(JavaKind.Int, append(genArrayLength(array)));
4052    }
4053
4054    @Override
4055    public ResolvedJavaMethod getMethod() {
4056        return method;
4057    }
4058
4059    @Override
4060    public Bytecode getCode() {
4061        return code;
4062    }
4063
4064    public FrameStateBuilder getFrameStateBuilder() {
4065        return frameState;
4066    }
4067
4068    protected boolean traceInstruction(int bci, int opcode, boolean blockStart) {
4069        if (Debug.isEnabled() && BytecodeParserOptions.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) {
4070            traceInstructionHelper(bci, opcode, blockStart);
4071        }
4072        return true;
4073    }
4074
4075    private void traceInstructionHelper(int bci, int opcode, boolean blockStart) {
4076        StringBuilder sb = new StringBuilder(40);
4077        sb.append(blockStart ? '+' : '|');
4078        if (bci < 10) {
4079            sb.append("  ");
4080        } else if (bci < 100) {
4081            sb.append(' ');
4082        }
4083        sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode));
4084        for (int i = bci + 1; i < stream.nextBCI(); ++i) {
4085            sb.append(' ').append(stream.readUByte(i));
4086        }
4087        if (!currentBlock.getJsrScope().isEmpty()) {
4088            sb.append(' ').append(currentBlock.getJsrScope());
4089        }
4090        Debug.log("%s", sb);
4091    }
4092
4093    @Override
4094    public boolean parsingIntrinsic() {
4095        return intrinsicContext != null;
4096    }
4097
4098    @Override
4099    public BytecodeParser getNonIntrinsicAncestor() {
4100        BytecodeParser ancestor = parent;
4101        while (ancestor != null && ancestor.parsingIntrinsic()) {
4102            ancestor = ancestor.parent;
4103        }
4104        return ancestor;
4105    }
4106
4107    static String nSpaces(int n) {
4108        return n == 0 ? "" : format("%" + n + "s", "");
4109    }
4110
4111    @SuppressWarnings("all")
4112    private static boolean assertionsEnabled() {
4113        boolean assertionsEnabled = false;
4114        assert assertionsEnabled = true;
4115        return assertionsEnabled;
4116    }
4117}
4118