Skip to content

Commit

Permalink
8332106: VerifyError when using switch pattern in this(...) or super(…
Browse files Browse the repository at this point in the history
…...)

Reviewed-by: abimpoudis, vromero
  • Loading branch information
lahodaj committed May 24, 2024
1 parent da3001d commit af056c1
Show file tree
Hide file tree
Showing 3 changed files with 450 additions and 15 deletions.
65 changes: 50 additions & 15 deletions src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ protected Gen(Context context) {
Chain switchExpressionFalseChain;
List<LocalItem> stackBeforeSwitchExpression;
LocalItem switchResult;
Set<JCMethodInvocation> invocationsWithPatternMatchingCatch = Set.of();
ListBuffer<int[]> patternMatchingInvocationRanges;
PatternMatchingCatchConfiguration patternMatchingCatchConfiguration =
new PatternMatchingCatchConfiguration(Set.of(), null, null, null);

/** Cache the symbol to reflect the qualifying type.
* key: corresponding type
Expand Down Expand Up @@ -1087,21 +1087,31 @@ public void visitBlock(JCBlock tree) {
}

private void visitBlockWithPatterns(JCBlock tree) {
Set<JCMethodInvocation> prevInvocationsWithPatternMatchingCatch = invocationsWithPatternMatchingCatch;
ListBuffer<int[]> prevRanges = patternMatchingInvocationRanges;
State startState = code.state.dup();
PatternMatchingCatchConfiguration prevConfiguration = patternMatchingCatchConfiguration;
try {
invocationsWithPatternMatchingCatch = tree.patternMatchingCatch.calls2Handle();
patternMatchingInvocationRanges = new ListBuffer<>();
patternMatchingCatchConfiguration =
new PatternMatchingCatchConfiguration(tree.patternMatchingCatch.calls2Handle(),
new ListBuffer<int[]>(),
tree.patternMatchingCatch.handler(),
code.state.dup());
internalVisitBlock(tree);
} finally {
generatePatternMatchingCatch(env);
patternMatchingCatchConfiguration = prevConfiguration;
}
}

private void generatePatternMatchingCatch(Env<GenContext> env) {
if (patternMatchingCatchConfiguration.handler != null &&
!patternMatchingCatchConfiguration.ranges.isEmpty()) {
Chain skipCatch = code.branch(goto_);
JCCatch handler = tree.patternMatchingCatch.handler();
code.entryPoint(startState, handler.param.sym.type);
genPatternMatchingCatch(handler, env, patternMatchingInvocationRanges.toList());
JCCatch handler = patternMatchingCatchConfiguration.handler();
code.entryPoint(patternMatchingCatchConfiguration.startState(),
handler.param.sym.type);
genPatternMatchingCatch(handler,
env,
patternMatchingCatchConfiguration.ranges.toList());
code.resolve(skipCatch);
invocationsWithPatternMatchingCatch = prevInvocationsWithPatternMatchingCatch;
patternMatchingInvocationRanges = prevRanges;
}
}

Expand Down Expand Up @@ -1926,12 +1936,26 @@ public void visitApply(JCMethodInvocation tree) {
if (!msym.isDynamic()) {
code.statBegin(tree.pos);
}
if (invocationsWithPatternMatchingCatch.contains(tree)) {
if (patternMatchingCatchConfiguration.invocations().contains(tree)) {
int start = code.curCP();
result = m.invoke();
patternMatchingInvocationRanges.add(new int[] {start, code.curCP()});
patternMatchingCatchConfiguration.ranges().add(new int[] {start, code.curCP()});
} else {
result = m.invoke();
if (msym.isConstructor() && TreeInfo.isConstructorCall(tree)) {
//if this is a this(...) or super(...) call, there is a pending
//"uninitialized this" before this call. One catch handler cannot
//handle exceptions that may come from places with "uninitialized this"
//and (initialized) this, hence generate one set of handlers here
//for the "uninitialized this" case, and another set of handlers
//will be generated at the end of the method for the initialized this,
//if needed:
generatePatternMatchingCatch(env);
result = m.invoke();
patternMatchingCatchConfiguration =
patternMatchingCatchConfiguration.restart(code.state.dup());
} else {
result = m.invoke();
}
}
}

Expand Down Expand Up @@ -2555,4 +2579,15 @@ void addCont(Chain c) {
}
}

record PatternMatchingCatchConfiguration(Set<JCMethodInvocation> invocations,
ListBuffer<int[]> ranges,
JCCatch handler,
State startState) {
public PatternMatchingCatchConfiguration restart(State newState) {
return new PatternMatchingCatchConfiguration(invocations(),
new ListBuffer<int[]>(),
handler(),
newState);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,16 @@ public void visitLambda(JCLambda tree) {
}
}

/**
* Is the given method invocation an invocation of this(...) or super(...)?
*/
public static boolean isConstructorCall(JCMethodInvocation invoke) {
Name name = TreeInfo.name(invoke.meth);
Names names = name.table.names;

return (name == names._this || name == names._super);
}

/** Finds super() invocations and translates them using the given mapping.
*/
public static void mapSuperCalls(JCBlock block, Function<? super JCExpressionStatement, ? extends JCStatement> mapper) {
Expand Down
Loading

1 comment on commit af056c1

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.