Java 12: javac crash with switch expression containing try-catch-finally

Remi Forax forax at univ-mlv.fr
Thu Mar 21 16:02:35 UTC 2019


That's interesting,
it means that the sequence
  switch(0) { default -> { ... }}
can transform any statement syntax into an expression.
  
so
  let x = init in expression
can be written
  switch(0) { default -> { try(var x = init) { break expression; } }}

so instead of point.getX() * point.getX() which is clearly not effective,
one can now write
  switch(0) { default -> { try(var x = point.getX()) { break x * x; } }}
which is obviously far better

Rémi

----- Mail original -----
> De: "B. Blaser" <bsrbnd at gmail.com>
> À: "Tagir Valeev" <amaembo at gmail.com>
> Cc: "compiler-dev" <compiler-dev at openjdk.java.net>
> Envoyé: Jeudi 21 Mars 2019 16:37:04
> Objet: Re: Java 12: javac crash with switch expression containing try-catch-finally

> Hi,
> 
> On Wed, 20 Mar 2019 at 05:11, Tagir Valeev <amaembo at gmail.com> wrote:
>>
>> Hello!
>>
>> I just wanted to draw your attention to the issue JDK-8220018. I
>> reported it several weeks ago, but saw no reaction. Probably I failed
>> to fill all the necessary fields. The problem is still actual in java
>> 12 GA:
>>
>> // SwTest.java
>> public class SwTest {
>>     public static void main(String[] args) {
>>         System.out.println(switch (0) {
>>            default -> {
>>                try {
>>                    break 1;
>>                }
>>                catch (Exception ex) {
>>                    break 2;
>>                }
>>                finally {
>>                    break 3;
>>                }
>>            }
>>         });
>>     }
>> }
> 
> Is somebody already looking at this?
> 
> This is an interesting issue because when generating the final 'break
> 3', an operand stack size mismatch occurs due to the other already
> emitted breaks.
> I tried the following tweak to pop the unnecessary operands before
> generating the last break, does this look reasonable (langtools:tier1
> being OK)?
> 
> 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,15 @@
>         return !alive || state.stacksize == letExprStackPos;
>     }
> 
> +    public void makeStatementStart() {
> +        if (state.stacksize > letExprStackPos) {
> +            int toPop = state.stacksize - letExprStackPos;
> +            for (int i=0; i<toPop; i++) {
> +                emitop0(pop);
> +            }
> +        }
> +    }
> +
> /**************************************************************************
>  * 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
> @@ -1704,7 +1704,7 @@
>     }
> 
>     public void visitBreak(JCBreak tree) {
> -        Assert.check(code.isStatementStart());
> +        code.makeStatementStart();
>         final Env<GenContext> targetEnv;
>         if (tree.isValueBreak()) {
>              //restore stack as it was before the switch expression:


More information about the compiler-dev mailing list