JDK-8074487 : Static analysis of IfNode should consider terminating branches
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2015-03-05
  • Updated: 2015-09-29
  • Resolved: 2015-03-06
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.

To download the current JDK release, click here.
JDK 8 JDK 9
8u60Fixed 9 b55Fixed
Description
Static analysis of IfNode doesn't properly recognize terminating branches, resulting in unnecessary widening of some variables. E.g. Octane Crypto benchmark contains this code in its bnpFromString function: 

  var k;
  if(b == 16) k = 4;
  else if(b == 8) k = 3;
  else if(b == 256) k = 8; // byte array
  else if(b == 2) k = 1;
  else if(b == 32) k = 5;
  else if(b == 4) k = 2;
  else { this.fromRadix(s,b); return; }
  ...
Currently, the type of k will be OBJECT after the if/elseif statements. This is due to the fact that the analysis doesn't recognize that the only branch that doesn't set it to INT also terminates, therefore it is impossible to exit the last else branch with k being UNDEFINED.
Comments
I run octane with --print-lower-parse before and after the changes and read through their diff (both resulting text files are around 54MB). Aside from bnpFromString in crypto, notable eliminations also happened in: tautologyp_nboyer: sc_x_11 variable _ZN16btCollisionWorld18addCollisionObjectEP17btCollisionObjectss: r10 variable _ZN16btDbvtBroadphase7setAabbEP17btBroadphaseProxyRK9btVector3S4_P12btDispatcher: r10 variable pdfjsWrapper$FlateStreamClosure$FlateStream_readBlock:repeatLength, bitsLength, what, bitsOffset variables pdfjsWrapper$PartialEvaluatorClosure$PartialEvaluator_getOperatorList: L:splay_: left, current variables. In many cases a pattern like var x = someDouble; for(...) { if (pred) { x = someInt; } else { ... break or return; } } moved the conversion from behind the end of the true branch to the back edge of the loop. Functionally it doesn't matter, both cases are equally good. E.g. it used to be var x = someDouble; for(...) { if (pred) { x = someInt; } [x:I->D] else { ... break or return; } } and now it is var x = someDouble; for(...) { if (pred) { x = someInt; } else { ... break or return; } } [x:I->D] What is important is that types never got worse, and also that often when we eliminate an overly conservative object promotion for a local variabe, other local variables that depend on that variable will also become narrower (e.g. "sh" in bnpFromString depended on "k", but there are examples in other octanes).
05-03-2015