JDK-8067774 : Local variable type calculation mismatch
Type:Bug
Component:core-libs
Sub-Component:jdk.nashorn
Affected Version:9
Priority:P3
Status:Resolved
Resolution:Fixed
OS:generic
CPU:generic
Submitted:2014-12-17
Updated:2015-09-29
Resolved:2014-12-18
The Version table provides details related to the release that this issue/RFE will be addressed.
Unresolved : Release in which this issue/RFE will be addressed. Resolved: Release in which this issue/RFE has been resolved. Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.
This very simple program throws an assertion in code generator about trying to load an uninitialized slot:
(function (p) {
var a, b;
a = p ? ((b = 0), b) : 0;
return a;
})(true);
Comments
To trigger the assert, the combination of a control flow in expression (?:), conditional assignment in only one branch from undefined to int, comma operator for subsequent read of the assignment, are all needed.
The issue here is that while the expression assigned to "a" will always evaluate to int, the type of the assignment will still be considered to be object, because we ask the expression to separately evaluate its type after it has already been evaluated once. The current evaluation algorithm for an assignment is:
- walk the RHS (in our case the "p ? ..." ternary) and calculate local variable types. In our case, the control flow join point at the end of the ternary widens "b" to Object, as it can be undefined if the false branch was taken.
- ask RHS to evaluate its type given the current local variable types. The comma operator will return the type of "b", which at this moment is Object. That's obviously wrong, as it can be statically known that at that point it was actually int. This results in the whole RHS type evaluating to Object.
- consider Object to be the value of "a" afterwards.
The code generator will bomb because we:
- produce an integer expression, but throw it away instead of assigning to "a" because we (sort-of) correctly recognize it will never be read as int
- try to read the object slot for "a", which is uninitialized.
Proposed fix: instead of trying to re-calculate the type of expressions after they have been evaluated, simulate a type stack in LocalVariableTypesCalculator as the expression AST is walked. The current approach ��� as demonstrated ��� fails if the expression has any conditional assignment to local variables that change their type.