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