Skip to content

Commit

Permalink
[GR-18427] Fix JSR handling in the presence of exception edges.
Browse files Browse the repository at this point in the history
PullRequest: graal/4905
  • Loading branch information
gilles-duboscq committed Nov 15, 2019
2 parents 22c5054 + 6a4d602 commit 47e18e0
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,7 @@ private void createJsrAlternatives(BciBlock[] blockMap, BciBlock block) {
BciBlock successor = block.getSuccessor(i);
JsrScope nextScope = scope;
if (successor == block.getJsrSuccessor()) {
nextScope = scope.push(block.getJsrReturnBci());
nextScope = scope.push(block.getJsrReturnBci(), successor);
}
if (successor == block.getRetSuccessor()) {
nextScope = scope.pop();
Expand Down Expand Up @@ -1109,12 +1109,25 @@ private void createJsrAlternatives(BciBlock[] blockMap, BciBlock block) {
}
}
for (BciBlock successor : block.getSuccessors()) {
if (!jsrVisited.contains(successor)) {
if (!jsrVisited.contains(successor) && shouldFollowEdge(successor, scope)) {
createJsrAlternatives(blockMap, successor);
}
}
}

private static boolean shouldFollowEdge(BciBlock successor, JsrScope scope) {
if (successor instanceof ExceptionDispatchBlock && scope.getJsrEntryBlock() != null) {
ExceptionDispatchBlock exceptionDispatchBlock = (ExceptionDispatchBlock) successor;
int bci = scope.getJsrEntryBlock().startBci;
if (exceptionDispatchBlock.handler.getStartBCI() < bci && bci < exceptionDispatchBlock.handler.getEndBCI()) {
// Handler covers start of JSR block and the bci before that => don't follow edge.
return false;
}
}

return true;
}

private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) {
ExceptionDispatchBlock lastHandler = null;
int dispatchBlocks = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
import static jdk.vm.ci.meta.DeoptimizationAction.None;
import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException;
import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
Expand Down Expand Up @@ -2738,8 +2737,9 @@ protected void genRet(int localIndex) {
int retAddress = scope.nextReturnAddress();
ConstantNode returnBciNode = getJsrConstant(retAddress);
LogicNode guard = IntegerEqualsNode.create(getConstantReflection(), getMetaAccess(), options, null, local, returnBciNode, NodeView.DEFAULT);
guard = graph.addOrUniqueWithInputs(guard);
append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile));
if (!guard.isTautology()) {
throw new JsrNotSupportedBailout("cannot statically decide jsr return address " + local);
}
if (!successor.getJsrScope().equals(scope.pop())) {
throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package org.graalvm.compiler.java;

import org.graalvm.compiler.bytecode.Bytecodes;
import org.graalvm.compiler.java.BciBlockMapping.BciBlock;

/**
* Represents a subroutine entered via {@link Bytecodes#JSR} and exited via {@link Bytecodes#RET}.
Expand All @@ -40,34 +41,46 @@ public final class JsrScope {

private final JsrScope parent;

private JsrScope(int returnBci, JsrScope parent) {
private final BciBlock jsrEntryBlock;

private JsrScope(int returnBci, BciBlock jsrEntryBlock, JsrScope parent) {
this.returnAddress = (char) returnBci;
this.parent = parent;
this.jsrEntryBlock = jsrEntryBlock;
}

private JsrScope() {
this.returnAddress = 0;
this.parent = null;
this.jsrEntryBlock = null;
}

public int nextReturnAddress() {
return returnAddress;
}

public BciBlock getJsrEntryBlock() {
return jsrEntryBlock;
}

/**
* Enters a new subroutine from the current scope represented by this object.
*
* @param returnBci the bytecode address returned to when leaving the new scope
* @return an object representing the newly entered scope
*/
public JsrScope push(int returnBci) {
public JsrScope push(int returnBci, BciBlock newJsrEntryBlock) {
if (returnBci == 0) {
throw new IllegalArgumentException("A bytecode subroutine cannot have a return address of 0");
}
if (returnBci < 1 || returnBci > 0xFFFF) {
throw new IllegalArgumentException("Bytecode subroutine return address cannot be encoded as a char: " + returnBci);
}
return new JsrScope(returnBci, this);
return new JsrScope(returnBci, newJsrEntryBlock, this);
}

public JsrScope push(int returnBci) {
return push(returnBci, null);
}

/**
Expand All @@ -85,13 +98,13 @@ public boolean isEmpty() {
* {@code int[]} with {@code value.chars().toArray()}.
*/
public String getAncestry() {
StringBuilder sb = new StringBuilder();
String result = "";
for (JsrScope s = this; s != null; s = s.parent) {
if (!s.isEmpty()) {
sb.append(s.returnAddress);
result = s.returnAddress + result;
}
}
return sb.reverse().toString();
return result;
}

/**
Expand Down

0 comments on commit 47e18e0

Please sign in to comment.