21 * questions.
22 */
23
24
25 package org.graalvm.compiler.java;
26
27 import static java.lang.String.format;
28 import static java.lang.reflect.Modifier.STATIC;
29 import static java.lang.reflect.Modifier.SYNCHRONIZED;
30 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile;
31 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
32 import static jdk.vm.ci.meta.DeoptimizationAction.None;
33 import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException;
34 import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
35 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
36 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
37 import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated;
38 import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
39 import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved;
40 import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
41 import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
42 import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE;
43 import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL;
44 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD;
45 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_0;
46 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_1;
47 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_2;
48 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_3;
49 import static org.graalvm.compiler.bytecode.Bytecodes.ANEWARRAY;
50 import static org.graalvm.compiler.bytecode.Bytecodes.ARETURN;
51 import static org.graalvm.compiler.bytecode.Bytecodes.ARRAYLENGTH;
52 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE;
53 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_0;
54 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_1;
55 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_2;
56 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_3;
57 import static org.graalvm.compiler.bytecode.Bytecodes.ATHROW;
58 import static org.graalvm.compiler.bytecode.Bytecodes.BALOAD;
59 import static org.graalvm.compiler.bytecode.Bytecodes.BASTORE;
60 import static org.graalvm.compiler.bytecode.Bytecodes.BIPUSH;
253 import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing;
254 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel;
255 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
256 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
257 import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics;
258 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
259 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_FAST_PATH_PROBABILITY;
260 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_SLOW_PATH_PROBABILITY;
261 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING;
262 import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull;
263
264 import java.util.ArrayList;
265 import java.util.Collections;
266 import java.util.Comparator;
267 import java.util.Formatter;
268 import java.util.List;
269 import java.util.function.Supplier;
270
271 import jdk.internal.vm.compiler.collections.EconomicMap;
272 import jdk.internal.vm.compiler.collections.Equivalence;
273 import org.graalvm.compiler.api.replacements.Snippet;
274 import org.graalvm.compiler.bytecode.Bytecode;
275 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
276 import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
277 import org.graalvm.compiler.bytecode.BytecodeProvider;
278 import org.graalvm.compiler.bytecode.BytecodeStream;
279 import org.graalvm.compiler.bytecode.BytecodeSwitch;
280 import org.graalvm.compiler.bytecode.BytecodeTableSwitch;
281 import org.graalvm.compiler.bytecode.Bytecodes;
282 import org.graalvm.compiler.bytecode.Bytes;
283 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
284 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
285 import org.graalvm.compiler.core.common.GraalOptions;
286 import org.graalvm.compiler.core.common.PermanentBailoutException;
287 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
288 import org.graalvm.compiler.core.common.calc.Condition;
289 import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
290 import org.graalvm.compiler.core.common.calc.FloatConvert;
291 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
292 import org.graalvm.compiler.core.common.type.IntegerStamp;
407 import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
408 import org.graalvm.compiler.nodes.java.InstanceOfNode;
409 import org.graalvm.compiler.nodes.java.LoadFieldNode;
410 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
411 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
412 import org.graalvm.compiler.nodes.java.MonitorEnterNode;
413 import org.graalvm.compiler.nodes.java.MonitorExitNode;
414 import org.graalvm.compiler.nodes.java.MonitorIdNode;
415 import org.graalvm.compiler.nodes.java.NewArrayNode;
416 import org.graalvm.compiler.nodes.java.NewInstanceNode;
417 import org.graalvm.compiler.nodes.java.NewMultiArrayNode;
418 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
419 import org.graalvm.compiler.nodes.java.StoreFieldNode;
420 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
421 import org.graalvm.compiler.nodes.spi.StampProvider;
422 import org.graalvm.compiler.nodes.type.StampTool;
423 import org.graalvm.compiler.nodes.util.GraphUtil;
424 import org.graalvm.compiler.options.OptionValues;
425 import org.graalvm.compiler.phases.OptimisticOptimizations;
426 import org.graalvm.compiler.phases.util.ValueMergeUtil;
427 import org.graalvm.compiler.serviceprovider.GraalServices;
428 import jdk.internal.vm.compiler.word.LocationIdentity;
429
430 import jdk.vm.ci.code.BailoutException;
431 import jdk.vm.ci.code.BytecodeFrame;
432 import jdk.vm.ci.code.CodeUtil;
433 import jdk.vm.ci.code.site.InfopointReason;
434 import jdk.vm.ci.meta.Constant;
435 import jdk.vm.ci.meta.ConstantPool;
436 import jdk.vm.ci.meta.ConstantReflectionProvider;
437 import jdk.vm.ci.meta.DeoptimizationAction;
438 import jdk.vm.ci.meta.DeoptimizationReason;
439 import jdk.vm.ci.meta.JavaConstant;
440 import jdk.vm.ci.meta.JavaField;
441 import jdk.vm.ci.meta.JavaKind;
442 import jdk.vm.ci.meta.JavaMethod;
443 import jdk.vm.ci.meta.JavaType;
444 import jdk.vm.ci.meta.JavaTypeProfile;
445 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
446 import jdk.vm.ci.meta.LineNumberTable;
447 import jdk.vm.ci.meta.MetaAccessProvider;
1273 protected LogicNode genObjectEquals(ValueNode x, ValueNode y) {
1274 return ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, NodeView.DEFAULT);
1275 }
1276
1277 protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) {
1278 return IntegerEqualsNode.create(constantReflection, metaAccess, options, null, x, y, NodeView.DEFAULT);
1279 }
1280
1281 protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) {
1282 return IntegerLessThanNode.create(constantReflection, metaAccess, options, null, x, y, NodeView.DEFAULT);
1283 }
1284
1285 protected ValueNode genUnique(ValueNode x) {
1286 return graph.addOrUniqueWithInputs(x);
1287 }
1288
1289 protected LogicNode genUnique(LogicNode x) {
1290 return graph.addOrUniqueWithInputs(x);
1291 }
1292
1293 protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) {
1294 return new IfNode(condition, falseSuccessor, trueSuccessor, d);
1295 }
1296
1297 protected void genThrow() {
1298 genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
1299
1300 ValueNode exception = maybeEmitExplicitNullCheck(frameState.pop(JavaKind.Object));
1301 if (!StampTool.isPointerNonNull(exception.stamp(NodeView.DEFAULT))) {
1302 FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
1303 exception = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp(NodeView.DEFAULT).join(objectNonNull()), nullCheck));
1304 }
1305 lastInstr.setNext(handleException(exception, bci(), false));
1306 }
1307
1308 protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
1309 return InstanceOfNode.create(type, object);
1310 }
1311
1312 protected AnchoringNode createAnchor(JavaTypeProfile profile) {
1313 if (profile == null || profile.getNotRecordedProbability() > 0.0) {
1314 return null;
1629 protected final ConstantPool constantPool;
1630 protected final MetaAccessProvider metaAccess;
1631 private final ConstantReflectionProvider constantReflection;
1632 private final ConstantFieldProvider constantFieldProvider;
1633 private final StampProvider stampProvider;
1634 protected final IntrinsicContext intrinsicContext;
1635
1636 @Override
1637 public InvokeKind getInvokeKind() {
1638 return currentInvoke == null ? null : currentInvoke.kind;
1639 }
1640
1641 @Override
1642 public JavaType getInvokeReturnType() {
1643 return currentInvoke == null ? null : currentInvoke.returnType;
1644 }
1645
1646 private boolean forceInliningEverything;
1647
1648 @Override
1649 public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) {
1650 boolean previous = forceInliningEverything;
1651 forceInliningEverything = previous || inlineEverything;
1652 try {
1653 appendInvoke(invokeKind, targetMethod, args);
1654 } finally {
1655 forceInliningEverything = previous;
1656 }
1657 }
1658
1659 @Override
1660 public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
1661 BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1662 ExceptionEdgeAction exceptionEdgeAction = intrinsicCallSiteParser == null ? getActionForInvokeExceptionEdge(null) : intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null);
1663 createNonInlinedInvoke(exceptionEdgeAction, bci(), callTarget, resultType);
1664 }
1665
1666 protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
1667 ResolvedJavaMethod targetMethod = initialTargetMethod;
1668 InvokeKind invokeKind = initialInvokeKind;
1669 if (initialInvokeKind.isIndirect()) {
1670 ResolvedJavaType contextType = this.frameState.getMethod().getDeclaringClass();
1671 ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(initialInvokeKind, args[0], initialTargetMethod, contextType);
1672 if (specialCallTarget != null) {
1673 invokeKind = InvokeKind.Special;
1703 if (TraceParserPlugins.getValue(options)) {
1704 traceWithContext("used node plugin for %s", targetMethod.format("%h.%n(%p)"));
1705 }
1706 return null;
1707 }
1708
1709 if (invokeKind.hasReceiver() && args[0].isNullConstant()) {
1710 append(new DeoptimizeNode(InvalidateRecompile, NullCheckException));
1711 return null;
1712 }
1713
1714 if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) {
1715 if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) {
1716 if (TraceParserPlugins.getValue(options)) {
1717 traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
1718 }
1719 return null;
1720 }
1721 }
1722 if (invokeKind.isDirect()) {
1723
1724 inlineInfo = tryInline(args, targetMethod);
1725 if (inlineInfo == SUCCESSFULLY_INLINED) {
1726 return null;
1727 }
1728 }
1729 } finally {
1730 currentInvoke = null;
1731 }
1732
1733 int invokeBci = bci();
1734 JavaTypeProfile profile = getProfileForInvoke(invokeKind);
1735 ExceptionEdgeAction edgeAction = getActionForInvokeExceptionEdge(inlineInfo);
1736 boolean partialIntrinsicExit = false;
1737 if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
1738 partialIntrinsicExit = true;
1739 ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod();
1740 BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1741 if (intrinsicCallSiteParser != null) {
1742 // When exiting a partial intrinsic, the invoke to the original
1743 // must use the same context as the call to the intrinsic.
2303 if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
2304 if (intrinsic.isCompilationRoot()) {
2305 // A root compiled intrinsic needs to deoptimize
2306 // if the slow path is taken. During frame state
2307 // assignment, the deopt node will get its stateBefore
2308 // from the start node of the intrinsic
2309 append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
2310 printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
2311 if (scope != null) {
2312 graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "compilation root");
2313 }
2314 return true;
2315 } else {
2316 if (intrinsic.getOriginalMethod().isNative()) {
2317 printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
2318 if (scope != null) {
2319 graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "native method");
2320 }
2321 return false;
2322 }
2323 if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) {
2324 // Otherwise inline the original method. Any frame state created
2325 // during the inlining will exclude frame(s) in the
2326 // intrinsic method (see FrameStateBuilder.create(int bci)).
2327 notifyBeforeInline(inlinedMethod);
2328 printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
2329 if (scope != null) {
2330 graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "partial intrinsic exit");
2331 }
2332 parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
2333 notifyAfterInline(inlinedMethod);
2334 return true;
2335 } else {
2336 printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)");
2337 if (scope != null) {
2338 graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "partial intrinsic exit");
2339 }
2340 return false;
2341 }
2342 }
2343 } else {
2523 }
2524
2525 protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType, ExceptionEdgeAction exceptionEdgeAction) {
2526 if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
2527 /*
2528 * Clear non-live locals early so that the exception handler entry gets the cleared
2529 * state.
2530 */
2531 frameState.clearNonLiveLocals(currentBlock, liveness, false);
2532 }
2533
2534 AbstractBeginNode exceptionEdge = handleException(null, bci(), exceptionEdgeAction == ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE);
2535 InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci));
2536 frameState.pushReturn(resultType, invoke);
2537 invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
2538 return invoke;
2539 }
2540
2541 protected void genReturn(ValueNode returnVal, JavaKind returnKind) {
2542 if (parsingIntrinsic() && returnVal != null) {
2543 if (returnVal instanceof StateSplit) {
2544 StateSplit stateSplit = (StateSplit) returnVal;
2545 FrameState stateAfter = stateSplit.stateAfter();
2546 if (stateSplit.hasSideEffect()) {
2547 assert stateSplit != null;
2548 if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
2549 assert stateAfter.usages().count() == 1;
2550 assert stateAfter.usages().first() == stateSplit;
2551 stateAfter.replaceAtUsages(graph.add(new FrameState(BytecodeFrame.AFTER_BCI, returnVal)));
2552 GraphUtil.killWithUnusedFloatingInputs(stateAfter);
2553 } else {
2554 /*
2555 * This must be the return value from within a partial intrinsification.
2556 */
2557 assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci);
2558 }
2559 } else {
2560 assert stateAfter == null;
2561 }
2562 }
2563 }
2564
2565 ValueNode realReturnVal = processReturnValue(returnVal, returnKind);
2566
2567 frameState.setRethrowException(false);
2568 frameState.clearStack();
2569 beforeReturn(realReturnVal, returnKind);
2570 if (parent == null) {
2571 append(new ReturnNode(realReturnVal));
3378 // Remove a logic negation node.
3379 if (condition instanceof LogicNegationNode) {
3380 LogicNegationNode logicNegationNode = (LogicNegationNode) condition;
3381 BciBlock tmpBlock = trueBlock;
3382 trueBlock = falseBlock;
3383 falseBlock = tmpBlock;
3384 if (shouldComplementProbability()) {
3385 // the probability coming from profile is about the original condition
3386 probability = 1 - probability;
3387 }
3388 condition = logicNegationNode.getValue();
3389 }
3390
3391 if (condition instanceof LogicConstantNode) {
3392 genConstantTargetIf(trueBlock, falseBlock, condition);
3393 } else {
3394 if (condition.graph() == null) {
3395 condition = genUnique(condition);
3396 }
3397
3398 NodeSourcePosition currentPosition = graph.currentNodeSourcePosition();
3399 if (isNeverExecutedCode(probability)) {
3400 NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition()
3401 ? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), falseBlock.startBci)
3402 : null;
3403 append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true, survivingSuccessorPosition));
3404 if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3405 profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
3406 }
3407 appendGoto(falseBlock);
3408 return;
3409 } else if (isNeverExecutedCode(1 - probability)) {
3410 NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition()
3411 ? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), trueBlock.startBci)
3412 : null;
3413 append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false, survivingSuccessorPosition));
3414 if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3415 profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
3416 }
3417 appendGoto(trueBlock);
3418 return;
3419 }
3420
3421 if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3422 profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore);
3423 }
3424
3425 int oldBci = stream.currentBCI();
3426 int trueBlockInt = checkPositiveIntConstantPushed(trueBlock);
3427 if (trueBlockInt != -1) {
3428 int falseBlockInt = checkPositiveIntConstantPushed(falseBlock);
3429 if (falseBlockInt != -1) {
3430 if (tryGenConditionalForIf(trueBlock, falseBlock, condition, oldBci, trueBlockInt, falseBlockInt)) {
3431 return;
3432 }
3433 }
3434 }
3435
3436 this.controlFlowSplit = true;
3437 FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false);
3438 FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true);
3439 ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability);
3440 postProcessIfNode(ifNode);
3441 append(ifNode);
3442 }
3443 }
3444
3445 /**
3446 * Hook for subclasses to decide whether the IfNode probability should be complemented during
3447 * conversion to Graal IR.
3448 */
3449 protected boolean shouldComplementProbability() {
3450 return true;
3451 }
3452
3453 /**
3454 * Hook for subclasses to generate custom nodes before an IfNode.
3455 */
3456 @SuppressWarnings("unused")
3457 protected void postProcessIfNode(ValueNode node) {
3458 }
3459
3460 private boolean tryGenConditionalForIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt) {
3461 if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) {
3462 genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, false);
3463 return true;
3464 } else if (this.parent != null && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) {
3936 private static void initialize(ResolvedJavaType resolvedType) {
3937 /*
3938 * Since we're potentially triggering class initialization here, we need synchronization to
3939 * mitigate the potential for class initialization related deadlock being caused by the
3940 * compiler (e.g., https://github.com/graalvm/graal-core/pull/232/files#r90788550).
3941 */
3942 synchronized (BytecodeParser.class) {
3943 resolvedType.initialize();
3944 }
3945 }
3946
3947 protected JavaType lookupType(int cpi, int bytecode) {
3948 maybeEagerlyResolve(cpi, bytecode);
3949 JavaType result = constantPool.lookupType(cpi, bytecode);
3950 assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
3951 return result;
3952 }
3953
3954 private String unresolvedMethodAssertionMessage(JavaMethod result) {
3955 String message = result.format("%H.%n(%P)%R");
3956 if (GraalServices.Java8OrEarlier) {
3957 JavaType declaringClass = result.getDeclaringClass();
3958 String className = declaringClass.getName();
3959 switch (className) {
3960 case "Ljava/nio/ByteBuffer;":
3961 case "Ljava/nio/ShortBuffer;":
3962 case "Ljava/nio/CharBuffer;":
3963 case "Ljava/nio/IntBuffer;":
3964 case "Ljava/nio/LongBuffer;":
3965 case "Ljava/nio/FloatBuffer;":
3966 case "Ljava/nio/DoubleBuffer;":
3967 case "Ljava/nio/MappedByteBuffer;": {
3968 switch (result.getName()) {
3969 case "position":
3970 case "limit":
3971 case "mark":
3972 case "reset":
3973 case "clear":
3974 case "flip":
3975 case "rewind": {
3976 String returnType = result.getSignature().getReturnType(null).toJavaName();
4197 if (typeIsResolved(type)) {
4198 genNewInstance((ResolvedJavaType) type);
4199 } else {
4200 handleUnresolvedNewInstance(type);
4201 }
4202 }
4203
4204 protected void genNewInstance(ResolvedJavaType resolvedType) {
4205 if (resolvedType.isAbstract() || resolvedType.isInterface()) {
4206 handleIllegalNewInstance(resolvedType);
4207 return;
4208 }
4209 maybeEagerlyInitialize(resolvedType);
4210
4211 ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
4212 if (!resolvedType.isInitialized() && classInitializationPlugin == null) {
4213 handleIllegalNewInstance(resolvedType);
4214 return;
4215 }
4216
4217 ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
4218 if (skippedExceptionTypes != null) {
4219 for (ResolvedJavaType exceptionType : skippedExceptionTypes) {
4220 if (exceptionType.isAssignableFrom(resolvedType)) {
4221 append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, RuntimeConstraint));
4222 return;
4223 }
4224 }
4225 }
4226
4227 if (classInitializationPlugin != null) {
4228 classInitializationPlugin.apply(this, resolvedType, this::createCurrentFrameState);
4229 }
4230
4231 for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
4232 if (plugin.handleNewInstance(this, resolvedType)) {
4233 return;
4234 }
4235 }
4236
4237 frameState.push(JavaKind.Object, append(createNewInstance(resolvedType, true)));
4238 }
4239
4240 /**
4241 * Gets the kind of array elements for the array type code that appears in a
4242 * {@link Bytecodes#NEWARRAY} bytecode.
4243 *
4496
4497 protected void genGetStatic(int cpi, int opcode) {
4498 JavaField field = lookupField(cpi, opcode);
4499 genGetStatic(field);
4500 }
4501
4502 private void genGetStatic(JavaField field) {
4503 ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, null);
4504 if (resolvedField == null) {
4505 return;
4506 }
4507
4508 if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
4509 graph.recordField(resolvedField);
4510 }
4511
4512 /*
4513 * Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in
4514 * which case a suffix is added to the generated field.
4515 */
4516 if ((parsingIntrinsic() || graphBuilderConfig.omitAssertions()) && resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) {
4517 frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph));
4518 return;
4519 }
4520
4521 ResolvedJavaType holder = resolvedField.getDeclaringClass();
4522 ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
4523 if (classInitializationPlugin != null) {
4524 classInitializationPlugin.apply(this, holder, this::createCurrentFrameState);
4525 }
4526
4527 for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
4528 if (plugin.handleLoadStaticField(this, resolvedField)) {
4529 return;
4530 }
4531 }
4532
4533 ValueNode fieldRead = append(genLoadField(null, resolvedField));
4534 JavaKind fieldKind = resolvedField.getJavaKind();
4535
4536 pushLoadField(resolvedField, fieldRead, fieldKind);
4537 }
4538
|
21 * questions.
22 */
23
24
25 package org.graalvm.compiler.java;
26
27 import static java.lang.String.format;
28 import static java.lang.reflect.Modifier.STATIC;
29 import static java.lang.reflect.Modifier.SYNCHRONIZED;
30 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile;
31 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
32 import static jdk.vm.ci.meta.DeoptimizationAction.None;
33 import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException;
34 import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
35 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
36 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
37 import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated;
38 import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
39 import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved;
40 import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
41 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
42 import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
43 import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE;
44 import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL;
45 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD;
46 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_0;
47 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_1;
48 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_2;
49 import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_3;
50 import static org.graalvm.compiler.bytecode.Bytecodes.ANEWARRAY;
51 import static org.graalvm.compiler.bytecode.Bytecodes.ARETURN;
52 import static org.graalvm.compiler.bytecode.Bytecodes.ARRAYLENGTH;
53 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE;
54 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_0;
55 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_1;
56 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_2;
57 import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_3;
58 import static org.graalvm.compiler.bytecode.Bytecodes.ATHROW;
59 import static org.graalvm.compiler.bytecode.Bytecodes.BALOAD;
60 import static org.graalvm.compiler.bytecode.Bytecodes.BASTORE;
61 import static org.graalvm.compiler.bytecode.Bytecodes.BIPUSH;
254 import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing;
255 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel;
256 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
257 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
258 import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics;
259 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
260 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_FAST_PATH_PROBABILITY;
261 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_SLOW_PATH_PROBABILITY;
262 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING;
263 import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull;
264
265 import java.util.ArrayList;
266 import java.util.Collections;
267 import java.util.Comparator;
268 import java.util.Formatter;
269 import java.util.List;
270 import java.util.function.Supplier;
271
272 import jdk.internal.vm.compiler.collections.EconomicMap;
273 import jdk.internal.vm.compiler.collections.Equivalence;
274 import org.graalvm.compiler.api.replacements.Fold;
275 import org.graalvm.compiler.api.replacements.Snippet;
276 import org.graalvm.compiler.bytecode.Bytecode;
277 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
278 import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
279 import org.graalvm.compiler.bytecode.BytecodeProvider;
280 import org.graalvm.compiler.bytecode.BytecodeStream;
281 import org.graalvm.compiler.bytecode.BytecodeSwitch;
282 import org.graalvm.compiler.bytecode.BytecodeTableSwitch;
283 import org.graalvm.compiler.bytecode.Bytecodes;
284 import org.graalvm.compiler.bytecode.Bytes;
285 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
286 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
287 import org.graalvm.compiler.core.common.GraalOptions;
288 import org.graalvm.compiler.core.common.PermanentBailoutException;
289 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
290 import org.graalvm.compiler.core.common.calc.Condition;
291 import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
292 import org.graalvm.compiler.core.common.calc.FloatConvert;
293 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
294 import org.graalvm.compiler.core.common.type.IntegerStamp;
409 import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
410 import org.graalvm.compiler.nodes.java.InstanceOfNode;
411 import org.graalvm.compiler.nodes.java.LoadFieldNode;
412 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
413 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
414 import org.graalvm.compiler.nodes.java.MonitorEnterNode;
415 import org.graalvm.compiler.nodes.java.MonitorExitNode;
416 import org.graalvm.compiler.nodes.java.MonitorIdNode;
417 import org.graalvm.compiler.nodes.java.NewArrayNode;
418 import org.graalvm.compiler.nodes.java.NewInstanceNode;
419 import org.graalvm.compiler.nodes.java.NewMultiArrayNode;
420 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
421 import org.graalvm.compiler.nodes.java.StoreFieldNode;
422 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
423 import org.graalvm.compiler.nodes.spi.StampProvider;
424 import org.graalvm.compiler.nodes.type.StampTool;
425 import org.graalvm.compiler.nodes.util.GraphUtil;
426 import org.graalvm.compiler.options.OptionValues;
427 import org.graalvm.compiler.phases.OptimisticOptimizations;
428 import org.graalvm.compiler.phases.util.ValueMergeUtil;
429 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
430 import jdk.internal.vm.compiler.word.LocationIdentity;
431
432 import jdk.vm.ci.code.BailoutException;
433 import jdk.vm.ci.code.BytecodeFrame;
434 import jdk.vm.ci.code.CodeUtil;
435 import jdk.vm.ci.code.site.InfopointReason;
436 import jdk.vm.ci.meta.Constant;
437 import jdk.vm.ci.meta.ConstantPool;
438 import jdk.vm.ci.meta.ConstantReflectionProvider;
439 import jdk.vm.ci.meta.DeoptimizationAction;
440 import jdk.vm.ci.meta.DeoptimizationReason;
441 import jdk.vm.ci.meta.JavaConstant;
442 import jdk.vm.ci.meta.JavaField;
443 import jdk.vm.ci.meta.JavaKind;
444 import jdk.vm.ci.meta.JavaMethod;
445 import jdk.vm.ci.meta.JavaType;
446 import jdk.vm.ci.meta.JavaTypeProfile;
447 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
448 import jdk.vm.ci.meta.LineNumberTable;
449 import jdk.vm.ci.meta.MetaAccessProvider;
1275 protected LogicNode genObjectEquals(ValueNode x, ValueNode y) {
1276 return ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, NodeView.DEFAULT);
1277 }
1278
1279 protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) {
1280 return IntegerEqualsNode.create(constantReflection, metaAccess, options, null, x, y, NodeView.DEFAULT);
1281 }
1282
1283 protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) {
1284 return IntegerLessThanNode.create(constantReflection, metaAccess, options, null, x, y, NodeView.DEFAULT);
1285 }
1286
1287 protected ValueNode genUnique(ValueNode x) {
1288 return graph.addOrUniqueWithInputs(x);
1289 }
1290
1291 protected LogicNode genUnique(LogicNode x) {
1292 return graph.addOrUniqueWithInputs(x);
1293 }
1294
1295 protected ValueNode genIfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double d) {
1296 return new IfNode(condition, trueSuccessor, falseSuccessor, d);
1297 }
1298
1299 protected void genThrow() {
1300 genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
1301
1302 ValueNode exception = maybeEmitExplicitNullCheck(frameState.pop(JavaKind.Object));
1303 if (!StampTool.isPointerNonNull(exception.stamp(NodeView.DEFAULT))) {
1304 FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
1305 exception = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp(NodeView.DEFAULT).join(objectNonNull()), nullCheck));
1306 }
1307 lastInstr.setNext(handleException(exception, bci(), false));
1308 }
1309
1310 protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
1311 return InstanceOfNode.create(type, object);
1312 }
1313
1314 protected AnchoringNode createAnchor(JavaTypeProfile profile) {
1315 if (profile == null || profile.getNotRecordedProbability() > 0.0) {
1316 return null;
1631 protected final ConstantPool constantPool;
1632 protected final MetaAccessProvider metaAccess;
1633 private final ConstantReflectionProvider constantReflection;
1634 private final ConstantFieldProvider constantFieldProvider;
1635 private final StampProvider stampProvider;
1636 protected final IntrinsicContext intrinsicContext;
1637
1638 @Override
1639 public InvokeKind getInvokeKind() {
1640 return currentInvoke == null ? null : currentInvoke.kind;
1641 }
1642
1643 @Override
1644 public JavaType getInvokeReturnType() {
1645 return currentInvoke == null ? null : currentInvoke.returnType;
1646 }
1647
1648 private boolean forceInliningEverything;
1649
1650 @Override
1651 public Invoke handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) {
1652 boolean previous = forceInliningEverything;
1653 forceInliningEverything = previous || inlineEverything;
1654 try {
1655 return appendInvoke(invokeKind, targetMethod, args);
1656 } finally {
1657 forceInliningEverything = previous;
1658 }
1659 }
1660
1661 @Override
1662 public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
1663 BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1664 ExceptionEdgeAction exceptionEdgeAction = intrinsicCallSiteParser == null ? getActionForInvokeExceptionEdge(null) : intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null);
1665 createNonInlinedInvoke(exceptionEdgeAction, bci(), callTarget, resultType);
1666 }
1667
1668 protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
1669 ResolvedJavaMethod targetMethod = initialTargetMethod;
1670 InvokeKind invokeKind = initialInvokeKind;
1671 if (initialInvokeKind.isIndirect()) {
1672 ResolvedJavaType contextType = this.frameState.getMethod().getDeclaringClass();
1673 ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(initialInvokeKind, args[0], initialTargetMethod, contextType);
1674 if (specialCallTarget != null) {
1675 invokeKind = InvokeKind.Special;
1705 if (TraceParserPlugins.getValue(options)) {
1706 traceWithContext("used node plugin for %s", targetMethod.format("%h.%n(%p)"));
1707 }
1708 return null;
1709 }
1710
1711 if (invokeKind.hasReceiver() && args[0].isNullConstant()) {
1712 append(new DeoptimizeNode(InvalidateRecompile, NullCheckException));
1713 return null;
1714 }
1715
1716 if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) {
1717 if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) {
1718 if (TraceParserPlugins.getValue(options)) {
1719 traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
1720 }
1721 return null;
1722 }
1723 }
1724 if (invokeKind.isDirect()) {
1725 inlineInfo = tryInline(args, targetMethod);
1726 if (inlineInfo == SUCCESSFULLY_INLINED) {
1727 return null;
1728 }
1729 }
1730 } finally {
1731 currentInvoke = null;
1732 }
1733
1734 int invokeBci = bci();
1735 JavaTypeProfile profile = getProfileForInvoke(invokeKind);
1736 ExceptionEdgeAction edgeAction = getActionForInvokeExceptionEdge(inlineInfo);
1737 boolean partialIntrinsicExit = false;
1738 if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
1739 partialIntrinsicExit = true;
1740 ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod();
1741 BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
1742 if (intrinsicCallSiteParser != null) {
1743 // When exiting a partial intrinsic, the invoke to the original
1744 // must use the same context as the call to the intrinsic.
2304 if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
2305 if (intrinsic.isCompilationRoot()) {
2306 // A root compiled intrinsic needs to deoptimize
2307 // if the slow path is taken. During frame state
2308 // assignment, the deopt node will get its stateBefore
2309 // from the start node of the intrinsic
2310 append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
2311 printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
2312 if (scope != null) {
2313 graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "compilation root");
2314 }
2315 return true;
2316 } else {
2317 if (intrinsic.getOriginalMethod().isNative()) {
2318 printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
2319 if (scope != null) {
2320 graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "native method");
2321 }
2322 return false;
2323 }
2324 if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options) && !IS_BUILDING_NATIVE_IMAGE) {
2325 // Otherwise inline the original method. Any frame state created
2326 // during the inlining will exclude frame(s) in the
2327 // intrinsic method (see FrameStateBuilder.create(int bci)).
2328 notifyBeforeInline(inlinedMethod);
2329 printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
2330 if (scope != null) {
2331 graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "partial intrinsic exit");
2332 }
2333 parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
2334 notifyAfterInline(inlinedMethod);
2335 return true;
2336 } else {
2337 printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)");
2338 if (scope != null) {
2339 graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "partial intrinsic exit");
2340 }
2341 return false;
2342 }
2343 }
2344 } else {
2524 }
2525
2526 protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType, ExceptionEdgeAction exceptionEdgeAction) {
2527 if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
2528 /*
2529 * Clear non-live locals early so that the exception handler entry gets the cleared
2530 * state.
2531 */
2532 frameState.clearNonLiveLocals(currentBlock, liveness, false);
2533 }
2534
2535 AbstractBeginNode exceptionEdge = handleException(null, bci(), exceptionEdgeAction == ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE);
2536 InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci));
2537 frameState.pushReturn(resultType, invoke);
2538 invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
2539 return invoke;
2540 }
2541
2542 protected void genReturn(ValueNode returnVal, JavaKind returnKind) {
2543 if (parsingIntrinsic() && returnVal != null) {
2544
2545 if (returnVal instanceof StateSplit) {
2546 StateSplit stateSplit = (StateSplit) returnVal;
2547 FrameState stateAfter = stateSplit.stateAfter();
2548 if (stateSplit.hasSideEffect()) {
2549 assert stateSplit != null;
2550 if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
2551 assert stateAfter.usages().count() == 1;
2552 assert stateAfter.usages().first() == stateSplit;
2553 FrameState state;
2554 if (returnVal.getStackKind() == JavaKind.Illegal) {
2555 // This should only occur when Fold and NodeIntrinsic plugins are
2556 // deferred. Their return value might not be a Java type and in that
2557 // case this can't be the final AFTER_BCI so just create a FrameState
2558 // without a return value on the top of stack.
2559 assert stateSplit instanceof Invoke;
2560 ResolvedJavaMethod targetMethod = ((Invoke) stateSplit).getTargetMethod();
2561 assert targetMethod != null && (targetMethod.getAnnotation(Fold.class) != null || targetMethod.getAnnotation(Node.NodeIntrinsic.class) != null);
2562 state = new FrameState(BytecodeFrame.AFTER_BCI);
2563 } else {
2564 state = new FrameState(BytecodeFrame.AFTER_BCI, returnVal);
2565 }
2566 stateAfter.replaceAtUsages(graph.add(state));
2567 GraphUtil.killWithUnusedFloatingInputs(stateAfter);
2568 } else {
2569 /*
2570 * This must be the return value from within a partial intrinsification.
2571 */
2572 assert !BytecodeFrame.isPlaceholderBci(stateAfter.bci);
2573 }
2574 } else {
2575 assert stateAfter == null;
2576 }
2577 }
2578 }
2579
2580 ValueNode realReturnVal = processReturnValue(returnVal, returnKind);
2581
2582 frameState.setRethrowException(false);
2583 frameState.clearStack();
2584 beforeReturn(realReturnVal, returnKind);
2585 if (parent == null) {
2586 append(new ReturnNode(realReturnVal));
3393 // Remove a logic negation node.
3394 if (condition instanceof LogicNegationNode) {
3395 LogicNegationNode logicNegationNode = (LogicNegationNode) condition;
3396 BciBlock tmpBlock = trueBlock;
3397 trueBlock = falseBlock;
3398 falseBlock = tmpBlock;
3399 if (shouldComplementProbability()) {
3400 // the probability coming from profile is about the original condition
3401 probability = 1 - probability;
3402 }
3403 condition = logicNegationNode.getValue();
3404 }
3405
3406 if (condition instanceof LogicConstantNode) {
3407 genConstantTargetIf(trueBlock, falseBlock, condition);
3408 } else {
3409 if (condition.graph() == null) {
3410 condition = genUnique(condition);
3411 }
3412
3413 BciBlock deoptBlock = null;
3414 BciBlock noDeoptBlock = null;
3415 if (isNeverExecutedCode(probability)) {
3416 deoptBlock = trueBlock;
3417 noDeoptBlock = falseBlock;
3418 } else if (isNeverExecutedCode(1 - probability)) {
3419 deoptBlock = falseBlock;
3420 noDeoptBlock = trueBlock;
3421 }
3422
3423 if (deoptBlock != null) {
3424 NodeSourcePosition currentPosition = graph.currentNodeSourcePosition();
3425 NodeSourcePosition survivingSuccessorPosition = null;
3426 if (graph.trackNodeSourcePosition()) {
3427 survivingSuccessorPosition = new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), noDeoptBlock.startBci);
3428 }
3429 boolean negated = deoptBlock == trueBlock;
3430 if (!isPotentialCountedLoopExit(condition, deoptBlock)) {
3431 if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3432 profilingPlugin.profileGoto(this, method, bci(), noDeoptBlock.startBci, stateBefore);
3433 }
3434 append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, negated, survivingSuccessorPosition));
3435 appendGoto(noDeoptBlock);
3436 } else {
3437 this.controlFlowSplit = true;
3438 FixedNode noDeoptSuccessor = createTarget(noDeoptBlock, frameState, false, true);
3439 DeoptimizeNode deopt = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
3440 /*
3441 * We do not want to `checkLoopExit` here: otherwise the deopt will go to the
3442 * deoptBlock's BCI, skipping the branch in the interpreter, and the profile
3443 * will never see that the branch is taken. This can lead to deopt loops or OSR
3444 * failure.
3445 */
3446 FixedNode deoptSuccessor = BeginNode.begin(deopt);
3447 ValueNode ifNode = genIfNode(condition, negated ? deoptSuccessor : noDeoptSuccessor, negated ? noDeoptSuccessor : deoptSuccessor, negated ? 1 - probability : probability);
3448 postProcessIfNode(ifNode);
3449 append(ifNode);
3450 }
3451 return;
3452 }
3453
3454 if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
3455 profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore);
3456 }
3457
3458 int oldBci = stream.currentBCI();
3459 int trueBlockInt = checkPositiveIntConstantPushed(trueBlock);
3460 if (trueBlockInt != -1) {
3461 int falseBlockInt = checkPositiveIntConstantPushed(falseBlock);
3462 if (falseBlockInt != -1) {
3463 if (tryGenConditionalForIf(trueBlock, falseBlock, condition, oldBci, trueBlockInt, falseBlockInt)) {
3464 return;
3465 }
3466 }
3467 }
3468
3469 this.controlFlowSplit = true;
3470 FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false);
3471 FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true);
3472 ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability);
3473 postProcessIfNode(ifNode);
3474 append(ifNode);
3475 }
3476 }
3477
3478 public boolean isPotentialCountedLoopExit(LogicNode condition, BciBlock target) {
3479 if (currentBlock != null) {
3480 long exits = currentBlock.loops & ~target.loops;
3481 if (exits != 0) {
3482 return condition instanceof CompareNode;
3483 }
3484 }
3485 return false;
3486 }
3487
3488 /**
3489 * Hook for subclasses to decide whether the IfNode probability should be complemented during
3490 * conversion to Graal IR.
3491 */
3492 protected boolean shouldComplementProbability() {
3493 return true;
3494 }
3495
3496 /**
3497 * Hook for subclasses to generate custom nodes before an IfNode.
3498 */
3499 @SuppressWarnings("unused")
3500 protected void postProcessIfNode(ValueNode node) {
3501 }
3502
3503 private boolean tryGenConditionalForIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt) {
3504 if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) {
3505 genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, false);
3506 return true;
3507 } else if (this.parent != null && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) {
3979 private static void initialize(ResolvedJavaType resolvedType) {
3980 /*
3981 * Since we're potentially triggering class initialization here, we need synchronization to
3982 * mitigate the potential for class initialization related deadlock being caused by the
3983 * compiler (e.g., https://github.com/graalvm/graal-core/pull/232/files#r90788550).
3984 */
3985 synchronized (BytecodeParser.class) {
3986 resolvedType.initialize();
3987 }
3988 }
3989
3990 protected JavaType lookupType(int cpi, int bytecode) {
3991 maybeEagerlyResolve(cpi, bytecode);
3992 JavaType result = constantPool.lookupType(cpi, bytecode);
3993 assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
3994 return result;
3995 }
3996
3997 private String unresolvedMethodAssertionMessage(JavaMethod result) {
3998 String message = result.format("%H.%n(%P)%R");
3999 if (JavaVersionUtil.Java8OrEarlier) {
4000 JavaType declaringClass = result.getDeclaringClass();
4001 String className = declaringClass.getName();
4002 switch (className) {
4003 case "Ljava/nio/ByteBuffer;":
4004 case "Ljava/nio/ShortBuffer;":
4005 case "Ljava/nio/CharBuffer;":
4006 case "Ljava/nio/IntBuffer;":
4007 case "Ljava/nio/LongBuffer;":
4008 case "Ljava/nio/FloatBuffer;":
4009 case "Ljava/nio/DoubleBuffer;":
4010 case "Ljava/nio/MappedByteBuffer;": {
4011 switch (result.getName()) {
4012 case "position":
4013 case "limit":
4014 case "mark":
4015 case "reset":
4016 case "clear":
4017 case "flip":
4018 case "rewind": {
4019 String returnType = result.getSignature().getReturnType(null).toJavaName();
4240 if (typeIsResolved(type)) {
4241 genNewInstance((ResolvedJavaType) type);
4242 } else {
4243 handleUnresolvedNewInstance(type);
4244 }
4245 }
4246
4247 protected void genNewInstance(ResolvedJavaType resolvedType) {
4248 if (resolvedType.isAbstract() || resolvedType.isInterface()) {
4249 handleIllegalNewInstance(resolvedType);
4250 return;
4251 }
4252 maybeEagerlyInitialize(resolvedType);
4253
4254 ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
4255 if (!resolvedType.isInitialized() && classInitializationPlugin == null) {
4256 handleIllegalNewInstance(resolvedType);
4257 return;
4258 }
4259
4260 for (ResolvedJavaType exceptionType : this.graphBuilderConfig.getSkippedExceptionTypes()) {
4261 if (exceptionType.isAssignableFrom(resolvedType)) {
4262 append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, RuntimeConstraint));
4263 return;
4264 }
4265 }
4266
4267 if (classInitializationPlugin != null) {
4268 classInitializationPlugin.apply(this, resolvedType, this::createCurrentFrameState);
4269 }
4270
4271 for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
4272 if (plugin.handleNewInstance(this, resolvedType)) {
4273 return;
4274 }
4275 }
4276
4277 frameState.push(JavaKind.Object, append(createNewInstance(resolvedType, true)));
4278 }
4279
4280 /**
4281 * Gets the kind of array elements for the array type code that appears in a
4282 * {@link Bytecodes#NEWARRAY} bytecode.
4283 *
4536
4537 protected void genGetStatic(int cpi, int opcode) {
4538 JavaField field = lookupField(cpi, opcode);
4539 genGetStatic(field);
4540 }
4541
4542 private void genGetStatic(JavaField field) {
4543 ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, null);
4544 if (resolvedField == null) {
4545 return;
4546 }
4547
4548 if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
4549 graph.recordField(resolvedField);
4550 }
4551
4552 /*
4553 * Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in
4554 * which case a suffix is added to the generated field.
4555 */
4556 if (resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) {
4557 if (parsingIntrinsic()) {
4558 throw new GraalError("Cannot use an assertion within the context of an intrinsic.");
4559 } else if (graphBuilderConfig.omitAssertions()) {
4560 frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph));
4561 return;
4562 }
4563 }
4564
4565 ResolvedJavaType holder = resolvedField.getDeclaringClass();
4566 ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
4567 if (classInitializationPlugin != null) {
4568 classInitializationPlugin.apply(this, holder, this::createCurrentFrameState);
4569 }
4570
4571 for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
4572 if (plugin.handleLoadStaticField(this, resolvedField)) {
4573 return;
4574 }
4575 }
4576
4577 ValueNode fieldRead = append(genLoadField(null, resolvedField));
4578 JavaKind fieldKind = resolvedField.getJavaKind();
4579
4580 pushLoadField(resolvedField, fieldRead, fieldKind);
4581 }
4582
|