< prev index next >

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

Print this page




  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 


< prev index next >