RFR: JDK-8222795: post inc operator inside compute function of HashMap results in Exception

Vicente Romero vicente.romero at oracle.com
Wed May 8 22:25:29 UTC 2019


Please review fix for regression [1] at [2]. The regression was 
introduced by [3] which introduced the support for switch expressions. 
The compiler is failing with an assertion error for code:

import java.util.HashMap;
import java.util.Map;

public class LetExpressionAssertionTest {
     void m() {
         Map<String, Integer> m = new HashMap<>();
         m.put("a",2);
         m.compute("a", (k, v) -> (v > 5) ? v-- : v++);
     }
}

Where `v--` and `v++` are converted to let expressions. Recall that in 
this case `v` is of type integer so the let expressions are similar to:

`(let /*synthetic*/ final Integer $373182087 = v in (let v = 
Integer.valueOf((int)(v.intValue() - 1)); in $373182087))`

notice the cast, the ::intValue invocation etc.

This patch, [3], also made some changes related to let expressions. In 
particular it changed a common idiom in Gen:

`Assert.check(code.state.stacksize == 0);` by:
Assert.check(code.isStatementStart());

where Code::isStatementStart is:

public boolean isStatementStart() {
     return !alive ||state.stacksize ==letExprStackPos;
}

which is basically the same check as before, modulo the `alive` check. 
The problem is that at Gen::visitVarDef we had a more relaxed assertion 
check before [3]:

Assert.check(letExprDepth != 0 || code.state.stacksize == 0); which was 
also substituted by:
Assert.check(code.isStatementStart());

this implies a semantic change. In the old code `letExprDepth` was just 
a counter of "nestedness" of let expressions and the original condition 
in Gen::visitVarDef was mostly to check if the compiler was generating a 
let expression or not. Enforcing that code.state.stacksize has to be 
equal to the stack position of the let expression when we started 
generating the let expression, which is what the current assertion is 
checking is a too strong condition. Which can be false if, as in this 
case, the let expression has several method invocations inside, etc that 
will move the stack as get generated. This patch is proposing going back 
to a more relaxed assertion at Gen::visitVarDef,

Thanks,
Vicente

[1] https://bugs.openjdk.java.net/browse/JDK-8222795
[2] http://cr.openjdk.java.net/~vromero/8222795/webrev.00/
[3] https://bugs.openjdk.java.net/browse/JDK-8206986
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20190508/1ee5c8ee/attachment.html>


More information about the compiler-dev mailing list