325 import org.graalvm.compiler.nodes.KillingBeginNode;
326 import org.graalvm.compiler.nodes.LogicConstantNode;
327 import org.graalvm.compiler.nodes.LogicNegationNode;
328 import org.graalvm.compiler.nodes.LogicNode;
329 import org.graalvm.compiler.nodes.LoopBeginNode;
330 import org.graalvm.compiler.nodes.LoopEndNode;
331 import org.graalvm.compiler.nodes.LoopExitNode;
332 import org.graalvm.compiler.nodes.MergeNode;
333 import org.graalvm.compiler.nodes.ParameterNode;
334 import org.graalvm.compiler.nodes.PiNode;
335 import org.graalvm.compiler.nodes.ReturnNode;
336 import org.graalvm.compiler.nodes.StartNode;
337 import org.graalvm.compiler.nodes.StateSplit;
338 import org.graalvm.compiler.nodes.StructuredGraph;
339 import org.graalvm.compiler.nodes.UnwindNode;
340 import org.graalvm.compiler.nodes.ValueNode;
341 import org.graalvm.compiler.nodes.calc.AddNode;
342 import org.graalvm.compiler.nodes.calc.AndNode;
343 import org.graalvm.compiler.nodes.calc.CompareNode;
344 import org.graalvm.compiler.nodes.calc.ConditionalNode;
345 import org.graalvm.compiler.nodes.calc.DivNode;
346 import org.graalvm.compiler.nodes.calc.FloatConvertNode;
347 import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
348 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
349 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
350 import org.graalvm.compiler.nodes.calc.IsNullNode;
351 import org.graalvm.compiler.nodes.calc.LeftShiftNode;
352 import org.graalvm.compiler.nodes.calc.MulNode;
353 import org.graalvm.compiler.nodes.calc.NarrowNode;
354 import org.graalvm.compiler.nodes.calc.NegateNode;
355 import org.graalvm.compiler.nodes.calc.NormalizeCompareNode;
356 import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
357 import org.graalvm.compiler.nodes.calc.OrNode;
358 import org.graalvm.compiler.nodes.calc.RemNode;
359 import org.graalvm.compiler.nodes.calc.RightShiftNode;
360 import org.graalvm.compiler.nodes.calc.SignExtendNode;
361 import org.graalvm.compiler.nodes.calc.SignedDivNode;
362 import org.graalvm.compiler.nodes.calc.SignedRemNode;
363 import org.graalvm.compiler.nodes.calc.SubNode;
364 import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
365 import org.graalvm.compiler.nodes.calc.XorNode;
366 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
367 import org.graalvm.compiler.nodes.extended.AnchoringNode;
368 import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
369 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode;
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.StateSplitProxyNode;
375 import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
376 import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
377 import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
378 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
379 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
380 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
381 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
382 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo;
383 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
384 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
385 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
386 import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
387 import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin;
388 import org.graalvm.compiler.nodes.java.ArrayLengthNode;
389 import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
390 import org.graalvm.compiler.nodes.java.FinalFieldBarrierNode;
391 import org.graalvm.compiler.nodes.java.InstanceOfNode;
392 import org.graalvm.compiler.nodes.java.LoadFieldNode;
393 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
394 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
395 import org.graalvm.compiler.nodes.java.MonitorEnterNode;
396 import org.graalvm.compiler.nodes.java.MonitorExitNode;
397 import org.graalvm.compiler.nodes.java.MonitorIdNode;
398 import org.graalvm.compiler.nodes.java.NewArrayNode;
399 import org.graalvm.compiler.nodes.java.NewInstanceNode;
400 import org.graalvm.compiler.nodes.java.NewMultiArrayNode;
401 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
402 import org.graalvm.compiler.nodes.java.StoreFieldNode;
403 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
404 import org.graalvm.compiler.nodes.spi.StampProvider;
405 import org.graalvm.compiler.nodes.type.StampTool;
418 import jdk.vm.ci.meta.ConstantPool;
419 import jdk.vm.ci.meta.ConstantReflectionProvider;
420 import jdk.vm.ci.meta.DeoptimizationAction;
421 import jdk.vm.ci.meta.DeoptimizationReason;
422 import jdk.vm.ci.meta.JavaConstant;
423 import jdk.vm.ci.meta.JavaField;
424 import jdk.vm.ci.meta.JavaKind;
425 import jdk.vm.ci.meta.JavaMethod;
426 import jdk.vm.ci.meta.JavaType;
427 import jdk.vm.ci.meta.JavaTypeProfile;
428 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
429 import jdk.vm.ci.meta.LineNumberTable;
430 import jdk.vm.ci.meta.MetaAccessProvider;
431 import jdk.vm.ci.meta.ProfilingInfo;
432 import jdk.vm.ci.meta.RawConstant;
433 import jdk.vm.ci.meta.ResolvedJavaField;
434 import jdk.vm.ci.meta.ResolvedJavaMethod;
435 import jdk.vm.ci.meta.ResolvedJavaType;
436 import jdk.vm.ci.meta.Signature;
437 import jdk.vm.ci.meta.TriState;
438
439 /**
440 * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
441 */
442 public class BytecodeParser implements GraphBuilderContext {
443
444 /**
445 * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
446 * to trace the bytecode instructions as they are parsed.
447 */
448 public static final int TRACELEVEL_INSTRUCTIONS = 1;
449
450 /**
451 * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
452 * to trace the frame state before each bytecode instruction as it is parsed.
453 */
454 public static final int TRACELEVEL_STATE = 2;
455
456 /**
457 * Meters the number of actual bytecodes parsed.
1019
1020 /**
1021 * @param type
1022 */
1023 protected void handleUnresolvedExceptionType(JavaType type) {
1024 assert !graphBuilderConfig.unresolvedIsError();
1025 DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1026 deopt.updateNodeSourcePosition(() -> createBytecodePosition());
1027 }
1028
1029 /**
1030 * @param javaMethod
1031 * @param invokeKind
1032 */
1033 protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) {
1034 assert !graphBuilderConfig.unresolvedIsError();
1035 DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1036 deopt.updateNodeSourcePosition(() -> createBytecodePosition());
1037 }
1038
1039 private AbstractBeginNode handleException(ValueNode exceptionObject, int bci) {
1040 assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci";
1041 debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci)));
1042
1043 FrameStateBuilder dispatchState = frameState.copy();
1044 dispatchState.clearStack();
1045
1046 AbstractBeginNode dispatchBegin;
1047 if (exceptionObject == null) {
1048 ExceptionObjectNode newExceptionObject = graph.add(new ExceptionObjectNode(metaAccess));
1049 dispatchBegin = newExceptionObject;
1050 dispatchState.push(JavaKind.Object, dispatchBegin);
1051 dispatchState.setRethrowException(true);
1052 newExceptionObject.setStateAfter(dispatchState.create(bci, newExceptionObject));
1053 } else {
1054 dispatchBegin = graph.add(new BeginNode());
1055 dispatchState.push(JavaKind.Object, exceptionObject);
1056 dispatchState.setRethrowException(true);
1057 }
1058 this.controlFlowSplit = true;
1059 FixedWithNextNode finishedDispatch = finishInstruction(dispatchBegin, dispatchState);
1060
1061 createHandleExceptionTarget(finishedDispatch, bci, dispatchState);
1062
1063 return dispatchBegin;
1064 }
1065
1066 protected void createHandleExceptionTarget(FixedWithNextNode finishedDispatch, int bci, FrameStateBuilder dispatchState) {
1067 BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
1068 /*
1069 * The exception dispatch block is always for the last bytecode of a block, so if we are not
1070 * at the endBci yet, there is no exception handler for this bci and we can unwind
1071 * immediately.
1072 */
1073 if (bci != currentBlock.endBci || dispatchBlock == null) {
1074 dispatchBlock = blockMap.getUnwindBlock();
1075 }
1076
1077 FixedNode target = createTarget(dispatchBlock, dispatchState);
1078 finishedDispatch.setNext(target);
1079 }
1080
1081 protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, JavaKind kind) {
1082 return LoadIndexedNode.create(graph.getAssumptions(), array, index, kind, metaAccess, constantReflection);
1094 return SubNode.create(x, y);
1095 }
1096
1097 protected ValueNode genIntegerMul(ValueNode x, ValueNode y) {
1098 return MulNode.create(x, y);
1099 }
1100
1101 protected ValueNode genFloatAdd(ValueNode x, ValueNode y) {
1102 return AddNode.create(x, y);
1103 }
1104
1105 protected ValueNode genFloatSub(ValueNode x, ValueNode y) {
1106 return SubNode.create(x, y);
1107 }
1108
1109 protected ValueNode genFloatMul(ValueNode x, ValueNode y) {
1110 return MulNode.create(x, y);
1111 }
1112
1113 protected ValueNode genFloatDiv(ValueNode x, ValueNode y) {
1114 return DivNode.create(x, y);
1115 }
1116
1117 protected ValueNode genFloatRem(ValueNode x, ValueNode y) {
1118 return new RemNode(x, y);
1119 }
1120
1121 protected ValueNode genIntegerDiv(ValueNode x, ValueNode y) {
1122 return new SignedDivNode(x, y);
1123 }
1124
1125 protected ValueNode genIntegerRem(ValueNode x, ValueNode y) {
1126 return new SignedRemNode(x, y);
1127 }
1128
1129 protected ValueNode genNegateOp(ValueNode x) {
1130 return NegateNode.create(x);
1131 }
1132
1133 protected ValueNode genLeftShift(ValueNode x, ValueNode y) {
1134 return LeftShiftNode.create(x, y);
1198 }
1199
1200 protected ValueNode genUnique(ValueNode x) {
1201 return graph.addOrUniqueWithInputs(x);
1202 }
1203
1204 protected LogicNode genUnique(LogicNode x) {
1205 return graph.addOrUniqueWithInputs(x);
1206 }
1207
1208 protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) {
1209 return new IfNode(condition, falseSuccessor, trueSuccessor, d);
1210 }
1211
1212 protected void genThrow() {
1213 genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
1214
1215 ValueNode exception = frameState.pop(JavaKind.Object);
1216 FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
1217 ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck));
1218 lastInstr.setNext(handleException(nonNullException, bci()));
1219 }
1220
1221 protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
1222 return InstanceOfNode.create(type, object);
1223 }
1224
1225 protected AnchoringNode createAnchor(JavaTypeProfile profile) {
1226 if (profile == null || profile.getNotRecordedProbability() > 0.0) {
1227 return null;
1228 } else {
1229 return append(new ValueAnchorNode(null));
1230 }
1231 }
1232
1233 protected LogicNode createInstanceOf(TypeReference type, ValueNode object, JavaTypeProfile profile) {
1234 return InstanceOfNode.create(type, object, profile, createAnchor(profile));
1235 }
1236
1237 protected LogicNode createInstanceOfAllowNull(TypeReference type, ValueNode object, JavaTypeProfile profile) {
1238 return InstanceOfNode.createAllowNull(type, object, profile, createAnchor(profile));
1258 StampPair stamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, field.getType(), false);
1259 if (stamp == null) {
1260 return LoadFieldNode.create(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(),
1261 getAssumptions(), receiver, field, false, false);
1262 } else {
1263 return LoadFieldNode.createOverrideStamp(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(),
1264 stamp, receiver, field, false, false);
1265 }
1266 }
1267
1268 protected StateSplitProxyNode genVolatileFieldReadProxy(ValueNode fieldRead) {
1269 return new StateSplitProxyNode(fieldRead);
1270 }
1271
1272 protected ValueNode emitExplicitNullCheck(ValueNode receiver) {
1273 if (StampTool.isPointerNonNull(receiver.stamp())) {
1274 return receiver;
1275 }
1276 BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
1277 AbstractBeginNode falseSucc = graph.add(new BeginNode());
1278 ValueNode nonNullReceiver = graph.addOrUnique(PiNode.create(receiver, objectNonNull(), falseSucc));
1279 append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY));
1280 lastInstr = falseSucc;
1281
1282 exception.setStateAfter(createFrameState(bci(), exception));
1283 exception.setNext(handleException(exception, bci()));
1284 EXPLICIT_EXCEPTIONS.increment(debug);
1285 return nonNullReceiver;
1286 }
1287
1288 protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
1289 AbstractBeginNode trueSucc = graph.add(new BeginNode());
1290 BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
1291 append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length)), trueSucc, exception, FAST_PATH_PROBABILITY));
1292 lastInstr = trueSucc;
1293
1294 exception.setStateAfter(createFrameState(bci(), exception));
1295 exception.setNext(handleException(exception, bci()));
1296 }
1297
1298 protected ValueNode genArrayLength(ValueNode x) {
1299 return ArrayLengthNode.create(x, constantReflection);
1300 }
1301
1302 protected void genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value) {
1303 StoreFieldNode storeFieldNode = new StoreFieldNode(receiver, field, value);
1304 append(storeFieldNode);
1305 storeFieldNode.setStateAfter(this.createFrameState(stream.nextBCI(), storeFieldNode));
1306 }
1307
1308 /**
1309 * Ensure that concrete classes are at least linked before generating an invoke. Interfaces may
1310 * never be linked so simply return true for them.
1311 *
1312 * @param target
1313 * @return true if the declared holder is an interface or is linked
1314 */
1315 private static boolean callTargetIsResolved(JavaMethod target) {
1515 public JavaType getInvokeReturnType() {
1516 return currentInvoke == null ? null : currentInvoke.returnType;
1517 }
1518
1519 private boolean forceInliningEverything;
1520
1521 @Override
1522 public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) {
1523 boolean previous = forceInliningEverything;
1524 forceInliningEverything = previous || inlineEverything;
1525 try {
1526 appendInvoke(invokeKind, targetMethod, args);
1527 } finally {
1528 forceInliningEverything = previous;
1529 }
1530 }
1531
1532 @Override
1533 public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
1534 BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1535 boolean withExceptionEdge = intrinsicCallSiteParser == null ? !omitInvokeExceptionEdge(null) : !intrinsicCallSiteParser.omitInvokeExceptionEdge(null);
1536 createNonInlinedInvoke(withExceptionEdge, bci(), callTarget, resultType);
1537 }
1538
1539 protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
1540 ResolvedJavaMethod targetMethod = initialTargetMethod;
1541 InvokeKind invokeKind = initialInvokeKind;
1542 if (initialInvokeKind.isIndirect()) {
1543 ResolvedJavaType contextType = this.frameState.getMethod().getDeclaringClass();
1544 ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(initialInvokeKind, args[0], initialTargetMethod, contextType);
1545 if (specialCallTarget != null) {
1546 invokeKind = InvokeKind.Special;
1547 targetMethod = specialCallTarget;
1548 }
1549 }
1550
1551 JavaKind resultType = targetMethod.getSignature().getReturnKind();
1552 if (!parsingIntrinsic() && DeoptALot.getValue(options)) {
1553 append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
1554 frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, graph));
1555 return null;
1556 }
1586 if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) {
1587 if (TraceParserPlugins.getValue(options)) {
1588 traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
1589 }
1590 return null;
1591 }
1592 }
1593 if (invokeKind.isDirect()) {
1594
1595 inlineInfo = tryInline(args, targetMethod);
1596 if (inlineInfo == SUCCESSFULLY_INLINED) {
1597 return null;
1598 }
1599 }
1600 } finally {
1601 currentInvoke = null;
1602 }
1603
1604 int invokeBci = bci();
1605 JavaTypeProfile profile = getProfileForInvoke(invokeKind);
1606 boolean withExceptionEdge = !omitInvokeExceptionEdge(inlineInfo);
1607 boolean partialIntrinsicExit = false;
1608 if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
1609 partialIntrinsicExit = true;
1610 ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod();
1611 BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1612 if (intrinsicCallSiteParser != null) {
1613 // When exiting a partial intrinsic, the invoke to the original
1614 // must use the same context as the call to the intrinsic.
1615 invokeBci = intrinsicCallSiteParser.bci();
1616 profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind);
1617 withExceptionEdge = !intrinsicCallSiteParser.omitInvokeExceptionEdge(inlineInfo);
1618 } else {
1619 // We are parsing the intrinsic for the root compilation or for inlining,
1620 // This call is a partial intrinsic exit, and we do not have profile information
1621 // for this callsite. We also have to assume that the call needs an exception
1622 // edge. Finally, we know that this intrinsic is parsed for late inlining,
1623 // so the bci must be set to unknown, so that the inliner patches it later.
1624 assert intrinsicContext.isPostParseInlined();
1625 invokeBci = BytecodeFrame.UNKNOWN_BCI;
1626 profile = null;
1627 withExceptionEdge = graph.method().getAnnotation(Snippet.class) == null;
1628 }
1629
1630 if (originalMethod.isStatic()) {
1631 invokeKind = InvokeKind.Static;
1632 } else {
1633 // The original call to the intrinsic must have been devirtualized
1634 // otherwise we wouldn't be here.
1635 invokeKind = InvokeKind.Special;
1636 }
1637 Signature sig = originalMethod.getSignature();
1638 returnType = sig.getReturnType(method.getDeclaringClass());
1639 resultType = sig.getReturnKind();
1640 assert checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
1641 targetMethod = originalMethod;
1642 }
1643 Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
1644 if (partialIntrinsicExit) {
1645 // This invoke must never be later inlined as it might select the intrinsic graph.
1646 // Until there is a mechanism to guarantee that any late inlining will not select
1647 // the intrinsic graph, prevent this invoke from being inlined.
1648 invoke.setUseForInlining(false);
1649 }
1650 return invoke;
1651 }
1652
1653 /**
1654 * Checks that the class of the receiver of an {@link Bytecodes#INVOKESPECIAL} in a method
1655 * declared in an interface (i.e., a default method) is assignable to the interface. If not,
1656 * then deoptimize so that the interpreter can throw an {@link IllegalAccessError}.
1657 *
1658 * This is a check not performed by the verifier and so must be performed at runtime.
1659 *
1660 * @param args arguments to an {@link Bytecodes#INVOKESPECIAL} implementing a direct call to a
1661 * method in a super class
1662 */
1663 protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) {
1681 return null;
1682 }
1683
1684 /**
1685 * A partial intrinsic exits by (effectively) calling the intrinsified method. This call must
1686 * use exactly the arguments to the call being intrinsified.
1687 *
1688 * @param originalArgs arguments of original call to intrinsified method
1689 * @param recursiveArgs arguments of recursive call to intrinsified method
1690 */
1691 private static boolean checkPartialIntrinsicExit(ValueNode[] originalArgs, ValueNode[] recursiveArgs) {
1692 if (originalArgs != null) {
1693 for (int i = 0; i < originalArgs.length; i++) {
1694 ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]);
1695 ValueNode icArg = GraphUtil.unproxify(originalArgs[i]);
1696 assert arg == icArg : String.format("argument %d of call denoting partial intrinsic exit should be %s, not %s", i, icArg, arg);
1697 }
1698 } else {
1699 for (int i = 0; i < recursiveArgs.length; i++) {
1700 ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]);
1701 assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s", i,
1702 ParameterNode.class.getSimpleName(), i, arg);
1703 }
1704 }
1705 return true;
1706 }
1707
1708 protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod,
1709 InvokeKind invokeKind, JavaKind resultType, JavaType returnType, JavaTypeProfile profile) {
1710
1711 StampPair returnStamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, returnType, false);
1712 if (returnStamp == null) {
1713 returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false);
1714 }
1715
1716 MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile));
1717 Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, callTarget, resultType);
1718
1719 for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
1720 plugin.notifyNotInlined(this, targetMethod, invoke);
1721 }
1722
1723 return invoke;
1724 }
1725
1726 protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
1727 if (!withExceptionEdge) {
1728 return createInvoke(invokeBci, callTarget, resultType);
1729 } else {
1730 Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType);
1731 AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any()));
1732 invoke.setNext(beginNode);
1733 lastInstr = beginNode;
1734 return invoke;
1735 }
1736 }
1737
1738 /**
1739 * If the method returns true, the invocation of the given {@link MethodCallTargetNode call
1740 * target} does not need an exception edge.
1741 */
1742 protected boolean omitInvokeExceptionEdge(InlineInfo lastInlineInfo) {
1743 if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) {
1744 return false;
1745 } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) {
1746 return true;
1747 } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) {
1748 return false;
1749 } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) {
1750 return false;
1751 } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) {
1752 return true;
1753 } else {
1754 assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile;
1755 // be conservative if information was not recorded (could result in endless
1756 // recompiles otherwise)
1757 if (!StressInvokeWithExceptionNode.getValue(options)) {
1758 if (optimisticOpts.useExceptionProbability(getOptions())) {
1759 if (profilingInfo != null) {
1760 TriState exceptionSeen = profilingInfo.getExceptionSeen(bci());
1761 if (exceptionSeen == TriState.FALSE) {
1762 return true;
1763 }
1764 }
1765 }
1766 }
1767 return false;
1768 }
1769 }
1770
1771 /**
1772 * Contains all the assertion checking logic around the application of an
1773 * {@link InvocationPlugin}. This class is only loaded when assertions are enabled.
1774 */
1775 class InvocationPluginAssertions {
1776 final InvocationPlugin plugin;
1777 final ValueNode[] args;
1778 final ResolvedJavaMethod targetMethod;
1779 final JavaKind resultType;
1780 final int beforeStackSize;
1781 final boolean needsNullCheck;
1782 final int nodeCount;
1783 final Mark mark;
1784
1785 InvocationPluginAssertions(InvocationPlugin plugin, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) {
1786 guarantee(Assertions.assertionsEnabled(), "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName());
1787 this.plugin = plugin;
1870 ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass());
1871 if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) {
1872 assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass());
1873 Mark mark = graph.getMark();
1874 FixedWithNextNode currentLastInstr = lastInstr;
1875 ValueNode nonNullReceiver = pluginReceiver.get();
1876 Stamp methodStamp = stampProvider.createMethodStamp();
1877 LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
1878 LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
1879 ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
1880 LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected));
1881
1882 JavaTypeProfile profile = null;
1883 if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
1884 profile = profilingInfo.getTypeProfile(bci());
1885 if (profile != null) {
1886 JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
1887 if (newProfile != profile) {
1888 if (newProfile.getTypes().length == 0) {
1889 // All profiled types select the intrinsic so
1890 // emit a fixed guard instead of a if-then-else.
1891 lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
1892 return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
1893 }
1894 } else {
1895 // No profiled types select the intrinsic so emit a virtual call
1896 return null;
1897 }
1898 profile = newProfile;
1899 }
1900 }
1901
1902 AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
1903 AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
1904 append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY));
1905 lastInstr = intrinsicBranch;
1906 return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
1907 } else {
1908 // Receiver selects an overriding method so emit a virtual call
1909 return null;
1910 }
1949 */
1950 protected void afterInvocationPluginExecution(boolean pluginHandledInvoke, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard,
1951 InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
1952 assert assertions.check(pluginHandledInvoke);
1953 if (intrinsicGuard != null) {
1954 if (pluginHandledInvoke) {
1955 if (intrinsicGuard.nonIntrinsicBranch != null) {
1956 // Intrinsic emitted: emit a virtual call to the target method and
1957 // merge it with the intrinsic branch
1958 EndNode intrinsicEnd = append(new EndNode());
1959
1960 FrameStateBuilder intrinsicState = null;
1961 FrameStateBuilder nonIntrinisicState = null;
1962 if (resultType != JavaKind.Void) {
1963 intrinsicState = frameState.copy();
1964 frameState.pop(resultType);
1965 nonIntrinisicState = frameState;
1966 }
1967
1968 lastInstr = intrinsicGuard.nonIntrinsicBranch;
1969 createNonInlinedInvoke(omitInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
1970
1971 EndNode nonIntrinsicEnd = append(new EndNode());
1972 AbstractMergeNode mergeNode = graph.add(new MergeNode());
1973
1974 mergeNode.addForwardEnd(intrinsicEnd);
1975 if (intrinsicState != null) {
1976 intrinsicState.merge(mergeNode, nonIntrinisicState);
1977 frameState = intrinsicState;
1978 }
1979 mergeNode.addForwardEnd(nonIntrinsicEnd);
1980 mergeNode.setStateAfter(frameState.create(stream.nextBCI(), mergeNode));
1981
1982 lastInstr = mergeNode;
1983 }
1984 } else {
1985 // Intrinsic was not applied: remove intrinsic guard
1986 // and restore the original receiver node in the arguments array
1987 intrinsicGuard.lastInstr.setNext(null);
1988 GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
1989 lastInstr = intrinsicGuard.lastInstr;
2286 frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue);
2287 }
2288 if (returnMergeNode != null) {
2289 returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode));
2290 lastInstr = finishInstruction(returnMergeNode, frameState);
2291 }
2292 }
2293 /*
2294 * Propagate any side effects into the caller when parsing intrinsics.
2295 */
2296 if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
2297 for (StateSplit sideEffect : parser.frameState.sideEffects()) {
2298 frameState.addSideEffect(sideEffect);
2299 }
2300 }
2301
2302 FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
2303 if (calleeBeforeUnwindNode != null) {
2304 ValueNode calleeUnwindValue = parser.getUnwindValue();
2305 assert calleeUnwindValue != null;
2306 calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
2307 }
2308 }
2309 }
2310
2311 public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) {
2312 return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, profile);
2313 }
2314
2315 protected InvokeNode createInvoke(int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
2316 InvokeNode invoke = append(new InvokeNode(callTarget, invokeBci));
2317 frameState.pushReturn(resultType, invoke);
2318 invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
2319 return invoke;
2320 }
2321
2322 protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
2323 if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
2324 /*
2325 * Clear non-live locals early so that the exception handler entry gets the cleared
2326 * state.
2327 */
2328 frameState.clearNonLiveLocals(currentBlock, liveness, false);
2329 }
2330
2331 AbstractBeginNode exceptionEdge = handleException(null, bci());
2332 InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci));
2333 frameState.pushReturn(resultType, invoke);
2334 invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
2335 return invoke;
2336 }
2337
2338 protected void genReturn(ValueNode returnVal, JavaKind returnKind) {
2339 if (parsingIntrinsic() && returnVal != null) {
2340 if (returnVal instanceof StateSplit) {
2341 StateSplit stateSplit = (StateSplit) returnVal;
2342 FrameState stateAfter = stateSplit.stateAfter();
2343 if (stateSplit.hasSideEffect()) {
2344 assert stateSplit != null;
2345 if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
2346 assert stateAfter.usages().count() == 1;
2347 assert stateAfter.usages().first() == stateSplit;
2348 stateAfter.replaceAtUsages(graph.add(new FrameState(BytecodeFrame.AFTER_BCI, returnVal)));
2349 GraphUtil.killWithUnusedFloatingInputs(stateAfter);
2350 } else {
2351 /*
2352 * This must be the return value from within a partial intrinsification.
2353 */
2354 assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci);
2355 }
2356 } else {
2357 assert stateAfter == null;
2358 }
2359 }
2360 }
2361
2362 frameState.setRethrowException(false);
2363 frameState.clearStack();
2364 beforeReturn(returnVal, returnKind);
2365 if (parent == null) {
2366 append(new ReturnNode(returnVal));
2367 } else {
2368 if (returnDataList == null) {
2369 returnDataList = new ArrayList<>();
2370 }
2371 returnDataList.add(new ReturnToCallerData(returnVal, lastInstr));
2372 lastInstr = null;
2373 }
2374 }
2375
2376 private void beforeReturn(ValueNode x, JavaKind kind) {
2377 if (graph.method() != null && graph.method().isJavaLangObjectInit()) {
2378 /*
2379 * Get the receiver from the initial state since bytecode rewriting could do arbitrary
2380 * things to the state of the locals.
2381 */
2382 ValueNode receiver = graph.start().stateAfter().localAt(0);
2383 assert receiver != null && receiver.getStackKind() == JavaKind.Object;
2384 if (RegisterFinalizerNode.mayHaveFinalizer(receiver, graph.getAssumptions())) {
2385 append(new RegisterFinalizerNode(receiver));
2386 }
2387 }
2388 genInfoPointNode(InfopointReason.METHOD_END, x);
2389 if (finalBarrierRequired) {
2390 assert originalReceiver != null;
2391 /*
2392 * When compiling an OSR with a final field store, don't bother tracking the original
2393 * receiver since the receiver cannot be EA'ed.
2394 */
2395 append(new FinalFieldBarrierNode(entryBCI == INVOCATION_ENTRY_BCI ? originalReceiver : null));
2777 synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null);
2778 ValueNode exception = frameState.pop(JavaKind.Object);
2779 append(new UnwindNode(exception));
2780 }
2781
2782 private void synchronizedEpilogue(int bci, ValueNode currentReturnValue, JavaKind currentReturnValueKind) {
2783 if (method.isSynchronized()) {
2784 if (currentReturnValue != null) {
2785 frameState.push(currentReturnValueKind, currentReturnValue);
2786 }
2787 genMonitorExit(methodSynchronizedObject, currentReturnValue, bci);
2788 assert !frameState.rethrowException();
2789 finishPrepare(lastInstr, bci);
2790 }
2791 if (frameState.lockDepth(false) != 0) {
2792 throw bailout("unbalanced monitors: too few exits exiting frame");
2793 }
2794 }
2795
2796 private void createExceptionDispatch(ExceptionDispatchBlock block) {
2797 assert frameState.stackSize() == 1 : frameState;
2798 if (block.handler.isCatchAll()) {
2799 assert block.getSuccessorCount() == 1;
2800 appendGoto(block.getSuccessor(0));
2801 return;
2802 }
2803
2804 JavaType catchType = block.handler.getCatchType();
2805 if (graphBuilderConfig.eagerResolving()) {
2806 catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF);
2807 }
2808 if (catchType instanceof ResolvedJavaType) {
2809 TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType);
2810
2811 if (graphBuilderConfig.getSkippedExceptionTypes() != null) {
2812 for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
2813 if (skippedType.isAssignableFrom(checkedCatchType.getType())) {
2814 BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
2815 ValueNode exception = frameState.stack[0];
2816 FixedNode trueSuccessor = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
|
325 import org.graalvm.compiler.nodes.KillingBeginNode;
326 import org.graalvm.compiler.nodes.LogicConstantNode;
327 import org.graalvm.compiler.nodes.LogicNegationNode;
328 import org.graalvm.compiler.nodes.LogicNode;
329 import org.graalvm.compiler.nodes.LoopBeginNode;
330 import org.graalvm.compiler.nodes.LoopEndNode;
331 import org.graalvm.compiler.nodes.LoopExitNode;
332 import org.graalvm.compiler.nodes.MergeNode;
333 import org.graalvm.compiler.nodes.ParameterNode;
334 import org.graalvm.compiler.nodes.PiNode;
335 import org.graalvm.compiler.nodes.ReturnNode;
336 import org.graalvm.compiler.nodes.StartNode;
337 import org.graalvm.compiler.nodes.StateSplit;
338 import org.graalvm.compiler.nodes.StructuredGraph;
339 import org.graalvm.compiler.nodes.UnwindNode;
340 import org.graalvm.compiler.nodes.ValueNode;
341 import org.graalvm.compiler.nodes.calc.AddNode;
342 import org.graalvm.compiler.nodes.calc.AndNode;
343 import org.graalvm.compiler.nodes.calc.CompareNode;
344 import org.graalvm.compiler.nodes.calc.ConditionalNode;
345 import org.graalvm.compiler.nodes.calc.FloatDivNode;
346 import org.graalvm.compiler.nodes.calc.FloatConvertNode;
347 import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
348 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
349 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
350 import org.graalvm.compiler.nodes.calc.IsNullNode;
351 import org.graalvm.compiler.nodes.calc.LeftShiftNode;
352 import org.graalvm.compiler.nodes.calc.MulNode;
353 import org.graalvm.compiler.nodes.calc.NarrowNode;
354 import org.graalvm.compiler.nodes.calc.NegateNode;
355 import org.graalvm.compiler.nodes.calc.NormalizeCompareNode;
356 import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
357 import org.graalvm.compiler.nodes.calc.OrNode;
358 import org.graalvm.compiler.nodes.calc.RemNode;
359 import org.graalvm.compiler.nodes.calc.RightShiftNode;
360 import org.graalvm.compiler.nodes.calc.SignExtendNode;
361 import org.graalvm.compiler.nodes.calc.SignedDivNode;
362 import org.graalvm.compiler.nodes.calc.SignedRemNode;
363 import org.graalvm.compiler.nodes.calc.SubNode;
364 import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
365 import org.graalvm.compiler.nodes.calc.XorNode;
366 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
367 import org.graalvm.compiler.nodes.extended.AnchoringNode;
368 import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
369 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode;
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.StateSplitProxyNode;
375 import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
376 import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
377 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
378 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
379 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
380 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
381 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo;
382 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
383 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
384 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
385 import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
386 import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
387 import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin;
388 import org.graalvm.compiler.nodes.java.ArrayLengthNode;
389 import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
390 import org.graalvm.compiler.nodes.java.FinalFieldBarrierNode;
391 import org.graalvm.compiler.nodes.java.InstanceOfNode;
392 import org.graalvm.compiler.nodes.java.LoadFieldNode;
393 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
394 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
395 import org.graalvm.compiler.nodes.java.MonitorEnterNode;
396 import org.graalvm.compiler.nodes.java.MonitorExitNode;
397 import org.graalvm.compiler.nodes.java.MonitorIdNode;
398 import org.graalvm.compiler.nodes.java.NewArrayNode;
399 import org.graalvm.compiler.nodes.java.NewInstanceNode;
400 import org.graalvm.compiler.nodes.java.NewMultiArrayNode;
401 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
402 import org.graalvm.compiler.nodes.java.StoreFieldNode;
403 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
404 import org.graalvm.compiler.nodes.spi.StampProvider;
405 import org.graalvm.compiler.nodes.type.StampTool;
418 import jdk.vm.ci.meta.ConstantPool;
419 import jdk.vm.ci.meta.ConstantReflectionProvider;
420 import jdk.vm.ci.meta.DeoptimizationAction;
421 import jdk.vm.ci.meta.DeoptimizationReason;
422 import jdk.vm.ci.meta.JavaConstant;
423 import jdk.vm.ci.meta.JavaField;
424 import jdk.vm.ci.meta.JavaKind;
425 import jdk.vm.ci.meta.JavaMethod;
426 import jdk.vm.ci.meta.JavaType;
427 import jdk.vm.ci.meta.JavaTypeProfile;
428 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
429 import jdk.vm.ci.meta.LineNumberTable;
430 import jdk.vm.ci.meta.MetaAccessProvider;
431 import jdk.vm.ci.meta.ProfilingInfo;
432 import jdk.vm.ci.meta.RawConstant;
433 import jdk.vm.ci.meta.ResolvedJavaField;
434 import jdk.vm.ci.meta.ResolvedJavaMethod;
435 import jdk.vm.ci.meta.ResolvedJavaType;
436 import jdk.vm.ci.meta.Signature;
437 import jdk.vm.ci.meta.TriState;
438 import org.graalvm.compiler.core.common.type.IntegerStamp;
439
440 /**
441 * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
442 */
443 public class BytecodeParser implements GraphBuilderContext {
444
445 /**
446 * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
447 * to trace the bytecode instructions as they are parsed.
448 */
449 public static final int TRACELEVEL_INSTRUCTIONS = 1;
450
451 /**
452 * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
453 * to trace the frame state before each bytecode instruction as it is parsed.
454 */
455 public static final int TRACELEVEL_STATE = 2;
456
457 /**
458 * Meters the number of actual bytecodes parsed.
1020
1021 /**
1022 * @param type
1023 */
1024 protected void handleUnresolvedExceptionType(JavaType type) {
1025 assert !graphBuilderConfig.unresolvedIsError();
1026 DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1027 deopt.updateNodeSourcePosition(() -> createBytecodePosition());
1028 }
1029
1030 /**
1031 * @param javaMethod
1032 * @param invokeKind
1033 */
1034 protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) {
1035 assert !graphBuilderConfig.unresolvedIsError();
1036 DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
1037 deopt.updateNodeSourcePosition(() -> createBytecodePosition());
1038 }
1039
1040 private AbstractBeginNode handleException(ValueNode exceptionObject, int bci, boolean deoptimizeOnly) {
1041 assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci";
1042 debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci)));
1043
1044 FrameStateBuilder dispatchState = frameState.copy();
1045 dispatchState.clearStack();
1046
1047 AbstractBeginNode dispatchBegin;
1048 if (exceptionObject == null) {
1049 ExceptionObjectNode newExceptionObject = graph.add(new ExceptionObjectNode(metaAccess));
1050 dispatchBegin = newExceptionObject;
1051 dispatchState.push(JavaKind.Object, dispatchBegin);
1052 dispatchState.setRethrowException(true);
1053 newExceptionObject.setStateAfter(dispatchState.create(bci, newExceptionObject));
1054 } else {
1055 dispatchBegin = graph.add(new BeginNode());
1056 dispatchState.push(JavaKind.Object, exceptionObject);
1057 dispatchState.setRethrowException(true);
1058 }
1059 this.controlFlowSplit = true;
1060 FixedWithNextNode finishedDispatch = finishInstruction(dispatchBegin, dispatchState);
1061
1062 if (deoptimizeOnly) {
1063 DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
1064 dispatchBegin.setNext(BeginNode.begin(deoptimizeNode));
1065 } else {
1066 createHandleExceptionTarget(finishedDispatch, bci, dispatchState);
1067 }
1068 return dispatchBegin;
1069 }
1070
1071 protected void createHandleExceptionTarget(FixedWithNextNode finishedDispatch, int bci, FrameStateBuilder dispatchState) {
1072 BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
1073 /*
1074 * The exception dispatch block is always for the last bytecode of a block, so if we are not
1075 * at the endBci yet, there is no exception handler for this bci and we can unwind
1076 * immediately.
1077 */
1078 if (bci != currentBlock.endBci || dispatchBlock == null) {
1079 dispatchBlock = blockMap.getUnwindBlock();
1080 }
1081
1082 FixedNode target = createTarget(dispatchBlock, dispatchState);
1083 finishedDispatch.setNext(target);
1084 }
1085
1086 protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, JavaKind kind) {
1087 return LoadIndexedNode.create(graph.getAssumptions(), array, index, kind, metaAccess, constantReflection);
1099 return SubNode.create(x, y);
1100 }
1101
1102 protected ValueNode genIntegerMul(ValueNode x, ValueNode y) {
1103 return MulNode.create(x, y);
1104 }
1105
1106 protected ValueNode genFloatAdd(ValueNode x, ValueNode y) {
1107 return AddNode.create(x, y);
1108 }
1109
1110 protected ValueNode genFloatSub(ValueNode x, ValueNode y) {
1111 return SubNode.create(x, y);
1112 }
1113
1114 protected ValueNode genFloatMul(ValueNode x, ValueNode y) {
1115 return MulNode.create(x, y);
1116 }
1117
1118 protected ValueNode genFloatDiv(ValueNode x, ValueNode y) {
1119 return FloatDivNode.create(x, y);
1120 }
1121
1122 protected ValueNode genFloatRem(ValueNode x, ValueNode y) {
1123 return new RemNode(x, y);
1124 }
1125
1126 protected ValueNode genIntegerDiv(ValueNode x, ValueNode y) {
1127 return new SignedDivNode(x, y);
1128 }
1129
1130 protected ValueNode genIntegerRem(ValueNode x, ValueNode y) {
1131 return new SignedRemNode(x, y);
1132 }
1133
1134 protected ValueNode genNegateOp(ValueNode x) {
1135 return NegateNode.create(x);
1136 }
1137
1138 protected ValueNode genLeftShift(ValueNode x, ValueNode y) {
1139 return LeftShiftNode.create(x, y);
1203 }
1204
1205 protected ValueNode genUnique(ValueNode x) {
1206 return graph.addOrUniqueWithInputs(x);
1207 }
1208
1209 protected LogicNode genUnique(LogicNode x) {
1210 return graph.addOrUniqueWithInputs(x);
1211 }
1212
1213 protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) {
1214 return new IfNode(condition, falseSuccessor, trueSuccessor, d);
1215 }
1216
1217 protected void genThrow() {
1218 genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
1219
1220 ValueNode exception = frameState.pop(JavaKind.Object);
1221 FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
1222 ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck));
1223 lastInstr.setNext(handleException(nonNullException, bci(), false));
1224 }
1225
1226 protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
1227 return InstanceOfNode.create(type, object);
1228 }
1229
1230 protected AnchoringNode createAnchor(JavaTypeProfile profile) {
1231 if (profile == null || profile.getNotRecordedProbability() > 0.0) {
1232 return null;
1233 } else {
1234 return append(new ValueAnchorNode(null));
1235 }
1236 }
1237
1238 protected LogicNode createInstanceOf(TypeReference type, ValueNode object, JavaTypeProfile profile) {
1239 return InstanceOfNode.create(type, object, profile, createAnchor(profile));
1240 }
1241
1242 protected LogicNode createInstanceOfAllowNull(TypeReference type, ValueNode object, JavaTypeProfile profile) {
1243 return InstanceOfNode.createAllowNull(type, object, profile, createAnchor(profile));
1263 StampPair stamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, field.getType(), false);
1264 if (stamp == null) {
1265 return LoadFieldNode.create(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(),
1266 getAssumptions(), receiver, field, false, false);
1267 } else {
1268 return LoadFieldNode.createOverrideStamp(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(),
1269 stamp, receiver, field, false, false);
1270 }
1271 }
1272
1273 protected StateSplitProxyNode genVolatileFieldReadProxy(ValueNode fieldRead) {
1274 return new StateSplitProxyNode(fieldRead);
1275 }
1276
1277 protected ValueNode emitExplicitNullCheck(ValueNode receiver) {
1278 if (StampTool.isPointerNonNull(receiver.stamp())) {
1279 return receiver;
1280 }
1281 BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
1282 AbstractBeginNode falseSucc = graph.add(new BeginNode());
1283 ValueNode nonNullReceiver = graph.addOrUniqueWithInputs(PiNode.create(receiver, objectNonNull(), falseSucc));
1284 append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY));
1285 lastInstr = falseSucc;
1286
1287 exception.setStateAfter(createFrameState(bci(), exception));
1288 exception.setNext(handleException(exception, bci(), false));
1289 EXPLICIT_EXCEPTIONS.increment(debug);
1290 return nonNullReceiver;
1291 }
1292
1293 protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
1294 AbstractBeginNode trueSucc = graph.add(new BeginNode());
1295 BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
1296 append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length)), trueSucc, exception, FAST_PATH_PROBABILITY));
1297 lastInstr = trueSucc;
1298
1299 exception.setStateAfter(createFrameState(bci(), exception));
1300 exception.setNext(handleException(exception, bci(), false));
1301 }
1302
1303 protected ValueNode genArrayLength(ValueNode x) {
1304 return ArrayLengthNode.create(x, constantReflection);
1305 }
1306
1307 protected void genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value) {
1308 StoreFieldNode storeFieldNode = new StoreFieldNode(receiver, field, value);
1309 append(storeFieldNode);
1310 storeFieldNode.setStateAfter(this.createFrameState(stream.nextBCI(), storeFieldNode));
1311 }
1312
1313 /**
1314 * Ensure that concrete classes are at least linked before generating an invoke. Interfaces may
1315 * never be linked so simply return true for them.
1316 *
1317 * @param target
1318 * @return true if the declared holder is an interface or is linked
1319 */
1320 private static boolean callTargetIsResolved(JavaMethod target) {
1520 public JavaType getInvokeReturnType() {
1521 return currentInvoke == null ? null : currentInvoke.returnType;
1522 }
1523
1524 private boolean forceInliningEverything;
1525
1526 @Override
1527 public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) {
1528 boolean previous = forceInliningEverything;
1529 forceInliningEverything = previous || inlineEverything;
1530 try {
1531 appendInvoke(invokeKind, targetMethod, args);
1532 } finally {
1533 forceInliningEverything = previous;
1534 }
1535 }
1536
1537 @Override
1538 public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
1539 BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1540 ExceptionEdgeAction exceptionEdgeAction = intrinsicCallSiteParser == null ? getActionForInvokeExceptionEdge(null) : intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null);
1541 createNonInlinedInvoke(exceptionEdgeAction, bci(), callTarget, resultType);
1542 }
1543
1544 protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
1545 ResolvedJavaMethod targetMethod = initialTargetMethod;
1546 InvokeKind invokeKind = initialInvokeKind;
1547 if (initialInvokeKind.isIndirect()) {
1548 ResolvedJavaType contextType = this.frameState.getMethod().getDeclaringClass();
1549 ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(initialInvokeKind, args[0], initialTargetMethod, contextType);
1550 if (specialCallTarget != null) {
1551 invokeKind = InvokeKind.Special;
1552 targetMethod = specialCallTarget;
1553 }
1554 }
1555
1556 JavaKind resultType = targetMethod.getSignature().getReturnKind();
1557 if (!parsingIntrinsic() && DeoptALot.getValue(options)) {
1558 append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
1559 frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, graph));
1560 return null;
1561 }
1591 if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) {
1592 if (TraceParserPlugins.getValue(options)) {
1593 traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
1594 }
1595 return null;
1596 }
1597 }
1598 if (invokeKind.isDirect()) {
1599
1600 inlineInfo = tryInline(args, targetMethod);
1601 if (inlineInfo == SUCCESSFULLY_INLINED) {
1602 return null;
1603 }
1604 }
1605 } finally {
1606 currentInvoke = null;
1607 }
1608
1609 int invokeBci = bci();
1610 JavaTypeProfile profile = getProfileForInvoke(invokeKind);
1611 ExceptionEdgeAction edgeAction = getActionForInvokeExceptionEdge(inlineInfo);
1612 boolean partialIntrinsicExit = false;
1613 if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
1614 partialIntrinsicExit = true;
1615 ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod();
1616 BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1617 if (intrinsicCallSiteParser != null) {
1618 // When exiting a partial intrinsic, the invoke to the original
1619 // must use the same context as the call to the intrinsic.
1620 invokeBci = intrinsicCallSiteParser.bci();
1621 profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind);
1622 edgeAction = intrinsicCallSiteParser.getActionForInvokeExceptionEdge(inlineInfo);
1623 } else {
1624 // We are parsing the intrinsic for the root compilation or for inlining,
1625 // This call is a partial intrinsic exit, and we do not have profile information
1626 // for this callsite. We also have to assume that the call needs an exception
1627 // edge. Finally, we know that this intrinsic is parsed for late inlining,
1628 // so the bci must be set to unknown, so that the inliner patches it later.
1629 assert intrinsicContext.isPostParseInlined();
1630 invokeBci = BytecodeFrame.UNKNOWN_BCI;
1631 profile = null;
1632 edgeAction = graph.method().getAnnotation(Snippet.class) == null ? ExceptionEdgeAction.INCLUDE_AND_HANDLE : ExceptionEdgeAction.OMIT;
1633 }
1634
1635 if (originalMethod.isStatic()) {
1636 invokeKind = InvokeKind.Static;
1637 } else {
1638 // The original call to the intrinsic must have been devirtualized
1639 // otherwise we wouldn't be here.
1640 invokeKind = InvokeKind.Special;
1641 }
1642 Signature sig = originalMethod.getSignature();
1643 returnType = sig.getReturnType(method.getDeclaringClass());
1644 resultType = sig.getReturnKind();
1645 assert intrinsicContext.allowPartialIntrinsicArgumentMismatch() || checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
1646 targetMethod = originalMethod;
1647 }
1648 Invoke invoke = createNonInlinedInvoke(edgeAction, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
1649 if (partialIntrinsicExit) {
1650 // This invoke must never be later inlined as it might select the intrinsic graph.
1651 // Until there is a mechanism to guarantee that any late inlining will not select
1652 // the intrinsic graph, prevent this invoke from being inlined.
1653 invoke.setUseForInlining(false);
1654 }
1655 return invoke;
1656 }
1657
1658 /**
1659 * Checks that the class of the receiver of an {@link Bytecodes#INVOKESPECIAL} in a method
1660 * declared in an interface (i.e., a default method) is assignable to the interface. If not,
1661 * then deoptimize so that the interpreter can throw an {@link IllegalAccessError}.
1662 *
1663 * This is a check not performed by the verifier and so must be performed at runtime.
1664 *
1665 * @param args arguments to an {@link Bytecodes#INVOKESPECIAL} implementing a direct call to a
1666 * method in a super class
1667 */
1668 protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) {
1686 return null;
1687 }
1688
1689 /**
1690 * A partial intrinsic exits by (effectively) calling the intrinsified method. This call must
1691 * use exactly the arguments to the call being intrinsified.
1692 *
1693 * @param originalArgs arguments of original call to intrinsified method
1694 * @param recursiveArgs arguments of recursive call to intrinsified method
1695 */
1696 private static boolean checkPartialIntrinsicExit(ValueNode[] originalArgs, ValueNode[] recursiveArgs) {
1697 if (originalArgs != null) {
1698 for (int i = 0; i < originalArgs.length; i++) {
1699 ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]);
1700 ValueNode icArg = GraphUtil.unproxify(originalArgs[i]);
1701 assert arg == icArg : String.format("argument %d of call denoting partial intrinsic exit should be %s, not %s", i, icArg, arg);
1702 }
1703 } else {
1704 for (int i = 0; i < recursiveArgs.length; i++) {
1705 ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]);
1706 assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s",
1707 i, ParameterNode.class.getSimpleName(), i, arg);
1708 }
1709 }
1710 return true;
1711 }
1712
1713 protected Invoke createNonInlinedInvoke(ExceptionEdgeAction exceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod,
1714 InvokeKind invokeKind, JavaKind resultType, JavaType returnType, JavaTypeProfile profile) {
1715
1716 StampPair returnStamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, returnType, false);
1717 if (returnStamp == null) {
1718 returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false);
1719 }
1720
1721 MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile));
1722 Invoke invoke = createNonInlinedInvoke(exceptionEdge, invokeBci, callTarget, resultType);
1723
1724 for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
1725 plugin.notifyNotInlined(this, targetMethod, invoke);
1726 }
1727
1728 return invoke;
1729 }
1730
1731 protected Invoke createNonInlinedInvoke(ExceptionEdgeAction exceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
1732 if (exceptionEdge == ExceptionEdgeAction.OMIT) {
1733 return createInvoke(invokeBci, callTarget, resultType);
1734 } else {
1735 Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType, exceptionEdge);
1736 AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any()));
1737 invoke.setNext(beginNode);
1738 lastInstr = beginNode;
1739 return invoke;
1740 }
1741 }
1742
1743 /**
1744 * Describes what should be done with the exception edge of an invocation. The edge can be
1745 * omitted or included. An included edge can handle the exception or transfer execution to the
1746 * interpreter for handling (deoptimize).
1747 */
1748 protected enum ExceptionEdgeAction {
1749 OMIT,
1750 INCLUDE_AND_HANDLE,
1751 INCLUDE_AND_DEOPTIMIZE
1752 }
1753
1754 protected ExceptionEdgeAction getActionForInvokeExceptionEdge(InlineInfo lastInlineInfo) {
1755 if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) {
1756 return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
1757 } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) {
1758 return ExceptionEdgeAction.OMIT;
1759 } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION) {
1760 return ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE;
1761 } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) {
1762 return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
1763 } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) {
1764 return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
1765 } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) {
1766 return ExceptionEdgeAction.OMIT;
1767 } else {
1768 assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile;
1769 // be conservative if information was not recorded (could result in endless
1770 // recompiles otherwise)
1771 if (!StressInvokeWithExceptionNode.getValue(options)) {
1772 if (optimisticOpts.useExceptionProbability(getOptions())) {
1773 if (profilingInfo != null) {
1774 TriState exceptionSeen = profilingInfo.getExceptionSeen(bci());
1775 if (exceptionSeen == TriState.FALSE) {
1776 return ExceptionEdgeAction.OMIT;
1777 }
1778 }
1779 }
1780 }
1781 return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
1782 }
1783 }
1784
1785 /**
1786 * Contains all the assertion checking logic around the application of an
1787 * {@link InvocationPlugin}. This class is only loaded when assertions are enabled.
1788 */
1789 class InvocationPluginAssertions {
1790 final InvocationPlugin plugin;
1791 final ValueNode[] args;
1792 final ResolvedJavaMethod targetMethod;
1793 final JavaKind resultType;
1794 final int beforeStackSize;
1795 final boolean needsNullCheck;
1796 final int nodeCount;
1797 final Mark mark;
1798
1799 InvocationPluginAssertions(InvocationPlugin plugin, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) {
1800 guarantee(Assertions.assertionsEnabled(), "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName());
1801 this.plugin = plugin;
1884 ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass());
1885 if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) {
1886 assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass());
1887 Mark mark = graph.getMark();
1888 FixedWithNextNode currentLastInstr = lastInstr;
1889 ValueNode nonNullReceiver = pluginReceiver.get();
1890 Stamp methodStamp = stampProvider.createMethodStamp();
1891 LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
1892 LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
1893 ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
1894 LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected));
1895
1896 JavaTypeProfile profile = null;
1897 if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
1898 profile = profilingInfo.getTypeProfile(bci());
1899 if (profile != null) {
1900 JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
1901 if (newProfile != profile) {
1902 if (newProfile.getTypes().length == 0) {
1903 // All profiled types select the intrinsic so
1904 // emit a fixed guard instead of an if-then-else.
1905 lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
1906 return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
1907 }
1908 } else {
1909 // No profiled types select the intrinsic so emit a virtual call
1910 return null;
1911 }
1912 profile = newProfile;
1913 }
1914 }
1915
1916 AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
1917 AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
1918 append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY));
1919 lastInstr = intrinsicBranch;
1920 return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
1921 } else {
1922 // Receiver selects an overriding method so emit a virtual call
1923 return null;
1924 }
1963 */
1964 protected void afterInvocationPluginExecution(boolean pluginHandledInvoke, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard,
1965 InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
1966 assert assertions.check(pluginHandledInvoke);
1967 if (intrinsicGuard != null) {
1968 if (pluginHandledInvoke) {
1969 if (intrinsicGuard.nonIntrinsicBranch != null) {
1970 // Intrinsic emitted: emit a virtual call to the target method and
1971 // merge it with the intrinsic branch
1972 EndNode intrinsicEnd = append(new EndNode());
1973
1974 FrameStateBuilder intrinsicState = null;
1975 FrameStateBuilder nonIntrinisicState = null;
1976 if (resultType != JavaKind.Void) {
1977 intrinsicState = frameState.copy();
1978 frameState.pop(resultType);
1979 nonIntrinisicState = frameState;
1980 }
1981
1982 lastInstr = intrinsicGuard.nonIntrinsicBranch;
1983 createNonInlinedInvoke(getActionForInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
1984
1985 EndNode nonIntrinsicEnd = append(new EndNode());
1986 AbstractMergeNode mergeNode = graph.add(new MergeNode());
1987
1988 mergeNode.addForwardEnd(intrinsicEnd);
1989 if (intrinsicState != null) {
1990 intrinsicState.merge(mergeNode, nonIntrinisicState);
1991 frameState = intrinsicState;
1992 }
1993 mergeNode.addForwardEnd(nonIntrinsicEnd);
1994 mergeNode.setStateAfter(frameState.create(stream.nextBCI(), mergeNode));
1995
1996 lastInstr = mergeNode;
1997 }
1998 } else {
1999 // Intrinsic was not applied: remove intrinsic guard
2000 // and restore the original receiver node in the arguments array
2001 intrinsicGuard.lastInstr.setNext(null);
2002 GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
2003 lastInstr = intrinsicGuard.lastInstr;
2300 frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue);
2301 }
2302 if (returnMergeNode != null) {
2303 returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode));
2304 lastInstr = finishInstruction(returnMergeNode, frameState);
2305 }
2306 }
2307 /*
2308 * Propagate any side effects into the caller when parsing intrinsics.
2309 */
2310 if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
2311 for (StateSplit sideEffect : parser.frameState.sideEffects()) {
2312 frameState.addSideEffect(sideEffect);
2313 }
2314 }
2315
2316 FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
2317 if (calleeBeforeUnwindNode != null) {
2318 ValueNode calleeUnwindValue = parser.getUnwindValue();
2319 assert calleeUnwindValue != null;
2320 calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false));
2321 }
2322 }
2323 }
2324
2325 public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) {
2326 return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, profile);
2327 }
2328
2329 protected InvokeNode createInvoke(int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
2330 InvokeNode invoke = append(new InvokeNode(callTarget, invokeBci));
2331 frameState.pushReturn(resultType, invoke);
2332 invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
2333 return invoke;
2334 }
2335
2336 protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType, ExceptionEdgeAction exceptionEdgeAction) {
2337 if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
2338 /*
2339 * Clear non-live locals early so that the exception handler entry gets the cleared
2340 * state.
2341 */
2342 frameState.clearNonLiveLocals(currentBlock, liveness, false);
2343 }
2344
2345 AbstractBeginNode exceptionEdge = handleException(null, bci(), exceptionEdgeAction == ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE);
2346 InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci));
2347 frameState.pushReturn(resultType, invoke);
2348 invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
2349 return invoke;
2350 }
2351
2352 protected void genReturn(ValueNode returnVal, JavaKind returnKind) {
2353 if (parsingIntrinsic() && returnVal != null) {
2354 if (returnVal instanceof StateSplit) {
2355 StateSplit stateSplit = (StateSplit) returnVal;
2356 FrameState stateAfter = stateSplit.stateAfter();
2357 if (stateSplit.hasSideEffect()) {
2358 assert stateSplit != null;
2359 if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
2360 assert stateAfter.usages().count() == 1;
2361 assert stateAfter.usages().first() == stateSplit;
2362 stateAfter.replaceAtUsages(graph.add(new FrameState(BytecodeFrame.AFTER_BCI, returnVal)));
2363 GraphUtil.killWithUnusedFloatingInputs(stateAfter);
2364 } else {
2365 /*
2366 * This must be the return value from within a partial intrinsification.
2367 */
2368 assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci);
2369 }
2370 } else {
2371 assert stateAfter == null;
2372 }
2373 }
2374 }
2375
2376 ValueNode realReturnVal = processReturnValue(returnVal, returnKind);
2377
2378 frameState.setRethrowException(false);
2379 frameState.clearStack();
2380 beforeReturn(realReturnVal, returnKind);
2381 if (parent == null) {
2382 append(new ReturnNode(realReturnVal));
2383 } else {
2384 if (returnDataList == null) {
2385 returnDataList = new ArrayList<>();
2386 }
2387 returnDataList.add(new ReturnToCallerData(realReturnVal, lastInstr));
2388 lastInstr = null;
2389 }
2390 }
2391
2392 private ValueNode processReturnValue(ValueNode value, JavaKind kind) {
2393 JavaKind returnKind = method.getSignature().getReturnKind();
2394 if (kind != returnKind) {
2395 // sub-word integer
2396 assert returnKind.isNumericInteger() && returnKind.getStackKind() == JavaKind.Int;
2397 IntegerStamp stamp = (IntegerStamp) value.stamp();
2398
2399 // the bytecode verifier doesn't check that the value is in the correct range
2400 if (stamp.lowerBound() < returnKind.getMinValue() || returnKind.getMaxValue() < stamp.upperBound()) {
2401 ValueNode narrow = append(genNarrow(value, returnKind.getBitCount()));
2402 if (returnKind.isUnsigned()) {
2403 return append(genZeroExtend(narrow, 32));
2404 } else {
2405 return append(genSignExtend(narrow, 32));
2406 }
2407 }
2408 }
2409
2410 return value;
2411 }
2412
2413 private void beforeReturn(ValueNode x, JavaKind kind) {
2414 if (graph.method() != null && graph.method().isJavaLangObjectInit()) {
2415 /*
2416 * Get the receiver from the initial state since bytecode rewriting could do arbitrary
2417 * things to the state of the locals.
2418 */
2419 ValueNode receiver = graph.start().stateAfter().localAt(0);
2420 assert receiver != null && receiver.getStackKind() == JavaKind.Object;
2421 if (RegisterFinalizerNode.mayHaveFinalizer(receiver, graph.getAssumptions())) {
2422 append(new RegisterFinalizerNode(receiver));
2423 }
2424 }
2425 genInfoPointNode(InfopointReason.METHOD_END, x);
2426 if (finalBarrierRequired) {
2427 assert originalReceiver != null;
2428 /*
2429 * When compiling an OSR with a final field store, don't bother tracking the original
2430 * receiver since the receiver cannot be EA'ed.
2431 */
2432 append(new FinalFieldBarrierNode(entryBCI == INVOCATION_ENTRY_BCI ? originalReceiver : null));
2814 synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null);
2815 ValueNode exception = frameState.pop(JavaKind.Object);
2816 append(new UnwindNode(exception));
2817 }
2818
2819 private void synchronizedEpilogue(int bci, ValueNode currentReturnValue, JavaKind currentReturnValueKind) {
2820 if (method.isSynchronized()) {
2821 if (currentReturnValue != null) {
2822 frameState.push(currentReturnValueKind, currentReturnValue);
2823 }
2824 genMonitorExit(methodSynchronizedObject, currentReturnValue, bci);
2825 assert !frameState.rethrowException();
2826 finishPrepare(lastInstr, bci);
2827 }
2828 if (frameState.lockDepth(false) != 0) {
2829 throw bailout("unbalanced monitors: too few exits exiting frame");
2830 }
2831 }
2832
2833 private void createExceptionDispatch(ExceptionDispatchBlock block) {
2834 lastInstr = finishInstruction(lastInstr, frameState);
2835
2836 assert frameState.stackSize() == 1 : frameState;
2837 if (block.handler.isCatchAll()) {
2838 assert block.getSuccessorCount() == 1;
2839 appendGoto(block.getSuccessor(0));
2840 return;
2841 }
2842
2843 JavaType catchType = block.handler.getCatchType();
2844 if (graphBuilderConfig.eagerResolving()) {
2845 catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF);
2846 }
2847 if (catchType instanceof ResolvedJavaType) {
2848 TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType);
2849
2850 if (graphBuilderConfig.getSkippedExceptionTypes() != null) {
2851 for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
2852 if (skippedType.isAssignableFrom(checkedCatchType.getType())) {
2853 BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
2854 ValueNode exception = frameState.stack[0];
2855 FixedNode trueSuccessor = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
|