-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8358801: javac produces class that does not pass verifier. #25849
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
👋 Welcome back jlahoda! A progress list of the required criteria for merging this PR into |
@lahodaj This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 139 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
//in the defined variables for jumps that go outside of this let | ||
//expression: | ||
undefineVariablesInChain(result.falseJumps, limit); | ||
undefineVariablesInChain(result.trueJumps, limit); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move this truncation of variables to CondItem itself? I moved the truncation of continue/break to GenContext and found that helpful, maybe we can require an extra int arg for makeCondItem(int, Chain, Chain)
for the limit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, personally: while doing it here is not perfect (mostly because I would prefer if we didn't have to do this bookkeeping at all), it seems to me like a fairly local property - the let expr starts, and then does its own cleanup. It already calls code.endScopes(limit);
above this change, so this is basically an extension to that. If we did it at makeCondItem
time, we would need to pass the limit everywhere makeCondItem
is called, making it non-local. Many parts of the code would now suddenly have to care whether the node is inside a let expression. That feels to me like increasing complexity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable. I asked this because I could see undefineVariablesInChain
being used elsewhere, such as GenContext::addCont/addExit
. We should probably update those two sites, as I didn't consider a linked list chain being used in those sites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or you can even make it an instance method on Chain - the limit can be considered an intrinsic property to where the chain leads to, except this information is not available when a chain is constructed (should it be?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pesky issue and a relatively clean solution (given the circumstances). I tend to agree with how the fix decided to treat this as a special case for when let expressions are used inside a conditional, which seems to be where the issue really stems from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good. We can update GenContext::addCont/addExit to use the new undefineVariablesInChain
later.
Consider code like:
javac will produce code that won't (rightfully) pass the verifier:
Now, the problem, as far as I can tell, is this: javac will desugar the pattern matching instanceof along the lines of:
(
$temp
is register/local variable number 4)specifically, note the
&&
in the middle of the let expression, and that the expression is in the conditional position. What happens here is that at the position of the&&
will basically generate a jump to skip the if (i.e. a jump whose target is just behind the if, for the case where the...
left to it evaluates to false). The problem here is that at the source position of the jump, the variable$temp
is defined/has value. And the set of variables which are defined/have value is stored at the moment of jump, and restored at the target place of the jump. I.e. in this case, javac will think variable number 4 has a value.This, by itself, while it does not seem right, but does not lead to a breakage, as the variable is not in
code.lvar
, and hence javac will ignore it.The problem is that inside the first case, variable number 4 is declared, and
lvar
is filled for it. In the first case, it is still not problematic, as the variable is defined/has value there as well. But, for the default case, the variable still has anlvar
entry (as the variable is still declared, just should be unassigned), but the defined/has value flag stored earlier is restored again. So, javac thinks the variable is fully valid, and generates a bogus StackMapTable entry listing the variable, leading to the verifier failure.I think the source of all trouble is the wrong "defined" flag. The solution in this PR is to make sure the variables declared by the let expression are removed from the
defined
variables stored in the conditional jump chains.Note this only applies to jumps that go outside of the left expression (and hence outside of the scope of the variable), internal jumps inside the let expression, if there would be any, shouldn't be affected.
Progress
Warning
8358801: javac produces class that does not pass verifier.
Found leading lowercase letter in issue title for
8358801: javac produces class that does not pass verifier.
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/25849/head:pull/25849
$ git checkout pull/25849
Update a local copy of the PR:
$ git checkout pull/25849
$ git pull https://git.openjdk.org/jdk.git pull/25849/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 25849
View PR using the GUI difftool:
$ git pr show -t 25849
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/25849.diff
Using Webrev
Link to Webrev Comment