< prev index next >
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
Print this page
*** 36,45 ****
--- 36,46 ----
import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated;
import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved;
import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
+ import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE;
import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL;
import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD;
import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_0;
*** 268,277 ****
--- 269,279 ----
import java.util.List;
import java.util.function.Supplier;
import jdk.internal.vm.compiler.collections.EconomicMap;
import jdk.internal.vm.compiler.collections.Equivalence;
+ import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
import org.graalvm.compiler.bytecode.BytecodeProvider;
*** 422,432 ****
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.util.ValueMergeUtil;
! import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.CodeUtil;
--- 424,434 ----
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.util.ValueMergeUtil;
! import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.CodeUtil;
*** 1288,1299 ****
protected LogicNode genUnique(LogicNode x) {
return graph.addOrUniqueWithInputs(x);
}
! protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) {
! return new IfNode(condition, falseSuccessor, trueSuccessor, d);
}
protected void genThrow() {
genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
--- 1290,1301 ----
protected LogicNode genUnique(LogicNode x) {
return graph.addOrUniqueWithInputs(x);
}
! protected ValueNode genIfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double d) {
! return new IfNode(condition, trueSuccessor, falseSuccessor, d);
}
protected void genThrow() {
genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
*** 1644,1658 ****
}
private boolean forceInliningEverything;
@Override
! public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) {
boolean previous = forceInliningEverything;
forceInliningEverything = previous || inlineEverything;
try {
! appendInvoke(invokeKind, targetMethod, args);
} finally {
forceInliningEverything = previous;
}
}
--- 1646,1660 ----
}
private boolean forceInliningEverything;
@Override
! public Invoke handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) {
boolean previous = forceInliningEverything;
forceInliningEverything = previous || inlineEverything;
try {
! return appendInvoke(invokeKind, targetMethod, args);
} finally {
forceInliningEverything = previous;
}
}
*** 1718,1728 ****
}
return null;
}
}
if (invokeKind.isDirect()) {
-
inlineInfo = tryInline(args, targetMethod);
if (inlineInfo == SUCCESSFULLY_INLINED) {
return null;
}
}
--- 1720,1729 ----
*** 2318,2328 ****
if (scope != null) {
graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "native method");
}
return false;
}
! if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) {
// Otherwise inline the original method. Any frame state created
// during the inlining will exclude frame(s) in the
// intrinsic method (see FrameStateBuilder.create(int bci)).
notifyBeforeInline(inlinedMethod);
printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
--- 2319,2329 ----
if (scope != null) {
graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "native method");
}
return false;
}
! if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options) && !IS_BUILDING_NATIVE_IMAGE) {
// Otherwise inline the original method. Any frame state created
// during the inlining will exclude frame(s) in the
// intrinsic method (see FrameStateBuilder.create(int bci)).
notifyBeforeInline(inlinedMethod);
printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
*** 2538,2556 ****
return invoke;
}
protected void genReturn(ValueNode returnVal, JavaKind returnKind) {
if (parsingIntrinsic() && returnVal != null) {
if (returnVal instanceof StateSplit) {
StateSplit stateSplit = (StateSplit) returnVal;
FrameState stateAfter = stateSplit.stateAfter();
if (stateSplit.hasSideEffect()) {
assert stateSplit != null;
if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
assert stateAfter.usages().count() == 1;
assert stateAfter.usages().first() == stateSplit;
! stateAfter.replaceAtUsages(graph.add(new FrameState(BytecodeFrame.AFTER_BCI, returnVal)));
GraphUtil.killWithUnusedFloatingInputs(stateAfter);
} else {
/*
* This must be the return value from within a partial intrinsification.
*/
--- 2539,2571 ----
return invoke;
}
protected void genReturn(ValueNode returnVal, JavaKind returnKind) {
if (parsingIntrinsic() && returnVal != null) {
+
if (returnVal instanceof StateSplit) {
StateSplit stateSplit = (StateSplit) returnVal;
FrameState stateAfter = stateSplit.stateAfter();
if (stateSplit.hasSideEffect()) {
assert stateSplit != null;
if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
assert stateAfter.usages().count() == 1;
assert stateAfter.usages().first() == stateSplit;
! FrameState state;
! if (returnVal.getStackKind() == JavaKind.Illegal) {
! // This should only occur when Fold and NodeIntrinsic plugins are
! // deferred. Their return value might not be a Java type and in that
! // case this can't be the final AFTER_BCI so just create a FrameState
! // without a return value on the top of stack.
! assert stateSplit instanceof Invoke;
! ResolvedJavaMethod targetMethod = ((Invoke) stateSplit).getTargetMethod();
! assert targetMethod != null && (targetMethod.getAnnotation(Fold.class) != null || targetMethod.getAnnotation(Node.NodeIntrinsic.class) != null);
! state = new FrameState(BytecodeFrame.AFTER_BCI);
! } else {
! state = new FrameState(BytecodeFrame.AFTER_BCI, returnVal);
! }
! stateAfter.replaceAtUsages(graph.add(state));
GraphUtil.killWithUnusedFloatingInputs(stateAfter);
} else {
/*
* This must be the return value from within a partial intrinsification.
*/
*** 3393,3422 ****
} else {
if (condition.graph() == null) {
condition = genUnique(condition);
}
! NodeSourcePosition currentPosition = graph.currentNodeSourcePosition();
if (isNeverExecutedCode(probability)) {
! NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition()
! ? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), falseBlock.startBci)
! : null;
! append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true, survivingSuccessorPosition));
! if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
! profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
! }
! appendGoto(falseBlock);
! return;
} else if (isNeverExecutedCode(1 - probability)) {
! NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition()
! ? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), trueBlock.startBci)
! : null;
! append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false, survivingSuccessorPosition));
! if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
! profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
}
- appendGoto(trueBlock);
return;
}
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore);
--- 3408,3455 ----
} else {
if (condition.graph() == null) {
condition = genUnique(condition);
}
! BciBlock deoptBlock = null;
! BciBlock noDeoptBlock = null;
if (isNeverExecutedCode(probability)) {
! deoptBlock = trueBlock;
! noDeoptBlock = falseBlock;
} else if (isNeverExecutedCode(1 - probability)) {
! deoptBlock = falseBlock;
! noDeoptBlock = trueBlock;
! }
!
! if (deoptBlock != null) {
! NodeSourcePosition currentPosition = graph.currentNodeSourcePosition();
! NodeSourcePosition survivingSuccessorPosition = null;
! if (graph.trackNodeSourcePosition()) {
! survivingSuccessorPosition = new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), noDeoptBlock.startBci);
! }
! boolean negated = deoptBlock == trueBlock;
! if (!isPotentialCountedLoopExit(condition, deoptBlock)) {
! if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
! profilingPlugin.profileGoto(this, method, bci(), noDeoptBlock.startBci, stateBefore);
! }
! append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, negated, survivingSuccessorPosition));
! appendGoto(noDeoptBlock);
! } else {
! this.controlFlowSplit = true;
! FixedNode noDeoptSuccessor = createTarget(noDeoptBlock, frameState, false, true);
! DeoptimizeNode deopt = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
! /*
! * We do not want to `checkLoopExit` here: otherwise the deopt will go to the
! * deoptBlock's BCI, skipping the branch in the interpreter, and the profile
! * will never see that the branch is taken. This can lead to deopt loops or OSR
! * failure.
! */
! FixedNode deoptSuccessor = BeginNode.begin(deopt);
! ValueNode ifNode = genIfNode(condition, negated ? deoptSuccessor : noDeoptSuccessor, negated ? noDeoptSuccessor : deoptSuccessor, negated ? 1 - probability : probability);
! postProcessIfNode(ifNode);
! append(ifNode);
}
return;
}
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore);
*** 3440,3449 ****
--- 3473,3492 ----
postProcessIfNode(ifNode);
append(ifNode);
}
}
+ public boolean isPotentialCountedLoopExit(LogicNode condition, BciBlock target) {
+ if (currentBlock != null) {
+ long exits = currentBlock.loops & ~target.loops;
+ if (exits != 0) {
+ return condition instanceof CompareNode;
+ }
+ }
+ return false;
+ }
+
/**
* Hook for subclasses to decide whether the IfNode probability should be complemented during
* conversion to Graal IR.
*/
protected boolean shouldComplementProbability() {
*** 3951,3961 ****
return result;
}
private String unresolvedMethodAssertionMessage(JavaMethod result) {
String message = result.format("%H.%n(%P)%R");
! if (GraalServices.Java8OrEarlier) {
JavaType declaringClass = result.getDeclaringClass();
String className = declaringClass.getName();
switch (className) {
case "Ljava/nio/ByteBuffer;":
case "Ljava/nio/ShortBuffer;":
--- 3994,4004 ----
return result;
}
private String unresolvedMethodAssertionMessage(JavaMethod result) {
String message = result.format("%H.%n(%P)%R");
! if (JavaVersionUtil.Java8OrEarlier) {
JavaType declaringClass = result.getDeclaringClass();
String className = declaringClass.getName();
switch (className) {
case "Ljava/nio/ByteBuffer;":
case "Ljava/nio/ShortBuffer;":
*** 4212,4228 ****
if (!resolvedType.isInitialized() && classInitializationPlugin == null) {
handleIllegalNewInstance(resolvedType);
return;
}
! ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
! if (skippedExceptionTypes != null) {
! for (ResolvedJavaType exceptionType : skippedExceptionTypes) {
! if (exceptionType.isAssignableFrom(resolvedType)) {
! append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, RuntimeConstraint));
! return;
! }
}
}
if (classInitializationPlugin != null) {
classInitializationPlugin.apply(this, resolvedType, this::createCurrentFrameState);
--- 4255,4268 ----
if (!resolvedType.isInitialized() && classInitializationPlugin == null) {
handleIllegalNewInstance(resolvedType);
return;
}
! for (ResolvedJavaType exceptionType : this.graphBuilderConfig.getSkippedExceptionTypes()) {
! if (exceptionType.isAssignableFrom(resolvedType)) {
! append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, RuntimeConstraint));
! return;
}
}
if (classInitializationPlugin != null) {
classInitializationPlugin.apply(this, resolvedType, this::createCurrentFrameState);
*** 4511,4523 ****
/*
* Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in
* which case a suffix is added to the generated field.
*/
! if ((parsingIntrinsic() || graphBuilderConfig.omitAssertions()) && resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) {
! frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph));
! return;
}
ResolvedJavaType holder = resolvedField.getDeclaringClass();
ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
if (classInitializationPlugin != null) {
--- 4551,4567 ----
/*
* Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in
* which case a suffix is added to the generated field.
*/
! if (resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) {
! if (parsingIntrinsic()) {
! throw new GraalError("Cannot use an assertion within the context of an intrinsic.");
! } else if (graphBuilderConfig.omitAssertions()) {
! frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph));
! return;
! }
}
ResolvedJavaType holder = resolvedField.getDeclaringClass();
ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
if (classInitializationPlugin != null) {
< prev index next >