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