Changeset 244760 in webkit


Ignore:
Timestamp:
Apr 29, 2019 3:25:03 PM (5 years ago)
Author:
ysuzuki@apple.com
Message:

normalizeMapKey should normalize NaN to one PureNaN bit pattern to make MapHash same
https://bugs.webkit.org/show_bug.cgi?id=197362

Reviewed by Saam Barati.

JSTests:

  • stress/map-with-nan.js: Added.

(shouldBe):
(div):
(NaN1):
(NaN2):
(NaN3):
(NaN4):
(NaN1NoInline):
(NaN2NoInline):
(NaN3NoInline):
(NaN4NoInline):
(test1):
(test2):
(test3):
(test4):

  • stress/set-with-nan.js: Added.

(shouldBe):
(div):
(NaN1):
(NaN2):
(NaN3):
(NaN4):
(NaN1NoInline):
(NaN2NoInline):
(NaN3NoInline):
(NaN4NoInline):
(test2):
(test4):

Source/JavaScriptCore:

Our Map/Set's hash algorithm relies on the bit pattern of JSValue. So our Map/Set has
normalization of the key, which normalizes Int32 / Double etc. But we did not normalize
pure NaNs into one canonicalized pure NaN. So we end up having multiple different pure NaNs
in one Map/Set. This patch normalizes NaN into one jsNaN(), which uses PNaN for the representation.

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileNormalizeMapKey):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNormalizeMapKey):

  • runtime/HashMapImpl.h:

(JSC::normalizeMapKey):

Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r244713 r244760  
     12019-04-29  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        normalizeMapKey should normalize NaN to one PureNaN bit pattern to make MapHash same
     4        https://bugs.webkit.org/show_bug.cgi?id=197362
     5
     6        Reviewed by Saam Barati.
     7
     8        * stress/map-with-nan.js: Added.
     9        (shouldBe):
     10        (div):
     11        (NaN1):
     12        (NaN2):
     13        (NaN3):
     14        (NaN4):
     15        (NaN1NoInline):
     16        (NaN2NoInline):
     17        (NaN3NoInline):
     18        (NaN4NoInline):
     19        (test1):
     20        (test2):
     21        (test3):
     22        (test4):
     23        * stress/set-with-nan.js: Added.
     24        (shouldBe):
     25        (div):
     26        (NaN1):
     27        (NaN2):
     28        (NaN3):
     29        (NaN4):
     30        (NaN1NoInline):
     31        (NaN2NoInline):
     32        (NaN3NoInline):
     33        (NaN4NoInline):
     34        (test2):
     35        (test4):
     36
    1372019-04-26  Commit Queue  <commit-queue@webkit.org>
    238
  • trunk/Source/JavaScriptCore/ChangeLog

    r244756 r244760  
     12019-04-29  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        normalizeMapKey should normalize NaN to one PureNaN bit pattern to make MapHash same
     4        https://bugs.webkit.org/show_bug.cgi?id=197362
     5
     6        Reviewed by Saam Barati.
     7
     8        Our Map/Set's hash algorithm relies on the bit pattern of JSValue. So our Map/Set has
     9        normalization of the key, which normalizes Int32 / Double etc. But we did not normalize
     10        pure NaNs into one canonicalized pure NaN. So we end up having multiple different pure NaNs
     11        in one Map/Set. This patch normalizes NaN into one jsNaN(), which uses PNaN for the representation.
     12
     13        * dfg/DFGSpeculativeJIT.cpp:
     14        (JSC::DFG::SpeculativeJIT::compileNormalizeMapKey):
     15        * ftl/FTLLowerDFGToB3.cpp:
     16        (JSC::FTL::DFG::LowerDFGToB3::compileNormalizeMapKey):
     17        * runtime/HashMapImpl.h:
     18        (JSC::normalizeMapKey):
     19
    1202019-04-29  Alex Christensen  <achristensen@webkit.org>
    221
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r244193 r244760  
    1171511715
    1171611716    CCallHelpers::JumpList passThroughCases;
     11717    CCallHelpers::JumpList doneCases;
    1171711718
    1171811719    passThroughCases.append(m_jit.branchIfNotNumber(keyRegs, scratchGPR));
     
    1172411725    unboxDouble(keyRegs.tagGPR(), keyRegs.payloadGPR(), doubleValueFPR, tempFPR);
    1172511726#endif
    11726     passThroughCases.append(m_jit.branchIfNaN(doubleValueFPR));
    11727 
     11727    auto notNaN = m_jit.branchIfNotNaN(doubleValueFPR);
     11728    m_jit.moveTrustedValue(jsNaN(), resultRegs);
     11729    doneCases.append(m_jit.jump());
     11730
     11731    notNaN.link(&m_jit);
    1172811732    m_jit.truncateDoubleToInt32(doubleValueFPR, scratchGPR);
    1172911733    m_jit.convertInt32ToDouble(scratchGPR, tempFPR);
     
    1173111735
    1173211736    m_jit.boxInt32(scratchGPR, resultRegs);
    11733     auto done = m_jit.jump();
     11737    doneCases.append(m_jit.jump());
    1173411738
    1173511739    passThroughCases.link(&m_jit);
    1173611740    m_jit.moveValueRegs(keyRegs, resultRegs);
    1173711741
    11738     done.link(&m_jit);
     11742    doneCases.link(&m_jit);
    1173911743    jsValueResult(resultRegs, node);
    1174011744}
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r244079 r244760  
    98239823        m_out.appendTo(notInt32NumberCase, notNaNCase);
    98249824        LValue doubleValue = unboxDouble(key);
     9825        ValueFromBlock normalizedNaNResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsNaN())));
    98259826        m_out.branch(m_out.doubleNotEqualOrUnordered(doubleValue, doubleValue), unsure(continuation), unsure(notNaNCase));
    98269827
     
    98319832
    98329833        m_out.appendTo(convertibleCase, continuation);
    9833         ValueFromBlock slowResult = m_out.anchor(boxInt32(integerValue));
     9834        ValueFromBlock boxedIntResult = m_out.anchor(boxInt32(integerValue));
    98349835        m_out.jump(continuation);
    98359836
    98369837        m_out.appendTo(continuation, lastNext);
    9837         setJSValue(m_out.phi(Int64, fastResult, slowResult));
     9838        setJSValue(m_out.phi(Int64, fastResult, normalizedNaNResult, boxedIntResult));
    98389839    }
    98399840
  • trunk/Source/JavaScriptCore/runtime/HashMapImpl.h

    r239427 r244760  
    2727
    2828#include "ExceptionHelpers.h"
     29#include "JSCJSValueInlines.h"
    2930#include "JSObject.h"
    3031
     
    246247    double d = key.asDouble();
    247248    if (std::isnan(d))
    248         return key;
     249        return jsNaN();
    249250
    250251    int i = static_cast<int>(d);
Note: See TracChangeset for help on using the changeset viewer.