JDK-8073670 : TypeF::eq and TypeD::eq do not handle NaNs correctly
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8u112,9
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2015-02-23
  • Updated: 2018-02-15
  • Resolved: 2015-02-28
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
8u162Fixed 9 b55Fixed
Description
Hi Chris,

i"ve found a problem with differet kinds of NaN nodes in the C2 compiler. In C2 different NaN nodes are merged together where in C1 and interpreter it does not and treats them as different NaNs. To make C2 consistent to C1, i've prepared this patch

The java spec does not define any behavior how the NaNs need to be normalized. But we can be sure, that we hardly break any existing javacode which relies on this behavior, because the behavior of C1 and C2 generated code diverges.

Test to run: java -cp ./bin/ -Xcomp -XX:-TieredCompilation NaNTest

Expected result:
Test Successful

Error result:
Exception in thread "main" java.lang.InternalError: 0x7ff00000000007a2 0x7ff00000000007a2
       at NaNTest.main(NaNTest.java:26)


Patch to fix this issue:

diff -r b300d1f6e817 src/share/vm/opto/type.cpp
--- a/src/share/vm/opto/type.cpp        Fri Jan 30 20:52:39 2015 +0100
+++ b/src/share/vm/opto/type.cpp        Mon Feb 16 16:01:35 2015 +0100
@@ -1092,8 +1092,10 @@
bool TypeD::eq( const Type *t ) const {
  if( g_isnan(_d) ||
      g_isnan(t->getd()) ) {
-    // One or both are NANs.  If both are NANs return true, else false.
-    return (g_isnan(_d) && g_isnan(t->getd()));
+    // it is important, when two different NaNs are used in one method, the NaNs are treated
+    // as different NaNs (as C1 does)
+    jdouble td = t->getd();
+    return *((jlong*)(&_d)) == *(jlong*)(&td);
  }
  if (_d == t->getd()) {
    // (NaN is impossible at this point, since it is not equal even to itself)

Stefan
Comments
Fix verified by regression test.
07-08-2017

Related?
24-02-2015

ILW=Possible wrong fp behaviour, C2 fp code - haven't seen, none=HL/MH=P2/P1=P1
24-02-2015

[~jrose] said: I agree, and check the hash methods too. It's not the business of the compiler to implement floating point NaN folding. I'd be just as happy to see the bitwise comparison used uniformly on those code paths, even for non-NaNs.
23-02-2015

[~kvn] said: I am fine with this fix. TypeF:eq() should be fixed too then.
23-02-2015