src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54601 c40b2a190173
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    33 import static jdk.vm.ci.meta.DeoptimizationAction.None;
    33 import static jdk.vm.ci.meta.DeoptimizationAction.None;
    34 import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException;
    34 import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException;
    35 import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
    35 import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
    36 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
    36 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
    37 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
    37 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
    38 import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated;
       
    39 import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
    38 import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
    40 import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved;
    39 import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved;
    41 import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
    40 import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
    42 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
    41 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
    43 import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
    42 import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
   254 import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
   253 import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
   255 import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing;
   254 import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing;
   256 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel;
   255 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel;
   257 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
   256 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
   258 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
   257 import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
   259 import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics;
       
   260 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY;
       
   261 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_FAST_PATH_PROBABILITY;
   258 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_FAST_PATH_PROBABILITY;
   262 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_SLOW_PATH_PROBABILITY;
   259 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_SLOW_PATH_PROBABILITY;
   263 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING;
   260 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING;
   264 import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull;
   261 import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull;
   265 
   262 
   272 
   269 
   273 import jdk.internal.vm.compiler.collections.EconomicMap;
   270 import jdk.internal.vm.compiler.collections.EconomicMap;
   274 import jdk.internal.vm.compiler.collections.Equivalence;
   271 import jdk.internal.vm.compiler.collections.Equivalence;
   275 import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
   272 import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
   276 import org.graalvm.compiler.api.replacements.Fold;
   273 import org.graalvm.compiler.api.replacements.Fold;
       
   274 import org.graalvm.compiler.api.replacements.MethodSubstitution;
   277 import org.graalvm.compiler.api.replacements.Snippet;
   275 import org.graalvm.compiler.api.replacements.Snippet;
   278 import org.graalvm.compiler.bytecode.Bytecode;
   276 import org.graalvm.compiler.bytecode.Bytecode;
   279 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
   277 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
   280 import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
   278 import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
   281 import org.graalvm.compiler.bytecode.BytecodeProvider;
   279 import org.graalvm.compiler.bytecode.BytecodeProvider;
   286 import org.graalvm.compiler.bytecode.Bytes;
   284 import org.graalvm.compiler.bytecode.Bytes;
   287 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
   285 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
   288 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
   286 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
   289 import org.graalvm.compiler.core.common.GraalOptions;
   287 import org.graalvm.compiler.core.common.GraalOptions;
   290 import org.graalvm.compiler.core.common.PermanentBailoutException;
   288 import org.graalvm.compiler.core.common.PermanentBailoutException;
       
   289 import org.graalvm.compiler.core.common.RetryableBailoutException;
   291 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
   290 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
   292 import org.graalvm.compiler.core.common.calc.Condition;
   291 import org.graalvm.compiler.core.common.calc.Condition;
   293 import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
   292 import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
   294 import org.graalvm.compiler.core.common.calc.FloatConvert;
   293 import org.graalvm.compiler.core.common.calc.FloatConvert;
   295 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
   294 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
   353 import org.graalvm.compiler.nodes.StartNode;
   352 import org.graalvm.compiler.nodes.StartNode;
   354 import org.graalvm.compiler.nodes.StateSplit;
   353 import org.graalvm.compiler.nodes.StateSplit;
   355 import org.graalvm.compiler.nodes.StructuredGraph;
   354 import org.graalvm.compiler.nodes.StructuredGraph;
   356 import org.graalvm.compiler.nodes.UnwindNode;
   355 import org.graalvm.compiler.nodes.UnwindNode;
   357 import org.graalvm.compiler.nodes.ValueNode;
   356 import org.graalvm.compiler.nodes.ValueNode;
       
   357 import org.graalvm.compiler.nodes.ValuePhiNode;
   358 import org.graalvm.compiler.nodes.calc.AddNode;
   358 import org.graalvm.compiler.nodes.calc.AddNode;
   359 import org.graalvm.compiler.nodes.calc.AndNode;
   359 import org.graalvm.compiler.nodes.calc.AndNode;
   360 import org.graalvm.compiler.nodes.calc.CompareNode;
   360 import org.graalvm.compiler.nodes.calc.CompareNode;
   361 import org.graalvm.compiler.nodes.calc.ConditionalNode;
   361 import org.graalvm.compiler.nodes.calc.ConditionalNode;
   362 import org.graalvm.compiler.nodes.calc.FloatConvertNode;
   362 import org.graalvm.compiler.nodes.calc.FloatConvertNode;
   363 import org.graalvm.compiler.nodes.calc.FloatDivNode;
   363 import org.graalvm.compiler.nodes.calc.FloatDivNode;
       
   364 import org.graalvm.compiler.nodes.calc.FloatNormalizeCompareNode;
   364 import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
   365 import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
   365 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
   366 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
   366 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
   367 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
       
   368 import org.graalvm.compiler.nodes.calc.IntegerNormalizeCompareNode;
   367 import org.graalvm.compiler.nodes.calc.IsNullNode;
   369 import org.graalvm.compiler.nodes.calc.IsNullNode;
   368 import org.graalvm.compiler.nodes.calc.LeftShiftNode;
   370 import org.graalvm.compiler.nodes.calc.LeftShiftNode;
   369 import org.graalvm.compiler.nodes.calc.MulNode;
   371 import org.graalvm.compiler.nodes.calc.MulNode;
   370 import org.graalvm.compiler.nodes.calc.NarrowNode;
   372 import org.graalvm.compiler.nodes.calc.NarrowNode;
   371 import org.graalvm.compiler.nodes.calc.NegateNode;
   373 import org.graalvm.compiler.nodes.calc.NegateNode;
   372 import org.graalvm.compiler.nodes.calc.NormalizeCompareNode;
       
   373 import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
   374 import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
   374 import org.graalvm.compiler.nodes.calc.OrNode;
   375 import org.graalvm.compiler.nodes.calc.OrNode;
   375 import org.graalvm.compiler.nodes.calc.RemNode;
   376 import org.graalvm.compiler.nodes.calc.RemNode;
   376 import org.graalvm.compiler.nodes.calc.RightShiftNode;
   377 import org.graalvm.compiler.nodes.calc.RightShiftNode;
   377 import org.graalvm.compiler.nodes.calc.SignExtendNode;
   378 import org.graalvm.compiler.nodes.calc.SignExtendNode;
   388 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
   389 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
   389 import org.graalvm.compiler.nodes.extended.GuardingNode;
   390 import org.graalvm.compiler.nodes.extended.GuardingNode;
   390 import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
   391 import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
   391 import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode;
   392 import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode;
   392 import org.graalvm.compiler.nodes.extended.LoadHubNode;
   393 import org.graalvm.compiler.nodes.extended.LoadHubNode;
   393 import org.graalvm.compiler.nodes.extended.LoadMethodNode;
       
   394 import org.graalvm.compiler.nodes.extended.MembarNode;
   394 import org.graalvm.compiler.nodes.extended.MembarNode;
   395 import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
   395 import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
   396 import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
       
   397 import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
   396 import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
   398 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
   397 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
   399 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
   398 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
   400 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
   399 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
   401 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
   400 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
   447 import jdk.vm.ci.meta.JavaField;
   446 import jdk.vm.ci.meta.JavaField;
   448 import jdk.vm.ci.meta.JavaKind;
   447 import jdk.vm.ci.meta.JavaKind;
   449 import jdk.vm.ci.meta.JavaMethod;
   448 import jdk.vm.ci.meta.JavaMethod;
   450 import jdk.vm.ci.meta.JavaType;
   449 import jdk.vm.ci.meta.JavaType;
   451 import jdk.vm.ci.meta.JavaTypeProfile;
   450 import jdk.vm.ci.meta.JavaTypeProfile;
   452 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
       
   453 import jdk.vm.ci.meta.LineNumberTable;
   451 import jdk.vm.ci.meta.LineNumberTable;
   454 import jdk.vm.ci.meta.MetaAccessProvider;
   452 import jdk.vm.ci.meta.MetaAccessProvider;
   455 import jdk.vm.ci.meta.ProfilingInfo;
   453 import jdk.vm.ci.meta.ProfilingInfo;
   456 import jdk.vm.ci.meta.RawConstant;
   454 import jdk.vm.ci.meta.RawConstant;
   457 import jdk.vm.ci.meta.ResolvedJavaField;
   455 import jdk.vm.ci.meta.ResolvedJavaField;
   625             throw GraalError.shouldNotReachHere("Unexpected return kind mismatch in " + parser.method + " at FS " + fs);
   623             throw GraalError.shouldNotReachHere("Unexpected return kind mismatch in " + parser.method + " at FS " + fs);
   626         }
   624         }
   627     }
   625     }
   628 
   626 
   629     static class IntrinsicScope extends InliningScope {
   627     static class IntrinsicScope extends InliningScope {
   630         boolean sawInvalidFrameState;
   628         ArrayList<StateSplit> invalidStateUsers;
   631 
   629 
   632         IntrinsicScope(BytecodeParser parser) {
   630         IntrinsicScope(BytecodeParser parser) {
   633             super(parser);
   631             super(parser);
   634         }
   632         }
   635 
   633 
   636         IntrinsicScope(BytecodeParser parser, ResolvedJavaMethod callee, ValueNode[] args) {
   634         IntrinsicScope(BytecodeParser parser, ResolvedJavaMethod callee, ValueNode[] args) {
   637             super(parser, callee, args);
   635             super(parser, callee, args);
   638         }
   636         }
   639 
   637 
       
   638         @SuppressWarnings("unlikely-arg-type")
   640         @Override
   639         @Override
   641         public void close() {
   640         public void close() {
   642             IntrinsicContext intrinsic = parser.intrinsicContext;
   641             IntrinsicContext intrinsic = parser.intrinsicContext;
   643             boolean isRootCompilation;
   642             boolean isRootCompilation;
   644             if (intrinsic != null) {
   643             if (intrinsic != null) {
   648                 isRootCompilation = intrinsic.isCompilationRoot();
   647                 isRootCompilation = intrinsic.isCompilationRoot();
   649             } else {
   648             } else {
   650                 isRootCompilation = false;
   649                 isRootCompilation = false;
   651             }
   650             }
   652             processPlaceholderFrameStates(isRootCompilation);
   651             processPlaceholderFrameStates(isRootCompilation);
   653             if (sawInvalidFrameState) {
   652             if (invalidStateUsers != null) {
   654                 JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
   653                 JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
   655                 FrameStateBuilder frameStateBuilder = parser.frameState;
   654                 ValueNode returnValue = parser.frameState.pop(returnKind);
   656                 ValueNode returnValue = frameStateBuilder.pop(returnKind);
   655                 if (invalidStateUsers.size() == 1 && invalidStateUsers.get(0) == parser.lastInstr) {
   657                 StructuredGraph graph = parser.lastInstr.graph();
   656                     updateSplitFrameState(invalidStateUsers.get(0), returnKind, returnValue);
   658                 StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue));
   657                 } else if (parser.lastInstr instanceof MergeNode) {
   659                 parser.lastInstr.setNext(proxy);
   658                     ValuePhiNode returnValues = null;
   660                 frameStateBuilder.push(returnKind, proxy);
   659                     MergeNode merge = (MergeNode) parser.lastInstr;
   661                 proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy));
   660 
   662                 parser.lastInstr = proxy;
   661                     if (returnValue instanceof ValuePhiNode && ((ValuePhiNode) returnValue).merge() == parser.lastInstr) {
       
   662                         returnValues = (ValuePhiNode) returnValue;
       
   663                     }
       
   664                     if (invalidStateUsers.remove(merge)) {
       
   665                         updateSplitFrameState(merge, returnKind, returnValue);
       
   666                     }
       
   667                     for (EndNode pred : merge.cfgPredecessors()) {
       
   668                         Node lastPred = pred.predecessor();
       
   669                         if (invalidStateUsers.remove(lastPred)) {
       
   670                             ValueNode predReturnValue = returnValue;
       
   671                             if (returnValues != null) {
       
   672                                 int index = merge.phiPredecessorIndex(pred);
       
   673                                 predReturnValue = ((ValuePhiNode) returnValue).valueAt(index);
       
   674                             }
       
   675                             updateSplitFrameState((StateSplit) lastPred, returnKind, predReturnValue);
       
   676                         }
       
   677                     }
       
   678                     if (invalidStateUsers.size() != 0) {
       
   679                         throw new GraalError("unexpected StateSplit above merge %s", invalidStateUsers);
       
   680                     }
       
   681                 } else {
       
   682                     throw new GraalError("unexpected node between return StateSplit and last instruction %s", parser.lastInstr);
       
   683                 }
       
   684                 // Restore the original return value
       
   685                 parser.frameState.push(returnKind, returnValue);
       
   686             }
       
   687         }
       
   688 
       
   689         private void updateSplitFrameState(StateSplit split, JavaKind returnKind, ValueNode returnValue) {
       
   690             parser.frameState.push(returnKind, returnValue);
       
   691             FrameState oldState = split.stateAfter();
       
   692             split.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), split));
       
   693             parser.frameState.pop(returnKind);
       
   694             if (oldState.hasNoUsages()) {
       
   695                 oldState.safeDelete();
   663             }
   696             }
   664         }
   697         }
   665 
   698 
   666         @Override
   699         @Override
   667         protected void handleReturnMismatch(StructuredGraph g, FrameState fs) {
   700         protected void handleReturnMismatch(StructuredGraph g, FrameState fs) {
   668             // If the intrinsic returns a non-void value, then any frame
   701             if (invalidStateUsers == null) {
   669             // state with an empty stack is invalid as it cannot
   702                 invalidStateUsers = new ArrayList<>();
   670             // be used to deoptimize to just after the call returns.
   703             }
   671             // These invalid frame states are expected to be removed
   704             for (Node use : fs.usages()) {
   672             // by later compilation stages.
   705                 if (!(use instanceof StateSplit)) {
   673             FrameState newFrameState = g.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
   706                     throw new GraalError("Expected StateSplit for return mismatch");
   674             newFrameState.setNodeSourcePosition(fs.getNodeSourcePosition());
   707                 }
   675             fs.replaceAndDelete(newFrameState);
   708                 invalidStateUsers.add((StateSplit) use);
   676             sawInvalidFrameState = true;
   709             }
   677         }
   710         }
   678     }
   711     }
   679 
   712 
   680     private static class Target {
   713     private static class Target {
   681         final FixedNode entry;
   714         final FixedNode entry;
   777         this.intrinsicContext = intrinsicContext;
   810         this.intrinsicContext = intrinsicContext;
   778         this.entryBCI = entryBCI;
   811         this.entryBCI = entryBCI;
   779         this.parent = parent;
   812         this.parent = parent;
   780 
   813 
   781         ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
   814         ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
   782         if (classInitializationPlugin != null && graphBuilderConfig.eagerResolving()) {
   815         if (classInitializationPlugin != null && graphBuilderConfig.eagerResolving() && classInitializationPlugin.supportsLazyInitialization(constantPool)) {
   783             uninitializedIsError = eagerInitializing = !classInitializationPlugin.supportsLazyInitialization(constantPool);
   816             eagerInitializing = false;
       
   817             uninitializedIsError = false;
   784         } else {
   818         } else {
   785             eagerInitializing = graphBuilderConfig.eagerResolving();
   819             eagerInitializing = graphBuilderConfig.eagerResolving();
   786             uninitializedIsError = graphBuilderConfig.unresolvedIsError();
   820             uninitializedIsError = graphBuilderConfig.unresolvedIsError();
   787         }
   821         }
   788 
   822 
   997             } else if (!beginNode.hasUsages()) {
  1031             } else if (!beginNode.hasUsages()) {
   998                 GraphUtil.unlinkFixedNode(beginNode);
  1032                 GraphUtil.unlinkFixedNode(beginNode);
   999                 beginNode.safeDelete();
  1033                 beginNode.safeDelete();
  1000             }
  1034             }
  1001         }
  1035         }
       
  1036         if (graph.isOSR() && getParent() == null && graph.getNodes().filter(EntryMarkerNode.class).isEmpty()) {
       
  1037             // This should generally be a transient condition because of inconsistent profile
       
  1038             // information.
       
  1039             throw new RetryableBailoutException("OSR entry point wasn't parsed");
       
  1040         }
  1002     }
  1041     }
  1003 
  1042 
  1004     /**
  1043     /**
  1005      * Creates the frame state after the start node of a graph for an {@link IntrinsicContext
  1044      * Creates the frame state after the start node of a graph for an {@link IntrinsicContext
  1006      * intrinsic} that is the parse root (either for root compiling or for post-parse inlining).
  1045      * intrinsic} that is the parse root (either for root compiling or for post-parse inlining).
  1293     protected ValueNode genXor(ValueNode x, ValueNode y) {
  1332     protected ValueNode genXor(ValueNode x, ValueNode y) {
  1294         return XorNode.create(x, y, NodeView.DEFAULT);
  1333         return XorNode.create(x, y, NodeView.DEFAULT);
  1295     }
  1334     }
  1296 
  1335 
  1297     protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) {
  1336     protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) {
  1298         return NormalizeCompareNode.create(x, y, isUnorderedLess, JavaKind.Int, getConstantReflection());
  1337         return FloatNormalizeCompareNode.create(x, y, isUnorderedLess, JavaKind.Int, getConstantReflection());
       
  1338     }
       
  1339 
       
  1340     protected ValueNode genIntegerNormalizeCompare(ValueNode x, ValueNode y) {
       
  1341         return IntegerNormalizeCompareNode.create(x, y, false, JavaKind.Int, getConstantReflection());
  1299     }
  1342     }
  1300 
  1343 
  1301     protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) {
  1344     protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) {
  1302         return FloatConvertNode.create(op, input, NodeView.DEFAULT);
  1345         return FloatConvertNode.create(op, input, NodeView.DEFAULT);
  1303     }
  1346     }
  1366 
  1409 
  1367     protected AnchoringNode createAnchor(JavaTypeProfile profile) {
  1410     protected AnchoringNode createAnchor(JavaTypeProfile profile) {
  1368         if (profile == null || profile.getNotRecordedProbability() > 0.0) {
  1411         if (profile == null || profile.getNotRecordedProbability() > 0.0) {
  1369             return null;
  1412             return null;
  1370         } else {
  1413         } else {
  1371             return append(new ValueAnchorNode(null));
  1414             return BeginNode.prevBegin(lastInstr);
  1372         }
  1415         }
  1373     }
  1416     }
  1374 
  1417 
  1375     protected LogicNode createInstanceOf(TypeReference type, ValueNode object, JavaTypeProfile profile) {
  1418     protected LogicNode createInstanceOf(TypeReference type, ValueNode object, JavaTypeProfile profile) {
  1376         return InstanceOfNode.create(type, object, profile, createAnchor(profile));
  1419         return InstanceOfNode.create(type, object, profile, createAnchor(profile));
  1732             append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
  1775             append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
  1733             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, graph));
  1776             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, graph));
  1734             return null;
  1777             return null;
  1735         }
  1778         }
  1736 
  1779 
  1737         JavaType returnType = targetMethod.getSignature().getReturnType(method.getDeclaringClass());
  1780         JavaType returnType = maybeEagerlyResolve(targetMethod.getSignature().getReturnType(method.getDeclaringClass()), targetMethod.getDeclaringClass());
  1738         if (graphBuilderConfig.eagerResolving() || parsingIntrinsic()) {
       
  1739             returnType = returnType.resolve(targetMethod.getDeclaringClass());
       
  1740         }
       
  1741         if (invokeKind.hasReceiver()) {
  1781         if (invokeKind.hasReceiver()) {
  1742             args[0] = maybeEmitExplicitNullCheck(args[0]);
  1782             args[0] = maybeEmitExplicitNullCheck(args[0]);
  1743         }
  1783         }
  1744 
  1784 
  1745         if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) {
  1785         if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) {
  1761             if (invokeKind.hasReceiver() && args[0].isNullConstant()) {
  1801             if (invokeKind.hasReceiver() && args[0].isNullConstant()) {
  1762                 append(new DeoptimizeNode(InvalidateRecompile, NullCheckException));
  1802                 append(new DeoptimizeNode(InvalidateRecompile, NullCheckException));
  1763                 return null;
  1803                 return null;
  1764             }
  1804             }
  1765 
  1805 
  1766             if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) {
  1806             if (!invokeKind.isIndirect()) {
  1767                 if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) {
  1807                 if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType)) {
  1768                     if (TraceParserPlugins.getValue(options)) {
  1808                     if (TraceParserPlugins.getValue(options)) {
  1769                         traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
  1809                         traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
  1770                     }
  1810                     }
  1771                     return null;
  1811                     return null;
  1772                 }
  1812                 }
  2038             }
  2078             }
  2039             return true;
  2079             return true;
  2040         }
  2080         }
  2041     }
  2081     }
  2042 
  2082 
  2043     protected static class IntrinsicGuard {
       
  2044         final FixedWithNextNode lastInstr;
       
  2045         final Mark mark;
       
  2046         final AbstractBeginNode nonIntrinsicBranch;
       
  2047         final ValueNode receiver;
       
  2048         final JavaTypeProfile profile;
       
  2049 
       
  2050         public IntrinsicGuard(FixedWithNextNode lastInstr, ValueNode receiver, Mark mark, AbstractBeginNode nonIntrinsicBranch, JavaTypeProfile profile) {
       
  2051             this.lastInstr = lastInstr;
       
  2052             this.receiver = receiver;
       
  2053             this.mark = mark;
       
  2054             this.nonIntrinsicBranch = nonIntrinsicBranch;
       
  2055             this.profile = profile;
       
  2056         }
       
  2057     }
       
  2058 
       
  2059     /**
       
  2060      * Weaves a test of the receiver type to ensure the dispatch will select {@code targetMethod}
       
  2061      * and not another method that overrides it. This should only be called if there is an
       
  2062      * {@link InvocationPlugin} for {@code targetMethod} and the invocation is indirect.
       
  2063      *
       
  2064      * The control flow woven around the intrinsic is as follows:
       
  2065      *
       
  2066      * <pre>
       
  2067      *  if (LoadMethod(LoadHub(receiver)) == targetMethod) {
       
  2068      *       <intrinsic for targetMethod>
       
  2069      *  } else {
       
  2070      *       <virtual call to targetMethod>
       
  2071      *  }
       
  2072      * </pre>
       
  2073      *
       
  2074      * The {@code else} branch is woven by {@link #afterInvocationPluginExecution}.
       
  2075      *
       
  2076      * @return {@code null} if the intrinsic cannot be used otherwise an object to be used by
       
  2077      *         {@link #afterInvocationPluginExecution} to weave code for the non-intrinsic branch
       
  2078      */
       
  2079     protected IntrinsicGuard guardIntrinsic(ValueNode[] args, ResolvedJavaMethod targetMethod, InvocationPluginReceiver pluginReceiver) {
       
  2080         ValueNode intrinsicReceiver = args[0];
       
  2081         ResolvedJavaType receiverType = StampTool.typeOrNull(intrinsicReceiver);
       
  2082         if (receiverType == null) {
       
  2083             // The verifier guarantees it to be at least type declaring targetMethod
       
  2084             receiverType = targetMethod.getDeclaringClass();
       
  2085         }
       
  2086         ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass());
       
  2087         if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) {
       
  2088             assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass());
       
  2089             Mark mark = graph.getMark();
       
  2090             FixedWithNextNode currentLastInstr = lastInstr;
       
  2091             ValueNode nonNullReceiver = pluginReceiver.get();
       
  2092             Stamp methodStamp = getStampProvider().createMethodStamp();
       
  2093             LoadHubNode hub = graph.unique(new LoadHubNode(getStampProvider(), nonNullReceiver));
       
  2094             LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
       
  2095             ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
       
  2096             LogicNode compare = graph.addOrUniqueWithInputs(
       
  2097                             CompareNode.createCompareNode(getConstantReflection(), getMetaAccess(), options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT));
       
  2098 
       
  2099             JavaTypeProfile profile = null;
       
  2100             if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
       
  2101                 profile = profilingInfo.getTypeProfile(bci());
       
  2102                 if (profile != null) {
       
  2103                     JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
       
  2104                     if (newProfile != profile) {
       
  2105                         if (newProfile.getTypes().length == 0) {
       
  2106                             // All profiled types select the intrinsic so
       
  2107                             // emit a fixed guard instead of an if-then-else.
       
  2108                             lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
       
  2109                             return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
       
  2110                         }
       
  2111                     } else {
       
  2112                         // No profiled types select the intrinsic so emit a virtual call
       
  2113                         return null;
       
  2114                     }
       
  2115                     profile = newProfile;
       
  2116                 }
       
  2117             }
       
  2118 
       
  2119             AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
       
  2120             AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
       
  2121             // In the adjustment above, we filter out receiver types that select the intrinsic as
       
  2122             // virtual call target. This means the recorded types in the adjusted profile will
       
  2123             // definitely not call into the intrinsic. Note that the following branch probability is
       
  2124             // still not precise -- the previously-not-recorded receiver types in the original
       
  2125             // profile might or might not call into the intrinsic. Yet we accumulate them into the
       
  2126             // probability of the intrinsic branch, assuming that the not-recorded types will only
       
  2127             // be a small fraction.
       
  2128             append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, profile != null ? profile.getNotRecordedProbability() : LIKELY_PROBABILITY));
       
  2129             lastInstr = intrinsicBranch;
       
  2130             return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
       
  2131         } else {
       
  2132             // Receiver selects an overriding method so emit a virtual call
       
  2133             return null;
       
  2134         }
       
  2135     }
       
  2136 
       
  2137     /**
       
  2138      * Adjusts the profile for an indirect invocation of a virtual method for which there is an
       
  2139      * intrinsic. The adjustment made by this method is to remove all types from the profile that do
       
  2140      * not override {@code targetMethod}.
       
  2141      *
       
  2142      * @param profile the profile to adjust
       
  2143      * @param targetMethod the virtual method for which there is an intrinsic
       
  2144      * @return the adjusted profile or the original {@code profile} object if no adjustment was made
       
  2145      */
       
  2146     protected JavaTypeProfile adjustProfileForInvocationPlugin(JavaTypeProfile profile, ResolvedJavaMethod targetMethod) {
       
  2147         if (profile.getTypes().length > 0) {
       
  2148             List<ProfiledType> retained = new ArrayList<>();
       
  2149             double notRecordedProbability = profile.getNotRecordedProbability();
       
  2150             for (ProfiledType ptype : profile.getTypes()) {
       
  2151                 if (!ptype.getType().resolveMethod(targetMethod, method.getDeclaringClass()).equals(targetMethod)) {
       
  2152                     retained.add(ptype);
       
  2153                 } else {
       
  2154                     notRecordedProbability += ptype.getProbability();
       
  2155                 }
       
  2156             }
       
  2157             if (!retained.isEmpty()) {
       
  2158                 if (retained.size() != profile.getTypes().length) {
       
  2159                     return new JavaTypeProfile(profile.getNullSeen(), notRecordedProbability, retained.toArray(new ProfiledType[retained.size()]));
       
  2160                 }
       
  2161             } else {
       
  2162                 return new JavaTypeProfile(profile.getNullSeen(), notRecordedProbability, new ProfiledType[0]);
       
  2163             }
       
  2164         }
       
  2165         return profile;
       
  2166     }
       
  2167 
       
  2168     /**
       
  2169      * Performs any action required after execution of an invocation plugin. This includes
       
  2170      * {@linkplain InvocationPluginAssertions#check checking} invocation plugin invariants as well
       
  2171      * as weaving the {@code else} branch of the code woven by {@link #guardIntrinsic} if
       
  2172      * {@code guard != null}.
       
  2173      */
       
  2174     protected void afterInvocationPluginExecution(boolean pluginHandledInvoke, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard,
       
  2175                     InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
       
  2176         assert assertions.check(pluginHandledInvoke);
       
  2177         if (intrinsicGuard != null) {
       
  2178             if (pluginHandledInvoke) {
       
  2179                 if (intrinsicGuard.nonIntrinsicBranch != null) {
       
  2180                     // Intrinsic emitted: emit a virtual call to the target method and
       
  2181                     // merge it with the intrinsic branch
       
  2182                     EndNode intrinsicEnd = append(new EndNode());
       
  2183 
       
  2184                     FrameStateBuilder intrinsicState = null;
       
  2185                     FrameStateBuilder nonIntrinisicState = null;
       
  2186                     if (resultType != JavaKind.Void) {
       
  2187                         intrinsicState = frameState.copy();
       
  2188                         frameState.pop(resultType);
       
  2189                         nonIntrinisicState = frameState;
       
  2190                     }
       
  2191 
       
  2192                     lastInstr = intrinsicGuard.nonIntrinsicBranch;
       
  2193                     createNonInlinedInvoke(getActionForInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
       
  2194 
       
  2195                     EndNode nonIntrinsicEnd = append(new EndNode());
       
  2196                     AbstractMergeNode mergeNode = graph.add(new MergeNode());
       
  2197 
       
  2198                     mergeNode.addForwardEnd(intrinsicEnd);
       
  2199                     if (intrinsicState != null) {
       
  2200                         intrinsicState.merge(mergeNode, nonIntrinisicState);
       
  2201                         frameState = intrinsicState;
       
  2202                     }
       
  2203                     mergeNode.addForwardEnd(nonIntrinsicEnd);
       
  2204                     mergeNode.setStateAfter(frameState.create(stream.nextBCI(), mergeNode));
       
  2205 
       
  2206                     lastInstr = mergeNode;
       
  2207                 }
       
  2208             } else {
       
  2209                 // Intrinsic was not applied: remove intrinsic guard
       
  2210                 // and restore the original receiver node in the arguments array
       
  2211                 intrinsicGuard.lastInstr.setNext(null);
       
  2212                 GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
       
  2213                 lastInstr = intrinsicGuard.lastInstr;
       
  2214                 args[0] = intrinsicGuard.receiver;
       
  2215             }
       
  2216         }
       
  2217     }
       
  2218 
       
  2219     @SuppressWarnings("try")
  2083     @SuppressWarnings("try")
  2220     protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
  2084     protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) {
  2221         InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
  2085         InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
  2222         if (plugin != null) {
  2086         if (plugin != null) {
  2223 
  2087 
  2224             if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
  2088             if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
  2225                 // Self recursive intrinsic means the original method should be called.
  2089                 // Self recursive intrinsic means the original method should be called.
  2226                 return false;
  2090                 return false;
  2227             }
  2091             }
  2228 
  2092 
  2229             InvocationPluginReceiver pluginReceiver = invocationPluginReceiver.init(targetMethod, args);
  2093             InvocationPluginReceiver pluginReceiver = invocationPluginReceiver.init(targetMethod, args);
  2230 
  2094             assert invokeKind.isDirect() : "Cannot apply invocation plugin on an indirect call site.";
  2231             IntrinsicGuard intrinsicGuard = null;
       
  2232             if (invokeKind.isIndirect()) {
       
  2233                 intrinsicGuard = guardIntrinsic(args, targetMethod, pluginReceiver);
       
  2234                 if (intrinsicGuard == null) {
       
  2235                     return false;
       
  2236                 } else if (intrinsicGuard.nonIntrinsicBranch == null) {
       
  2237                     assert lastInstr instanceof FixedGuardNode;
       
  2238                 }
       
  2239             }
       
  2240 
  2095 
  2241             InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
  2096             InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
  2242             try (DebugCloseable context = openNodeContext(targetMethod)) {
  2097             try (DebugCloseable context = openNodeContext(targetMethod)) {
  2243                 if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
  2098                 if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
  2244                     afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
  2099                     assert assertions.check(true);
  2245                     return !plugin.isDecorator();
  2100                     return !plugin.isDecorator();
  2246                 } else {
  2101                 } else {
  2247                     afterInvocationPluginExecution(false, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
  2102                     assert assertions.check(false);
  2248                 }
  2103                 }
  2249             }
  2104             }
  2250         }
  2105         }
  2251         return false;
  2106         return false;
  2252     }
  2107     }
  2628 
  2483 
  2629     protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) {
  2484     protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) {
  2630         FixedWithNextNode calleeBeforeUnwindNode = null;
  2485         FixedWithNextNode calleeBeforeUnwindNode = null;
  2631         ValueNode calleeUnwindValue = null;
  2486         ValueNode calleeUnwindValue = null;
  2632 
  2487 
  2633         try (InliningScope s = parsingIntrinsic() ? null : (calleeIntrinsicContext != null ? new IntrinsicScope(this, targetMethod, args)
  2488         try (InliningScope s = parsingIntrinsic() ? null
  2634                         : new InliningScope(this, targetMethod, args))) {
  2489                         : (calleeIntrinsicContext != null ? new IntrinsicScope(this, targetMethod, args)
       
  2490                                         : new InliningScope(this, targetMethod, args))) {
  2635             BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
  2491             BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
  2636             FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph, graphBuilderConfig.retainLocalVariables());
  2492             boolean targetIsSubstitution = targetMethod.isAnnotationPresent(MethodSubstitution.class);
       
  2493             FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph, graphBuilderConfig.retainLocalVariables() && !targetIsSubstitution);
  2637             if (!targetMethod.isStatic()) {
  2494             if (!targetMethod.isStatic()) {
  2638                 args[0] = nullCheckedValue(args[0]);
  2495                 args[0] = nullCheckedValue(args[0]);
  2639             }
  2496             }
  2640             startFrameState.initializeFromArgumentsArray(args);
  2497             startFrameState.initializeFromArgumentsArray(args);
  2641             parser.build(this.lastInstr, startFrameState);
  2498             parser.build(this.lastInstr, startFrameState);
  2642 
  2499 
  2643             List<ReturnToCallerData> calleeReturnDataList = parser.returnDataList;
  2500             List<ReturnToCallerData> calleeReturnDataList = parser.returnDataList;
  2644 
  2501 
  2645             processCalleeReturn(targetMethod, s, calleeReturnDataList);
       
  2646             /*
  2502             /*
  2647              * Propagate any side effects into the caller when parsing intrinsics.
  2503              * Propagate any side effects into the caller when parsing intrinsics.
  2648              */
  2504              */
  2649             if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
  2505             if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
  2650                 for (StateSplit sideEffect : parser.frameState.sideEffects()) {
  2506                 for (StateSplit sideEffect : parser.frameState.sideEffects()) {
  2651                     frameState.addSideEffect(sideEffect);
  2507                     frameState.addSideEffect(sideEffect);
  2652                 }
  2508                 }
  2653             }
  2509             }
       
  2510 
       
  2511             processCalleeReturn(targetMethod, s, calleeReturnDataList);
  2654 
  2512 
  2655             calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
  2513             calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
  2656             if (calleeBeforeUnwindNode != null) {
  2514             if (calleeBeforeUnwindNode != null) {
  2657                 calleeUnwindValue = parser.getUnwindValue();
  2515                 calleeUnwindValue = parser.getUnwindValue();
  2658                 assert calleeUnwindValue != null;
  2516                 assert calleeUnwindValue != null;
  2741                 StateSplit stateSplit = (StateSplit) returnVal;
  2599                 StateSplit stateSplit = (StateSplit) returnVal;
  2742                 FrameState stateAfter = stateSplit.stateAfter();
  2600                 FrameState stateAfter = stateSplit.stateAfter();
  2743                 if (stateSplit.hasSideEffect()) {
  2601                 if (stateSplit.hasSideEffect()) {
  2744                     assert stateSplit != null;
  2602                     assert stateSplit != null;
  2745                     if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
  2603                     if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
  2746                         assert stateAfter.usages().count() == 1;
  2604                         assert stateAfter.hasExactlyOneUsage();
  2747                         assert stateAfter.usages().first() == stateSplit;
  2605                         assert stateAfter.usages().first() == stateSplit;
  2748                         FrameState state;
  2606                         FrameState state;
  2749                         if (returnVal.getStackKind() == JavaKind.Illegal) {
  2607                         if (returnVal.getStackKind() == JavaKind.Illegal) {
  2750                             // This should only occur when Fold and NodeIntrinsic plugins are
  2608                             // This should only occur when Fold and NodeIntrinsic plugins are
  2751                             // deferred. Their return value might not be a Java type and in that
  2609                             // deferred. Their return value might not be a Java type and in that
  2846         if (frameState.lockDepth(false) == 0) {
  2704         if (frameState.lockDepth(false) == 0) {
  2847             throw bailout("unbalanced monitors: too many exits");
  2705             throw bailout("unbalanced monitors: too many exits");
  2848         }
  2706         }
  2849         MonitorIdNode monitorId = frameState.peekMonitorId();
  2707         MonitorIdNode monitorId = frameState.peekMonitorId();
  2850         ValueNode lockedObject = frameState.popLock();
  2708         ValueNode lockedObject = frameState.popLock();
  2851         if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) {
  2709         ValueNode originalLockedObject = GraphUtil.originalValue(lockedObject, false);
  2852             throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)));
  2710         ValueNode originalX = GraphUtil.originalValue(x, false);
       
  2711         if (originalLockedObject != originalX) {
       
  2712             throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", originalLockedObject, originalX));
  2853         }
  2713         }
  2854         MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedValue));
  2714         MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedValue));
  2855         monitorExit.setStateAfter(createFrameState(bci, monitorExit));
  2715         monitorExit.setStateAfter(createFrameState(bci, monitorExit));
  2856     }
  2716     }
  2857 
  2717 
  3093                 /*
  2953                 /*
  3094                  * This is the first time we see this block as a branch target. Create and return a
  2954                  * This is the first time we see this block as a branch target. Create and return a
  3095                  * placeholder that later can be replaced with a MergeNode when we see this block
  2955                  * placeholder that later can be replaced with a MergeNode when we see this block
  3096                  * again.
  2956                  * again.
  3097                  */
  2957                  */
  3098                 if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader() && (currentBlock.loops & ~block.loops) == 0) {
  2958                 if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader() && (currentBlock.loops & ~block.loops) == 0 &&
       
  2959                                 currentBlock.getJsrScope() == block.getJsrScope()) {
       
  2960                     /*
       
  2961                      * If we know that no BeginNode is necessary, then we can avoid allocating and
       
  2962                      * later removing that node. This is strictly a performance optimization:
       
  2963                      * unnecessary BeginNode are allowed and will be removed later on. We need to be
       
  2964                      * careful though because the predecessor information is not always enough: when
       
  2965                      * the loop level changes, we always need a BeginNode. Also, JSR scope changes
       
  2966                      * required a BeginNode because the predecessors coming from RET bytecodes are
       
  2967                      * not reflected in the predecessor count.
       
  2968                      */
  3099                     setFirstInstruction(block, lastInstr);
  2969                     setFirstInstruction(block, lastInstr);
  3100                     lastInstr = null;
  2970                     lastInstr = null;
  3101                 } else {
  2971                 } else {
  3102                     setFirstInstruction(block, graph.add(new BeginNode()));
  2972                     setFirstInstruction(block, graph.add(new BeginNode()));
  3103                 }
  2973                 }
  4153                 throw shouldNotReachHere();
  4023                 throw shouldNotReachHere();
  4154         }
  4024         }
  4155         frameState.push(kind, append(v));
  4025         frameState.push(kind, append(v));
  4156     }
  4026     }
  4157 
  4027 
  4158     private void genCompareOp(JavaKind kind, boolean isUnorderedLess) {
  4028     private void genFloatCompareOp(JavaKind kind, boolean isUnorderedLess) {
  4159         ValueNode y = frameState.pop(kind);
  4029         ValueNode y = frameState.pop(kind);
  4160         ValueNode x = frameState.pop(kind);
  4030         ValueNode x = frameState.pop(kind);
  4161         frameState.push(JavaKind.Int, append(genNormalizeCompare(x, y, isUnorderedLess)));
  4031         frameState.push(JavaKind.Int, append(genNormalizeCompare(x, y, isUnorderedLess)));
       
  4032     }
       
  4033 
       
  4034     private void genIntegerCompareOp(JavaKind kind) {
       
  4035         ValueNode y = frameState.pop(kind);
       
  4036         ValueNode x = frameState.pop(kind);
       
  4037         frameState.push(JavaKind.Int, append(genIntegerNormalizeCompare(x, y)));
  4162     }
  4038     }
  4163 
  4039 
  4164     private void genFloatConvert(FloatConvert op, JavaKind from, JavaKind to) {
  4040     private void genFloatConvert(FloatConvert op, JavaKind from, JavaKind to) {
  4165         ValueNode input = frameState.pop(from);
  4041         ValueNode input = frameState.pop(from);
  4166         frameState.push(to, append(genFloatConvert(op, input)));
  4042         frameState.push(to, append(genFloatConvert(op, input)));
  4231         return result;
  4107         return result;
  4232     }
  4108     }
  4233 
  4109 
  4234     private String unresolvedMethodAssertionMessage(JavaMethod result) {
  4110     private String unresolvedMethodAssertionMessage(JavaMethod result) {
  4235         String message = result.format("%H.%n(%P)%R");
  4111         String message = result.format("%H.%n(%P)%R");
  4236         if (JavaVersionUtil.Java8OrEarlier) {
  4112         if (JavaVersionUtil.JAVA_SPEC <= 8) {
  4237             JavaType declaringClass = result.getDeclaringClass();
  4113             JavaType declaringClass = result.getDeclaringClass();
  4238             String className = declaringClass.getName();
  4114             String className = declaringClass.getName();
  4239             switch (className) {
  4115             switch (className) {
  4240                 case "Ljava/nio/ByteBuffer;":
  4116                 case "Ljava/nio/ByteBuffer;":
  4241                 case "Ljava/nio/ShortBuffer;":
  4117                 case "Ljava/nio/ShortBuffer;":
  4322                 }
  4198                 }
  4323             }
  4199             }
  4324         }
  4200         }
  4325     }
  4201     }
  4326 
  4202 
       
  4203     protected JavaType maybeEagerlyResolve(JavaType type, ResolvedJavaType accessingClass) {
       
  4204         if (graphBuilderConfig.eagerResolving() || parsingIntrinsic()) {
       
  4205             return type.resolve(accessingClass);
       
  4206         }
       
  4207         return type;
       
  4208     }
       
  4209 
  4327     protected void maybeEagerlyInitialize(ResolvedJavaType resolvedType) {
  4210     protected void maybeEagerlyInitialize(ResolvedJavaType resolvedType) {
  4328         if (!resolvedType.isInitialized() && eagerInitializing) {
  4211         if (!resolvedType.isInitialized() && eagerInitializing) {
  4329             initialize(resolvedType);
  4212             initialize(resolvedType);
  4330         }
  4213         }
  4331     }
  4214     }
  4934             this.blockIndex = blockSuccessorIndex;
  4817             this.blockIndex = blockSuccessorIndex;
  4935             actualIndex = -1;
  4818             actualIndex = -1;
  4936         }
  4819         }
  4937     }
  4820     }
  4938 
  4821 
       
  4822     private static final int SWITCH_DEOPT_UNSEEN = -2;
       
  4823     private static final int SWITCH_DEOPT_SEEN = -1;
       
  4824 
  4939     private void genSwitch(BytecodeSwitch bs) {
  4825     private void genSwitch(BytecodeSwitch bs) {
  4940         int bci = bci();
  4826         int bci = bci();
  4941         ValueNode value = frameState.pop(JavaKind.Int);
  4827         ValueNode value = frameState.pop(JavaKind.Int);
  4942 
  4828 
  4943         int nofCases = bs.numberOfCases();
  4829         int nofCases = bs.numberOfCases();
  4951         }
  4837         }
  4952 
  4838 
  4953         ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
  4839         ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
  4954         int[] keys = new int[nofCases];
  4840         int[] keys = new int[nofCases];
  4955         int[] keySuccessors = new int[nofCasesPlusDefault];
  4841         int[] keySuccessors = new int[nofCasesPlusDefault];
  4956         int deoptSuccessorIndex = -1;
  4842         int deoptSuccessorIndex = SWITCH_DEOPT_UNSEEN;
  4957         int nextSuccessorIndex = 0;
  4843         int nextSuccessorIndex = 0;
  4958         boolean constantValue = value.isConstant();
  4844         boolean constantValue = value.isConstant();
  4959         for (int i = 0; i < nofCasesPlusDefault; i++) {
  4845         for (int i = 0; i < nofCasesPlusDefault; i++) {
  4960             if (i < nofCases) {
  4846             if (i < nofCases) {
  4961                 keys[i] = bs.keyAt(i);
  4847                 keys[i] = bs.keyAt(i);
  4962             }
  4848             }
  4963 
       
  4964             if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
  4849             if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
  4965                 if (deoptSuccessorIndex < 0) {
  4850                 deoptSuccessorIndex = SWITCH_DEOPT_SEEN;
  4966                     deoptSuccessorIndex = nextSuccessorIndex++;
  4851                 keySuccessors[i] = SWITCH_DEOPT_SEEN;
  4967                     actualSuccessors.add(null);
       
  4968                 }
       
  4969                 keySuccessors[i] = deoptSuccessorIndex;
       
  4970             } else {
  4852             } else {
  4971                 int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
  4853                 int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
  4972                 SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
  4854                 SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
  4973                 if (info.actualIndex < 0) {
  4855                 if (info.actualIndex < 0) {
  4974                     info.actualIndex = nextSuccessorIndex++;
  4856                     info.actualIndex = nextSuccessorIndex++;
  4999          * reaches a target, we have better chance cutting out unused branches. Otherwise,
  4881          * reaches a target, we have better chance cutting out unused branches. Otherwise,
  5000          * it might be beneficial routing to the same code instead of deopting.
  4882          * it might be beneficial routing to the same code instead of deopting.
  5001          *
  4883          *
  5002          * The following code rewires deoptimization stub to existing resolved branch target if
  4884          * The following code rewires deoptimization stub to existing resolved branch target if
  5003          * the target is connected by more than 1 cases.
  4885          * the target is connected by more than 1 cases.
       
  4886          *
       
  4887          * If this operation rewires every deoptimization seen to an existing branch, care is
       
  4888          * taken that we do not spawn a branch that will never be taken.
  5004          */
  4889          */
  5005         if (deoptSuccessorIndex >= 0) {
  4890         if (deoptSuccessorIndex == SWITCH_DEOPT_SEEN) {
  5006             int[] connectedCases = new int[nextSuccessorIndex];
  4891             int[] connectedCases = new int[nextSuccessorIndex + 1];
  5007             for (int i = 0; i < nofCasesPlusDefault; i++) {
  4892             for (int i = 0; i < nofCasesPlusDefault; i++) {
  5008                 connectedCases[keySuccessors[i]]++;
  4893                 connectedCases[keySuccessors[i] + 1]++;
  5009             }
  4894             }
  5010 
  4895 
  5011             for (int i = 0; i < nofCasesPlusDefault; i++) {
  4896             for (int i = 0; i < nofCasesPlusDefault; i++) {
  5012                 if (keySuccessors[i] == deoptSuccessorIndex) {
  4897                 if (keySuccessors[i] == SWITCH_DEOPT_SEEN) {
  5013                     int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
  4898                     int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
  5014                     SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
  4899                     SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
  5015                     int rewiredIndex = info.actualIndex;
  4900                     int rewiredIndex = info.actualIndex;
  5016                     if (rewiredIndex >= 0 && connectedCases[rewiredIndex] > 1) {
  4901                     if (rewiredIndex >= 0 && connectedCases[rewiredIndex + 1] > 1) {
       
  4902                         // Rewire
  5017                         keySuccessors[i] = info.actualIndex;
  4903                         keySuccessors[i] = info.actualIndex;
       
  4904                     } else {
       
  4905                         if (deoptSuccessorIndex == SWITCH_DEOPT_SEEN) {
       
  4906                             // Spawn deopt successor if needed.
       
  4907                             deoptSuccessorIndex = nextSuccessorIndex++;
       
  4908                             actualSuccessors.add(null);
       
  4909                         }
       
  4910                         keySuccessors[i] = deoptSuccessorIndex;
  5018                     }
  4911                     }
  5019                 }
  4912                 }
  5020             }
  4913             }
  5021         }
  4914         }
  5022 
  4915 
  5216             case L2I            : genNarrow(JavaKind.Long, JavaKind.Int); break;
  5109             case L2I            : genNarrow(JavaKind.Long, JavaKind.Int); break;
  5217             case I2L            : genSignExtend(JavaKind.Int, JavaKind.Long); break;
  5110             case I2L            : genSignExtend(JavaKind.Int, JavaKind.Long); break;
  5218             case I2B            : genSignExtend(JavaKind.Byte, JavaKind.Int); break;
  5111             case I2B            : genSignExtend(JavaKind.Byte, JavaKind.Int); break;
  5219             case I2S            : genSignExtend(JavaKind.Short, JavaKind.Int); break;
  5112             case I2S            : genSignExtend(JavaKind.Short, JavaKind.Int); break;
  5220             case I2C            : genZeroExtend(JavaKind.Char, JavaKind.Int); break;
  5113             case I2C            : genZeroExtend(JavaKind.Char, JavaKind.Int); break;
  5221             case LCMP           : genCompareOp(JavaKind.Long, false); break;
  5114             case LCMP           : genIntegerCompareOp(JavaKind.Long); break;
  5222             case FCMPL          : genCompareOp(JavaKind.Float, true); break;
  5115             case FCMPL          : genFloatCompareOp(JavaKind.Float, true); break;
  5223             case FCMPG          : genCompareOp(JavaKind.Float, false); break;
  5116             case FCMPG          : genFloatCompareOp(JavaKind.Float, false); break;
  5224             case DCMPL          : genCompareOp(JavaKind.Double, true); break;
  5117             case DCMPL          : genFloatCompareOp(JavaKind.Double, true); break;
  5225             case DCMPG          : genCompareOp(JavaKind.Double, false); break;
  5118             case DCMPG          : genFloatCompareOp(JavaKind.Double, false); break;
  5226             case IFEQ           : genIfZero(Condition.EQ); break;
  5119             case IFEQ           : genIfZero(Condition.EQ); break;
  5227             case IFNE           : genIfZero(Condition.NE); break;
  5120             case IFNE           : genIfZero(Condition.NE); break;
  5228             case IFLT           : genIfZero(Condition.LT); break;
  5121             case IFLT           : genIfZero(Condition.LT); break;
  5229             case IFGE           : genIfZero(Condition.GE); break;
  5122             case IFGE           : genIfZero(Condition.GE); break;
  5230             case IFGT           : genIfZero(Condition.GT); break;
  5123             case IFGT           : genIfZero(Condition.GT); break;
  5348 
  5241 
  5349     static String nSpaces(int n) {
  5242     static String nSpaces(int n) {
  5350         return n == 0 ? "" : format("%" + n + "s", "");
  5243         return n == 0 ? "" : format("%" + n + "s", "");
  5351     }
  5244     }
  5352 }
  5245 }
  5353