Java 12: javac crash with switch expression containing try-catch-finally
Jan Lahoda
jan.lahoda at oracle.com
Mon Mar 25 13:27:12 UTC 2019
Hi Bernard,
My current thinking is that we will need to restore the stack right
before the final goto for the given break (which can be skipped if
code.isAlive() == false).
I've put my current patch here (incl. test) (I wasn't running other
tests on this patch yet, though):
http://cr.openjdk.java.net/~jlahoda/8220018/8220018
This does not cover the switch expressions over booleans yet, that is
something I am looking at right now.
Jan
On 23.3.2019 18:24, B. Blaser wrote:
> Hi Jan,
>
> On Thu, 21 Mar 2019 at 18:24, Jan Lahoda <jan.lahoda at oracle.com> wrote:
>>
>> Hi Bernard,
>>
>> I was peeking at this, and expected to start to work on this.
>>
>> I do agree we will need to strip the extra values from the stack, but we
>> may also need to set the letExprStackPos at some point.
>>
>> Jan
>
> Right, this refers to Tagir's second example:
>
> public static void test2() {
> System.out.println(switch (0) {
> default -> {
> try(Stream<?> s = Stream.empty()) {
> break 1;
> }
> }
> });
> }
>
> The following patch fixes both cases, does this look more reasonable?
>
> Thanks,
> Bernard
>
> diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
> b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
> @@ -1223,6 +1223,18 @@
> return !alive || state.stacksize == letExprStackPos;
> }
>
> + private boolean valueBreak = false;
> +
> + public boolean setValueBreak(boolean set) {
> + boolean b = valueBreak;
> + valueBreak = set;
> + return b;
> + }
> +
> + public boolean isValueBreak() {
> + return valueBreak;
> + }
> +
> /**************************************************************************
> * Stack map generation
> *************************************************************************/
> 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
> --- 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
> @@ -1201,10 +1201,12 @@
> }
> }
> int prevLetExprStart =
> code.setLetExprStackPos(code.state.stacksize);
> + boolean prevValueBreak = code.setValueBreak(false);
> try {
> handleSwitch(tree, tree.selector, tree.cases);
> } finally {
> code.setLetExprStackPos(prevLetExprStart);
> + code.setValueBreak(prevValueBreak);
> }
> } finally {
> stackBeforeSwitchExpression = prevStackBeforeSwitchExpression;
> @@ -1707,9 +1709,14 @@
> Assert.check(code.isStatementStart());
> final Env<GenContext> targetEnv;
> if (tree.isValueBreak()) {
> - //restore stack as it was before the switch expression:
> - for (LocalItem li : stackBeforeSwitchExpression) {
> - li.load();
> + if (code.isValueBreak()) {
> + code.emitop0(pop);
> + }
> + else {
> + //restore stack as it was before the switch expression:
> + for (LocalItem li : stackBeforeSwitchExpression) {
> + li.load();
> + }
> }
> if (inCondSwitchExpression) {
> CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
> @@ -1732,7 +1739,17 @@
> } else {
> genExpr(tree.value, pt).load();
> code.state.forceStackTop(tree.target.type);
> - targetEnv = unwindBreak(tree);
> +
> + int prevLetStackPos =
> code.setLetExprStackPos(code.state.stacksize);
> + boolean prevValueBreak = code.setValueBreak(true);
> + try {
> + targetEnv = unwindBreak(tree);
> + }
> + finally {
> + code.setLetExprStackPos(prevLetStackPos);
> + code.setValueBreak(prevValueBreak);
> + }
> +
> targetEnv.info.addExit(code.branch(goto_));
> }
> } else {
>
More information about the compiler-dev
mailing list