Skip to content

Commit

Permalink
[GR-17334] Correct mismatch between framestate and deoptimization lan…
Browse files Browse the repository at this point in the history
…ding pad.

PullRequest: graal/7989
  • Loading branch information
gilles-duboscq committed Jan 12, 2021
2 parents 605a933 + 49bba0a commit acdbe6e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -2950,6 +2950,14 @@ private AbstractBeginNode updateWithExceptionNode(WithExceptionNode withExceptio
return nextBegin;
}

/**
* Because LoopExitNodes do not have a unique bci, in some native-image configurations it is not
* possible to clear non-live locals before generating these nodes.
*/
protected void clearNonLiveLocalsAtLoopExitCreation(BciBlock block, FrameStateBuilder state) {
state.clearNonLiveLocals(block, liveness, true);
}

private Target checkLoopExit(Target target, BciBlock targetBlock) {
if (currentBlock != null) {
long exits = currentBlock.loops & ~targetBlock.loops;
Expand Down Expand Up @@ -2985,6 +2993,8 @@ public int compare(BciBlock o1, BciBlock o2) {
if (targetBlock != blockMap.getUnwindBlock() && !(targetBlock instanceof ExceptionDispatchBlock)) {
newState.setRethrowException(false);
}
clearNonLiveLocalsAtLoopExitCreation(targetBlock, newState);

for (BciBlock loop : exitLoops) {
LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(loop);
LoopExitNode loopExit = graph.add(new LoopExitNode(loopBegin));
Expand All @@ -2996,7 +3006,6 @@ public int compare(BciBlock o1, BciBlock o2) {
}
lastLoopExit = loopExit;
debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop);
newState.clearNonLiveLocals(targetBlock, liveness, true);
newState.insertLoopProxies(loopExit, getEntryState(loop));
loopExit.setStateAfter(newState.create(bci, loopExit));
}
Expand Down Expand Up @@ -3062,6 +3071,14 @@ private FixedWithNextNode getFirstInstruction(BciBlock block) {
return firstInstructionArray[block.id];
}

/**
* In some native-image configurations, it is not legal to clear non-live locals at target
* creation.
*/
protected void clearNonLiveLocalsAtTargetCreation(BciBlock block, FrameStateBuilder state) {
state.clearNonLiveLocals(block, liveness, true);
}

private FixedNode createTarget(double probability, BciBlock block, FrameStateBuilder stateAfter) {
assert probability >= 0 && probability <= 1.01 : probability;
if (isNeverExecutedCode(probability)) {
Expand Down Expand Up @@ -3109,7 +3126,7 @@ private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean
FixedNode result = target.entry;
FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
setEntryState(block, currentEntryState);
currentEntryState.clearNonLiveLocals(block, liveness, true);
clearNonLiveLocalsAtTargetCreation(block, currentEntryState);

debug.log("createTarget %s: first visit, result: %s", block, result);
return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -26,7 +26,9 @@

import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.java.BciBlockMapping;
import org.graalvm.compiler.java.BytecodeParser;
import org.graalvm.compiler.java.FrameStateBuilder;
import org.graalvm.compiler.java.GraphBuilderPhase;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.StructuredGraph;
Expand All @@ -41,6 +43,9 @@

import com.oracle.graal.pointsto.constraints.TypeInstantiationException;
import com.oracle.graal.pointsto.constraints.UnresolvedElementException;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.deopt.DeoptimizationSupport;
import com.oracle.svm.core.meta.SharedMethod;
import com.oracle.svm.core.option.SubstrateOptionsParser;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.UserError.UserException;
Expand Down Expand Up @@ -374,5 +379,37 @@ public boolean needsExplicitException() {
public boolean isPluginEnabled(GraphBuilderPlugin plugin) {
return true;
}

private static boolean isDeoptimizationEnabled() {
return DeoptimizationSupport.enabled() && !SubstrateUtil.isBuildingLibgraal();
}

private boolean isMethodDeoptTarget() {
return method instanceof SharedMethod && ((SharedMethod) method).isDeoptTarget();
}

@Override
protected void clearNonLiveLocalsAtTargetCreation(BciBlockMapping.BciBlock block, FrameStateBuilder state) {
/*
* In order to match potential DeoptEntryNodes, within runtime compiled code it is not
* possible to clear non-live locals at the start of a exception dispatch block if
* deoptimizations can be present, as exception dispatch blocks have the same deopt bci
* as the exception.
*/
if ((!(isDeoptimizationEnabled() && block instanceof BciBlockMapping.ExceptionDispatchBlock)) || isMethodDeoptTarget()) {
super.clearNonLiveLocalsAtTargetCreation(block, state);
}
}

@Override
protected void clearNonLiveLocalsAtLoopExitCreation(BciBlockMapping.BciBlock block, FrameStateBuilder state) {
/*
* In order to match potential DeoptEntryNodes, within runtime compiled code it is not
* possible to clear non-live locals when deoptimizations can be present.
*/
if (!isDeoptimizationEnabled() || isMethodDeoptTarget()) {
super.clearNonLiveLocalsAtLoopExitCreation(block, state);
}
}
}
}

0 comments on commit acdbe6e

Please sign in to comment.