RFR: 8276836: Error in javac caused by switch expression without result expressions: Internal error: stack sim error
Jan Lahoda
jlahoda at openjdk.java.net
Mon Nov 29 18:46:08 UTC 2021
On Thu, 11 Nov 2021 13:47:17 GMT, Guoxiong Li <gli at openjdk.org> wrote:
> Hi all,
>
> The method `Gen#visitSwitchExpression` would switch code generation off by using the method `Code#markDead` when it meets the code like `throw new RuntimeException()`. Then the method `Gen#completeBinop` won't generate the expected code and wiil let the left operand stay in the stack without handling it.
>
> This patch pops the left operand from the stack to solve this issue. And the corresponding test is added.
>
> Thanks for taking the time to review.
>
> Best Regards,
> -- Guoxiong
Thanks for looking into this and sorry for trouble.
One possible alternative that might work would be to put this only into `doHandleSwitchExpression`:
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
index 9ef735e1543..f5d6430eecb 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
@@ -1237,6 +1237,9 @@ public class Gen extends JCTree.Visitor {
try {
handleSwitch(tree, tree.selector, tree.cases, tree.patternSwitch);
} finally {
+ if (!code.isAlive()) {
+ code.state.pop(code.state.stacksize);
+ }
code.setLetExprStackPos(prevLetExprStart);
}
} finally {
But I am not sure offhand if it would not have some problems.
But, I wonder if we need to fix the simulated stack at all (as it won't be completely sensible in anyway). Maybe all we need is to disable the assertion?
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
index 9ef735e1543..08b075822c6 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
@@ -971,7 +971,7 @@ public class Gen extends JCTree.Visitor {
genStat(tree.body, env);
}
- if (code.state.stacksize != 0) {
+ if (code.state.stacksize != 0 && code.isAlive()) {
log.error(tree.body.pos(), Errors.StackSimError(tree.sym));
throw new AssertionError();
}
In general, I am afraid there needs to be more testing:
- tests for compound assignments, roughly the same as for binary operators
- longer chains on binary operators - e.g. `4 + switch () {...} + 5`, `4 + switch () {...} + switch () {...}`, etc. (three operands would probably be enough)
- various other operand types - method invocations, array dereferences
- tests that employ boolean conditions (inside an `if` condition, for example)
- the tests should not only compile the code - they should also run it, and verify the resulting behavior
- possibly use such switch that does not return
I can help with writing some tests, if needed.
-------------
PR: https://git.openjdk.java.net/jdk/pull/6350
More information about the compiler-dev
mailing list