RFR; JDK-8214031: Assertion error in value break statement with conditional operator in switch expression

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Nov 28 12:12:46 UTC 2018


Hi Jan,
the patch looks very good and, albeit complex, I don't think there's 
another way to implement shortcircuiting of boolean switch expression 
w/o going deep in Gen (which is what this patch does). So well done.

 From a code perspective I have only minor comments, as the code is 
generally well done:

1) In Flow, since now you are making AssignAnalyzer also extends from 
BaseAnalyzer<PendingExit> (used to be BaseAnalyzer<AssignExit>), I think 
there is no need now for having a type parameter in BaseAnalyzer. Let 
all exits be PendingExit - then subclasses can come up with variants 
(like AssignExit) when needed. But it seems like the 1-1 relationship 
between analyzer type and exit type is gone and the code should probably 
be more upfront about that.

2) The valueBreakHandler abstraction in Gen is nice, but I wonder if the 
code would be clearer by encoding the desired logic directly in 
visitBreak. That is, visitBreak could fetch the switch expression it 
points to, and determine whether we are inside a 'cond' or not, and then 
act accordingly. I think that, with a couple of Gen instance fields 
(shared trueChain/falseChain), you could be able to get there. Not 100% 
sure it will make the code better, but I thought it could be worth a try.

3) In the test DefiniteAssignment1.java (and also, but to lesser extent, 
DefiniteAssignment1.java)  I guess it would also be nice to test some && 
condition in the break expression - e.g.

true && (x = 1)

Also, might be worth replacing the true with some other variable which 
the compiler doesn't know to be true statically (as that affects code 
generation).

Cheers
Maurizio

On 27/11/2018 20:21, Jan Lahoda wrote:
> Hi,
>
> javac does not handle switch expressions that return booleans 
> correctly. According to the spec, javac should track definite 
> [un]assignment when true/false for switch expressions, but fails to do 
> so. Moreover, for more complex code, like:
>
> int v = ...;
> int x;
> boolean b = switch (v) {
>      case 0: x = 12; break true;
>      case 1: x = 13; break true;
>      default: break false;
> } && x == 12;
>
> The current switch expression desugaring is not powerful enough to 
> generate valid bytecode for this input. The issue is that the current 
> desugaring will translate the switch expression into code like:
> (
>  boolean $result;
>  switch (v) {
>      case 0: x = 12; $result = true; break;
>      case 1: x = 13; $result = true; break;
>      default: $result = false; break;
>  }
>  $result   //"return" expression
> ) && x == 12
>
> But by assigning the true/false result to a variable, we are loosing 
> track of which variables are assigned (when true/false) and which are 
> not. The bytecode needs to ensure the "x == 12" is jumped over when 
> the switch expression's value is false, and that, I believe, is not 
> possible when desugaring in Lower.
>
> So, the proposed fix is to avoid desugaring in Lower, letting switch 
> expressions go to Gen and produce bytecode for them, including 
> handling them in Gen.genCond for true/false switch expressions. This 
> is mostly modelled after the conditional expression handling. Some 
> generalizations in Lower are required as well, to handle String and 
> enum switch expressions. Handling of definite assignment in Flow is 
> fixed as well.
>
> JBS: https://bugs.openjdk.java.net/browse/JDK-8214031
> Webrev: http://cr.openjdk.java.net/~jlahoda/8214031/webrev.00/
>
> Any feedback is welcome!
>
> Thanks,
>    Jan


More information about the compiler-dev mailing list