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