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