< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java

Print this page




 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));


< prev index next >