> FloatEntryImpl.equals() and DoubleEntryImpl.equals() used == for comparison, 
> which returns false for NaN == NaN per IEEE 754. This caused two different 
> FloatEntry/DoubleEntry objects holding NaN to not be considered equal, 
> violating the equals/hashCode contract (same hashCode but equals returns 
> false).
> 
> Similarly, SplitConstantPool.findFloatEntry() and findDoubleEntry() used == 
> to match values, so NaN entries could never be found in the pool, causing 
> every floatEntry(Float.NaN) or doubleEntry(Double.NaN) call to create a 
> duplicate entry and bloat the constant pool.
> 
> Fix by using Float.floatToRawIntBits() and Double.doubleToRawLongBits() for 
> bitwise comparison, which correctly handles NaN and also properly 
> distinguishes +0.0 from -0.0.

Shaojin Wen has refreshed the contents of this pull request, and previous 
commits have been removed. The incremental views will show differences compared 
to the previous content of the PR. The pull request contains seven new commits 
since the last revision:

 - Simplify findEntry loop: use for with direct width increment
   
   Change from while loop to for loop, moving the width increment
   directly into the loop body for better readability.
   
   Co-Authored-By: rgiulietti
 - Refactor findEntry loop to use while with direct width increment
   
   Change the loop from for-with-post-increment to a while loop that
   increments by e.width() directly, making the code clearer.
 - Add tests for Float/Double NaN with different bit patterns
   
   Since the code uses raw bit variants (floatToRawIntBits/doubleToRawLongBits)
   when converting floating-point values to integral bits for hashCode and
   equals, the tests should cover the cases of NaNs with different bit patterns.
   
   - testFloatNaNWithDifferentBitPatternsAreDistinct: Verify that NaNs with
     different bit patterns create distinct constant pool entries
   - testDoubleNaNWithDifferentBitPatternsAreDistinct: Same for Double
   - testFloatNaNWithDifferentBitPatternsAreNotEqual: Verify that NaNs with
     different bit patterns are not equal
   - testDoubleNaNWithDifferentBitPatternsAreNotEqual: Same for Double
   - testFloatNaNWithSameBitPatternIsDeduplicated: Verify that NaNs with the
     same bit pattern are deduplicated
   - testDoubleNaNWithSameBitPatternIsDeduplicated: Same for Double
 - Fix SplitConstantPool lookup hash to match updated entry hashCode
   
   The previous commit updated FloatEntryImpl/DoubleEntryImpl to use
   raw bits for hashCode, but findFloatEntry/findDoubleEntry still
   used Float.hashCode/Double.hashCode for lookup. This mismatch would
   cause non-canonical NaN entries to never be found in the map.
 - Use raw bits for Float/Double constant pool entry hashCode
   
   Update hashCode to use floatToRawIntBits/doubleToRawLongBits,
   consistent with the equals methods, so that different NaN bit
   patterns hash to different buckets instead of always colliding.
 - Add tests for Float/Double NaN constant pool equality and deduplication
   
   Test coverage for NaN and +/-0.0 handling in constant pool entries:
   - NaN entries are deduplicated (same index from same builder)
   - NaN entries from different pools are equals()
   - +0.0 and -0.0 are kept as distinct entries
   - Normal float/double deduplication still works
   - NaN values survive class file round-trip and rebuild
 - Fix Float/Double NaN constant pool entry equality and deduplication
   
   FloatEntryImpl.equals() and DoubleEntryImpl.equals() used == for
   comparison, which returns false for NaN == NaN per IEEE 754. This
   caused two different FloatEntry/DoubleEntry objects holding NaN to
   not be considered equal, violating the equals/hashCode contract
   (same hashCode but equals returns false).
   
   Similarly, SplitConstantPool.findFloatEntry() and findDoubleEntry()
   used == to match values, so NaN entries could never be found in the
   pool, causing every floatEntry(Float.NaN) or doubleEntry(Double.NaN)
   call to create a duplicate entry and bloat the constant pool.
   
   Fix by using Float.floatToRawIntBits() and Double.doubleToRawLongBits()
   for bitwise comparison, which correctly handles NaN and also properly
   distinguishes +0.0 from -0.0.

-------------

Changes:
  - all: https://git.openjdk.org/jdk/pull/30196/files
  - new: https://git.openjdk.org/jdk/pull/30196/files/34f4d54e..fd2dd7a0

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=30196&range=04
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=30196&range=03-04

  Stats: 0 lines in 0 files changed: 0 ins; 0 del; 0 mod
  Patch: https://git.openjdk.org/jdk/pull/30196.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/30196/head:pull/30196

PR: https://git.openjdk.org/jdk/pull/30196

Reply via email to