Changeset 267373 in webkit


Ignore:
Timestamp:
Sep 21, 2020 3:10:24 PM (4 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] BigInt should work with Map / Set
https://bugs.webkit.org/show_bug.cgi?id=216667
JSTests:

<rdar://problem/69107221>

Reviewed by Robin Morisset.

  • stress/bigint-and-map-set.js: Added.

(shouldBe):
(opaque1n):
(testMap):
(let.set new):

  • stress/bigint-string-map-set.js: Added.

(shouldBe):
(testMap):

  • stress/bigint32-map-set.js: Added.

(shouldBe):
(testMap):

Source/JavaScriptCore:

Reviewed by Robin Morisset.

This patch makes BigInt supported in Map / Set.

  1. In NormalizeMapKey, we always attempt to convert HeapBigInt to BigInt32 (if supported). So we ensure that,

normalized BigInt has one unique form for BigInt32 range. This allows us to use hashing for BigInt32 bit pattern directly.

  1. In MapHash, for BigInt32, we directly has the JSValue bits. For HeapBigInt, we calculate hash via Hasher.
  2. In GetMapBucket, we consider HeapBigInt case correctly.
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixupNormalizeMapKey):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGSpeculativeJIT.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLLowerDFGToB3.cpp:

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

  • runtime/HashMapImpl.h:

(JSC::normalizeMapKey):
(JSC::jsMapHash):
(JSC::concurrentJSMapHash):

  • runtime/JSBigInt.cpp:

(JSC::JSBigInt::concurrentHash):

  • runtime/JSBigInt.h:

(JSC::tryConvertToBigInt32):

Source/WebCore:

<rdar://problem/69107221>

Reviewed by Robin Morisset.

Strongly ensure that BigInt32 is always selected since Map / Set could use it as a key.

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneDeserializer::readBigInt):

Source/WTF:

Reviewed by Robin Morisset.

  • wtf/Hasher.h:

(WTF::Hasher::hash const):
(WTF::add):

Location:
trunk
Files:
3 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r267348 r267373  
     12020-09-21  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] BigInt should work with Map / Set
     4        https://bugs.webkit.org/show_bug.cgi?id=216667
     5        <rdar://problem/69107221>
     6
     7        Reviewed by Robin Morisset.
     8
     9        * stress/bigint-and-map-set.js: Added.
     10        (shouldBe):
     11        (opaque1n):
     12        (testMap):
     13        (let.set new):
     14        * stress/bigint-string-map-set.js: Added.
     15        (shouldBe):
     16        (testMap):
     17        * stress/bigint32-map-set.js: Added.
     18        (shouldBe):
     19        (testMap):
     20
    1212020-09-21  Yusuke Suzuki  <ysuzuki@apple.com>
    222
  • trunk/Source/JavaScriptCore/ChangeLog

    r267371 r267373  
     12020-09-21  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] BigInt should work with Map / Set
     4        https://bugs.webkit.org/show_bug.cgi?id=216667
     5
     6        Reviewed by Robin Morisset.
     7
     8        This patch makes BigInt supported in Map / Set.
     9
     10        1. In NormalizeMapKey, we always attempt to convert HeapBigInt to BigInt32 (if supported). So we ensure that,
     11            normalized BigInt has one unique form for BigInt32 range. This allows us to use hashing for BigInt32 bit pattern directly.
     12        2. In MapHash, for BigInt32, we directly has the JSValue bits. For HeapBigInt, we calculate hash via Hasher.
     13        3. In GetMapBucket, we consider HeapBigInt case correctly.
     14
     15        * dfg/DFGAbstractInterpreterInlines.h:
     16        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     17        * dfg/DFGConstantFoldingPhase.cpp:
     18        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     19        * dfg/DFGDoesGC.cpp:
     20        (JSC::DFG::doesGC):
     21        * dfg/DFGFixupPhase.cpp:
     22        (JSC::DFG::FixupPhase::fixupNode):
     23        (JSC::DFG::FixupPhase::fixupNormalizeMapKey):
     24        * dfg/DFGOperations.cpp:
     25        * dfg/DFGOperations.h:
     26        * dfg/DFGSpeculativeJIT.cpp:
     27        (JSC::DFG::SpeculativeJIT::compileNormalizeMapKey):
     28        * dfg/DFGSpeculativeJIT64.cpp:
     29        (JSC::DFG::SpeculativeJIT::compile):
     30        * ftl/FTLLowerDFGToB3.cpp:
     31        (JSC::FTL::DFG::LowerDFGToB3::compileMapHash):
     32        (JSC::FTL::DFG::LowerDFGToB3::compileNormalizeMapKey):
     33        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
     34        * runtime/HashMapImpl.h:
     35        (JSC::normalizeMapKey):
     36        (JSC::jsMapHash):
     37        (JSC::concurrentJSMapHash):
     38        * runtime/JSBigInt.cpp:
     39        (JSC::JSBigInt::concurrentHash):
     40        * runtime/JSBigInt.h:
     41        (JSC::tryConvertToBigInt32):
     42
    1432020-09-21  Mark Lam  <mark.lam@apple.com>
    244
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r266254 r267373  
    13821382        }
    13831383
    1384         SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only);
     1384        SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only) | SpecHeapBigInt;
    13851385        if (!(forNode(node->child1()).m_type & typeMaybeNormalized)) {
    13861386            m_state.setShouldTryConstantFolding(true);
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r265934 r267373  
    995995
    996996            case NormalizeMapKey: {
    997                 SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only);
     997                SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only) | SpecHeapBigInt;
    998998                if (m_state.forNode(node->child1()).m_type & typeMaybeNormalized)
    999999                    break;
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r266095 r267373  
    165165    case SuperSamplerEnd:
    166166    case CPUIntrinsic:
    167     case NormalizeMapKey:
     167    case NormalizeMapKey: // HeapBigInt => BigInt32 conversion does not involve GC.
    168168    case GetMapBucketHead:
    169169    case GetMapBucketNext:
     
    518518        case SymbolUse:
    519519        case ObjectUse:
     520#if USE(BIGINT32)
     521        case BigInt32Use:
     522#endif
     523        case HeapBigIntUse:
    520524            return false;
    521525        default:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r266095 r267373  
    23782378            else if (node->child2()->shouldSpeculateInt32())
    23792379                fixEdge<Int32Use>(node->child2());
     2380#if USE(BIGINT32)
     2381            else if (node->child2()->shouldSpeculateBigInt32())
     2382                fixEdge<BigInt32Use>(node->child2());
     2383#endif
    23802384            else if (node->child2()->shouldSpeculateSymbol())
    23812385                fixEdge<SymbolUse>(node->child2());
     
    23842388            else if (node->child2()->shouldSpeculateString())
    23852389                fixEdge<StringUse>(node->child2());
     2390            else if (node->child2()->shouldSpeculateHeapBigInt())
     2391                fixEdge<HeapBigIntUse>(node->child2());
    23862392            else if (node->child2()->shouldSpeculateCell())
    23872393                fixEdge<CellUse>(node->child2());
     
    24342440            if (node->child1()->shouldSpeculateString()) {
    24352441                fixEdge<StringUse>(node->child1());
     2442                break;
     2443            }
     2444
     2445#if USE(BIGINT32)
     2446            if (node->child1()->shouldSpeculateBigInt32()) {
     2447                fixEdge<BigInt32Use>(node->child1());
     2448                break;
     2449            }
     2450#endif
     2451
     2452            if (node->child1()->shouldSpeculateHeapBigInt()) {
     2453                fixEdge<HeapBigIntUse>(node->child1());
    24362454                break;
    24372455            }
     
    39974015        }
    39984016
    3999         if (node->child1()->shouldSpeculateCell()) {
    4000             fixEdge<CellUse>(node->child1());
     4017#if USE(BIGINT32)
     4018        if (node->child1()->shouldSpeculateBigInt32()) {
     4019            fixEdge<BigInt32Use>(node->child1());
    40014020            node->convertToIdentity();
    40024021            return;
    40034022        }
     4023#endif
    40044024
    40054025        fixEdge<UntypedUse>(node->child1());
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r266223 r267373  
    32133213}
    32143214
     3215EncodedJSValue JIT_OPERATION operationNormalizeMapKey(VM* vmPointer, EncodedJSValue input)
     3216{
     3217    VM& vm = *vmPointer;
     3218    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     3219    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     3220    return JSValue::encode(normalizeMapKey(JSValue::decode(input)));
     3221}
     3222
    32153223UCPUStrictInt32 JIT_OPERATION operationMapHash(JSGlobalObject* globalObject, EncodedJSValue input)
    32163224{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r265934 r267373  
    244244char* JIT_OPERATION operationDoubleToStringWithValidRadix(JSGlobalObject*, double, int32_t);
    245245
     246EncodedJSValue JIT_OPERATION operationNormalizeMapKey(VM*, EncodedJSValue input) WTF_INTERNAL;
    246247UCPUStrictInt32 JIT_OPERATION operationMapHash(JSGlobalObject*, EncodedJSValue input);
    247248JSCell* JIT_OPERATION operationJSMapFindBucket(JSGlobalObject*, JSCell*, EncodedJSValue, int32_t);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r266095 r267373  
    1251812518    CCallHelpers::JumpList doneCases;
    1251912519
     12520    auto isNotCell = m_jit.branchIfNotCell(keyRegs);
     12521    passThroughCases.append(m_jit.branchIfNotHeapBigInt(keyRegs.payloadGPR()));
     12522    auto slowPath = m_jit.jump();
     12523    isNotCell.link(&m_jit);
     12524
    1252012525    passThroughCases.append(m_jit.branchIfNotNumber(keyRegs, scratchGPR));
    1252112526    passThroughCases.append(m_jit.branchIfInt32(keyRegs));
     
    1254012545    passThroughCases.link(&m_jit);
    1254112546    m_jit.moveValueRegs(keyRegs, resultRegs);
     12547    addSlowPathGenerator(slowPathCall(slowPath, this, operationNormalizeMapKey, resultRegs, &vm(), keyRegs));
    1254212548
    1254312549    doneCases.link(&m_jit);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r266770 r267373  
    44324432    case MapHash: {
    44334433        switch (node->child1().useKind()) {
     4434#if USE(BIGINT32)
     4435        case BigInt32Use:
     4436#endif
    44344437        case BooleanUse:
    44354438        case Int32Use:
     
    44514454            break;
    44524455        }
     4456        case HeapBigIntUse: {
     4457            SpeculateCellOperand input(this, node->child1());
     4458            GPRReg inputGPR = input.gpr();
     4459
     4460            speculateHeapBigInt(node->child1(), inputGPR);
     4461
     4462            flushRegisters();
     4463            GPRFlushedCallResult result(this);
     4464            GPRReg resultGPR = result.gpr();
     4465            callOperation(operationMapHash, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), inputGPR);
     4466            m_jit.exceptionCheck();
     4467            strictInt32Result(resultGPR, node);
     4468            break;
     4469        }
    44534470        case CellUse:
    44544471        case StringUse: {
     
    44734490            else {
    44744491                auto isString = m_jit.branchIfString(inputGPR);
     4492                auto isHeapBigInt = m_jit.branchIfHeapBigInt(inputGPR);
    44754493                m_jit.move(inputGPR, resultGPR);
    44764494                m_jit.wangsInt64Hash(resultGPR, tempGPR);
     4495                addSlowPathGenerator(slowPathCall(isHeapBigInt, this, operationMapHash, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), inputGPR));
    44774496                done.append(m_jit.jump());
    44784497                isString.link(&m_jit);
     
    45164535        straightHash.append(m_jit.branchIfNotCell(inputGPR));
    45174536        MacroAssembler::JumpList slowPath;
     4537        auto isHeapBigInt = m_jit.branchIfHeapBigInt(inputGPR);
    45184538        straightHash.append(m_jit.branchIfNotString(inputGPR));
    45194539        m_jit.loadPtr(MacroAssembler::Address(inputGPR, JSString::offsetOfValue()), resultGPR);
     
    45274547        m_jit.move(inputGPR, resultGPR);
    45284548        m_jit.wangsInt64Hash(resultGPR, tempGPR);
     4549        addSlowPathGenerator(slowPathCall(isHeapBigInt, this, operationMapHash, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), inputGPR));
    45294550        done.append(m_jit.jump());
    45304551
     
    45974618        switch (node->child2().useKind()) {
    45984619        case BooleanUse:
     4620#if USE(BIGINT32)
     4621        case BigInt32Use:
     4622#endif
    45994623        case Int32Use:
    46004624        case SymbolUse:
     
    46054629        }
    46064630        case CellUse: {
     4631            // if (bucket.isString()) {
     4632            //     if (key.isString())
     4633            //         => slow path
     4634            // } else if (bucket.isHeapBigInt()) {
     4635            //     if (key.isHeapBigInt())
     4636            //         => slow path
     4637            // }
    46074638            done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR));
    46084639            loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
    4609             loopAround.append(m_jit.branchIfNotString(bucketGPR));
     4640
     4641            auto isBucketString = m_jit.branchIfString(bucketGPR);
     4642            loopAround.append(m_jit.branchIfNotHeapBigInt(bucketGPR));
     4643
     4644            // bucket is HeapBigInt.
     4645            slowPathCases.append(m_jit.branchIfHeapBigInt(keyGPR));
     4646            loopAround.append(m_jit.jump());
     4647
     4648            // bucket is String.
     4649            isBucketString.link(&m_jit);
    46104650            loopAround.append(m_jit.branchIfNotString(keyGPR));
    4611             // They're both strings.
    46124651            slowPathCases.append(m_jit.jump());
    46134652            break;
     
    46174656            loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
    46184657            loopAround.append(m_jit.branchIfNotString(bucketGPR));
     4658            slowPathCases.append(m_jit.jump());
     4659            break;
     4660        }
     4661        case HeapBigIntUse: {
     4662            done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for!
     4663            loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
     4664            loopAround.append(m_jit.branchIfNotHeapBigInt(bucketGPR));
    46194665            slowPathCases.append(m_jit.jump());
    46204666            break;
     
    46274673            loopAround.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR)));
    46284674            // Both are cells here.
    4629             loopAround.append(m_jit.branchIfNotString(bucketGPR));
    4630             // The first is a string here.
    4631             slowPathCases.append(m_jit.branchIfString(keyGPR));
    4632             // The first is a string, but the second is not, we continue to loop around.
     4675            auto isBucketString = m_jit.branchIfString(bucketGPR);
     4676            // bucket is not String.
     4677            loopAround.append(m_jit.branchIfNotHeapBigInt(bucketGPR));
     4678            // bucket is HeapBigInt.
     4679            slowPathCases.append(m_jit.branchIfHeapBigInt(keyGPR));
    46334680            loopAround.append(m_jit.jump());
     4681            // bucket is String.
     4682            isBucketString.link(&m_jit);
     4683            loopAround.append(m_jit.branchIfNotString(keyGPR));
     4684            slowPathCases.append(m_jit.jump());
    46344685            break;
    46354686        }
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r267032 r267373  
    1124511245        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
    1124611246        switch (m_node->child1().useKind()) {
     11247#if USE(BIGINT32)
     11248        case BigInt32Use:
     11249#endif
    1124711250        case BooleanUse:
    1124811251        case Int32Use:
     
    1125511258        }
    1125611259
     11260        case HeapBigIntUse: {
     11261            LValue key = lowHeapBigInt(m_node->child1());
     11262            setInt32(m_out.castToInt32(vmCall(Int64, operationMapHash, weakPointer(globalObject), key)));
     11263            return;
     11264        }
     11265
    1125711266        case CellUse: {
    1125811267            LBasicBlock isString = m_out.newBlock();
    1125911268            LBasicBlock notString = m_out.newBlock();
     11269            LBasicBlock isHeapBigIntCase = m_out.newBlock();
     11270            LBasicBlock notStringHeapBigIntCase = m_out.newBlock();
    1126011271            LBasicBlock continuation = m_out.newBlock();
    1126111272
     
    1126911280            m_out.jump(continuation);
    1127011281
    11271             m_out.appendTo(notString, continuation);
     11282            m_out.appendTo(notString, isHeapBigIntCase);
     11283            m_out.branch(isHeapBigInt(value, (provenType(m_node->child1()) & ~SpecString)), unsure(isHeapBigIntCase), unsure(notStringHeapBigIntCase));
     11284
     11285            m_out.appendTo(isHeapBigIntCase, notStringHeapBigIntCase);
     11286            ValueFromBlock heapBigIntResult = m_out.anchor(m_out.castToInt32(vmCall(Int64, operationMapHash, weakPointer(globalObject), value)));
     11287            m_out.jump(continuation);
     11288
     11289            m_out.appendTo(notStringHeapBigIntCase, continuation);
    1127211290            ValueFromBlock notStringResult = m_out.anchor(wangsInt64Hash(value));
    1127311291            m_out.jump(continuation);
    1127411292
    1127511293            m_out.appendTo(continuation, lastNext);
    11276             setInt32(m_out.phi(Int32, stringResult, notStringResult));
     11294            setInt32(m_out.phi(Int32, stringResult, heapBigIntResult, notStringResult));
    1127711295            return;
    1127811296        }
     
    1129511313        LBasicBlock straightHash = m_out.newBlock();
    1129611314        LBasicBlock isStringCase = m_out.newBlock();
     11315        LBasicBlock notStringCase = m_out.newBlock();
    1129711316        LBasicBlock nonEmptyStringCase = m_out.newBlock();
    1129811317        LBasicBlock continuation = m_out.newBlock();
     
    1130111320            isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(straightHash));
    1130211321
    11303         LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
     11322        LBasicBlock lastNext = m_out.appendTo(isCellCase, notStringCase);
    1130411323        LValue isString = m_out.equal(m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType), m_out.constInt32(StringType));
    1130511324        m_out.branch(
    11306             isString, unsure(isStringCase), unsure(straightHash));
     11325            isString, unsure(isStringCase), unsure(notStringCase));
     11326
     11327        m_out.appendTo(notStringCase, isStringCase);
     11328        m_out.branch(isHeapBigInt(value, (provenType(m_node->child1()) & ~SpecString)), unsure(slowCase), unsure(straightHash));
    1130711329
    1130811330        m_out.appendTo(isStringCase, nonEmptyStringCase);
     
    1133211354        ASSERT(m_node->child1().useKind() == UntypedUse);
    1133311355
     11356        LBasicBlock isCellCase = m_out.newBlock();
     11357        LBasicBlock notCellCase = m_out.newBlock();
     11358        LBasicBlock isHeapBigIntCase = m_out.newBlock();
    1133411359        LBasicBlock isNumberCase = m_out.newBlock();
    1133511360        LBasicBlock notInt32NumberCase = m_out.newBlock();
     
    1133811363        LBasicBlock continuation = m_out.newBlock();
    1133911364
    11340         LBasicBlock lastNext = m_out.insertNewBlocksBefore(isNumberCase);
     11365        LBasicBlock lastNext = m_out.insertNewBlocksBefore(isCellCase);
    1134111366
    1134211367        LValue key = lowJSValue(m_node->child1());
    1134311368        ValueFromBlock fastResult = m_out.anchor(key);
     11369        m_out.branch(isNotCell(key, provenType(m_node->child1())), unsure(notCellCase), unsure(isCellCase));
     11370
     11371        m_out.appendTo(isCellCase, isHeapBigIntCase);
     11372        m_out.branch(isNotHeapBigInt(key, (provenType(m_node->child1()) & SpecCellCheck)), unsure(continuation), unsure(isHeapBigIntCase));
     11373
     11374        m_out.appendTo(isHeapBigIntCase, notCellCase);
     11375        ValueFromBlock bigIntResult = m_out.anchor(vmCall(Int64, operationNormalizeMapKey, m_vmValue, key));
     11376        m_out.jump(continuation);
     11377
     11378        m_out.appendTo(notCellCase, isNumberCase);
    1134411379        m_out.branch(isNotNumber(key), unsure(continuation), unsure(isNumberCase));
    1134511380
     
    1136311398
    1136411399        m_out.appendTo(continuation, lastNext);
    11365         setJSValue(m_out.phi(Int64, fastResult, normalizedNaNResult, doubleResult, boxedIntResult));
     11400        setJSValue(m_out.phi(Int64, fastResult, bigIntResult, normalizedNaNResult, doubleResult, boxedIntResult));
    1136611401    }
    1136711402
     
    1141911454        switch (m_node->child2().useKind()) {
    1142011455        case BooleanUse:
     11456#if USE(BIGINT32)
     11457        case BigInt32Use:
     11458#endif
    1142111459        case Int32Use:
    1142211460        case SymbolUse:
     
    1144211480            break;
    1144311481        }
     11482        case HeapBigIntUse: {
     11483            LBasicBlock notBitEqual = m_out.newBlock();
     11484            LBasicBlock bucketKeyIsCell = m_out.newBlock();
     11485
     11486            m_out.branch(m_out.equal(key, bucketKey),
     11487                unsure(continuation), unsure(notBitEqual));
     11488
     11489            m_out.appendTo(notBitEqual, bucketKeyIsCell);
     11490            m_out.branch(isCell(bucketKey),
     11491                unsure(bucketKeyIsCell), unsure(loopAround));
     11492
     11493            m_out.appendTo(bucketKeyIsCell, loopAround);
     11494            m_out.branch(isHeapBigInt(bucketKey),
     11495                unsure(slowPath), unsure(loopAround));
     11496            break;
     11497        }
    1144411498        case CellUse: {
    1144511499            LBasicBlock notBitEqual = m_out.newBlock();
    1144611500            LBasicBlock bucketKeyIsCell = m_out.newBlock();
    1144711501            LBasicBlock bucketKeyIsString = m_out.newBlock();
     11502            LBasicBlock bucketKeyIsNotString = m_out.newBlock();
     11503            LBasicBlock bucketKeyIsHeapBigInt = m_out.newBlock();
    1144811504
    1144911505            m_out.branch(m_out.equal(key, bucketKey),
     
    1145611512            m_out.appendTo(bucketKeyIsCell, bucketKeyIsString);
    1145711513            m_out.branch(isString(bucketKey),
    11458                 unsure(bucketKeyIsString), unsure(loopAround));
    11459 
    11460             m_out.appendTo(bucketKeyIsString, loopAround);
    11461             m_out.branch(isString(key),
     11514                unsure(bucketKeyIsString), unsure(bucketKeyIsNotString));
     11515
     11516            m_out.appendTo(bucketKeyIsString, bucketKeyIsNotString);
     11517            m_out.branch(isString(key, provenType(m_node->child2())),
     11518                unsure(slowPath), unsure(loopAround));
     11519
     11520            m_out.appendTo(bucketKeyIsNotString, bucketKeyIsHeapBigInt);
     11521            m_out.branch(isHeapBigInt(bucketKey),
     11522                unsure(bucketKeyIsHeapBigInt), unsure(loopAround));
     11523
     11524            m_out.appendTo(bucketKeyIsHeapBigInt, loopAround);
     11525            m_out.branch(isHeapBigInt(key, provenType(m_node->child2())),
    1146211526                unsure(slowPath), unsure(loopAround));
    1146311527            break;
     
    1146811532            LBasicBlock bothAreCells = m_out.newBlock();
    1146911533            LBasicBlock bucketKeyIsString = m_out.newBlock();
     11534            LBasicBlock bucketKeyIsNotString = m_out.newBlock();
     11535            LBasicBlock bucketKeyIsHeapBigInt = m_out.newBlock();
    1147011536
    1147111537            m_out.branch(m_out.equal(key, bucketKey),
     
    1148211548            m_out.appendTo(bothAreCells, bucketKeyIsString);
    1148311549            m_out.branch(isString(bucketKey),
    11484                 unsure(bucketKeyIsString), unsure(loopAround));
    11485 
    11486             m_out.appendTo(bucketKeyIsString, loopAround);
    11487             m_out.branch(isString(key),
     11550                unsure(bucketKeyIsString), unsure(bucketKeyIsNotString));
     11551
     11552            m_out.appendTo(bucketKeyIsString, bucketKeyIsNotString);
     11553            m_out.branch(isString(key, provenType(m_node->child2())),
     11554                unsure(slowPath), unsure(loopAround));
     11555
     11556            m_out.appendTo(bucketKeyIsNotString, bucketKeyIsHeapBigInt);
     11557            m_out.branch(isHeapBigInt(bucketKey),
     11558                unsure(bucketKeyIsHeapBigInt), unsure(loopAround));
     11559
     11560            m_out.appendTo(bucketKeyIsHeapBigInt, loopAround);
     11561            m_out.branch(isHeapBigInt(key, provenType(m_node->child2())),
    1148811562                unsure(slowPath), unsure(loopAround));
    1148911563            break;
  • trunk/Source/JavaScriptCore/runtime/HashMapImpl.h

    r254087 r267373  
    244244ALWAYS_INLINE JSValue normalizeMapKey(JSValue key)
    245245{
    246     if (!key.isNumber())
     246    if (!key.isNumber()) {
     247        if (key.isHeapBigInt())
     248            return tryConvertToBigInt32(key.asHeapBigInt());
    247249        return key;
     250    }
    248251
    249252    if (key.isInt32())
     
    288291    }
    289292
     293    if (value.isHeapBigInt())
     294        return value.asHeapBigInt()->hash();
     295
    290296    return wangsInt64Hash(JSValue::encode(value));
    291297}
     
    303309        return impl->concurrentHash();
    304310    }
     311
     312    if (key.isHeapBigInt())
     313        return key.asHeapBigInt()->concurrentHash();
    305314
    306315    uint64_t rawValue = JSValue::encode(key);
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp

    r266250 r267373  
    5555#include "StructureInlines.h"
    5656#include <algorithm>
     57#include <wtf/Hasher.h>
    5758#include <wtf/MathExtras.h>
    5859
     
    430431    : payload(value)
    431432{ }
    432 
    433 static ALWAYS_INLINE JSValue tryConvertToBigInt32(JSBigInt* bigInt)
    434 {
    435 #if USE(BIGINT32)
    436     if (UNLIKELY(!bigInt))
    437         return JSValue();
    438 
    439     if (bigInt->length() <= 1) {
    440         if (!bigInt->length())
    441             return jsBigInt32(0);
    442         JSBigInt::Digit digit = bigInt->digit(0);
    443         if (bigInt->sign()) {
    444             static constexpr uint64_t maxValue = -static_cast<int64_t>(std::numeric_limits<int32_t>::min());
    445             if (digit <= maxValue)
    446                 return jsBigInt32(static_cast<int32_t>(-static_cast<int64_t>(digit)));
    447         } else {
    448             static constexpr uint64_t maxValue = static_cast<uint64_t>(std::numeric_limits<int32_t>::max());
    449             if (digit <= maxValue)
    450                 return jsBigInt32(static_cast<int32_t>(digit));
    451         }
    452     }
    453 #endif
    454 
    455     return bigInt;
    456 }
    457433
    458434static ALWAYS_INLINE JSValue tryConvertToBigInt32(JSBigInt::ImplResult implResult)
     
    30743050#endif
    30753051
     3052static ALWAYS_INLINE unsigned computeHash(JSBigInt::Digit* digits, unsigned length, bool sign)
     3053{
     3054    Hasher hasher;
     3055    WTF::add(hasher, sign);
     3056    for (unsigned index = 0; index < length; ++index)
     3057        WTF::add(hasher, digits[index]);
     3058    return hasher.hash();
     3059}
     3060
     3061Optional<unsigned> JSBigInt::concurrentHash()
     3062{
     3063    // FIXME: Implement JSBigInt::concurrentHash by inserting right store barriers.
     3064    // https://bugs.webkit.org/show_bug.cgi?id=216801
     3065    return WTF::nullopt;
     3066}
     3067
     3068unsigned JSBigInt::hashSlow()
     3069{
     3070    ASSERT(!m_hash);
     3071    m_hash = computeHash(dataStorage(), length(), m_sign);
     3072    return m_hash;
     3073}
     3074
    30763075} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.h

    r266795 r267373  
    428428    JS_EXPORT_PRIVATE JSBigInt* tryRightTrim(VM&);
    429429
     430    JS_EXPORT_PRIVATE Optional<unsigned> concurrentHash();
     431    unsigned hash()
     432    {
     433        if (m_hash)
     434            return m_hash;
     435        return hashSlow();
     436    }
     437
    430438private:
    431439    JSBigInt(VM&, Structure*, Digit*, unsigned length);
    432440
    433441    JSBigInt* rightTrim(JSGlobalObject*, VM&);
     442
     443    JS_EXPORT_PRIVATE unsigned hashSlow();
    434444
    435445    static JSBigInt* createFromImpl(JSGlobalObject*, uint64_t value, bool sign);
     
    573583
    574584    inline Digit* dataStorage() { return m_data.get(m_length); }
     585    inline Digit* dataStorageUnsafe() { return m_data.getUnsafe(); }
    575586
    576587    const unsigned m_length;
     588    unsigned m_hash { 0 };
    577589    bool m_sign { false };
    578590    CagedBarrierPtr<Gigacage::Primitive, Digit, tagCagedPtr> m_data;
     
    609621}
    610622
     623ALWAYS_INLINE JSValue tryConvertToBigInt32(JSBigInt* bigInt)
     624{
     625#if USE(BIGINT32)
     626    if (UNLIKELY(!bigInt))
     627        return JSValue();
     628
     629    if (bigInt->length() <= 1) {
     630        if (!bigInt->length())
     631            return jsBigInt32(0);
     632        JSBigInt::Digit digit = bigInt->digit(0);
     633        if (bigInt->sign()) {
     634            static constexpr uint64_t maxValue = -static_cast<int64_t>(std::numeric_limits<int32_t>::min());
     635            if (digit <= maxValue)
     636                return jsBigInt32(static_cast<int32_t>(-static_cast<int64_t>(digit)));
     637        } else {
     638            static constexpr uint64_t maxValue = static_cast<uint64_t>(std::numeric_limits<int32_t>::max());
     639            if (digit <= maxValue)
     640                return jsBigInt32(static_cast<int32_t>(digit));
     641        }
     642    }
     643#endif
     644
     645    return bigInt;
     646}
     647
    611648} // namespace JSC
  • trunk/Source/WTF/ChangeLog

    r267371 r267373  
     12020-09-21  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] BigInt should work with Map / Set
     4        https://bugs.webkit.org/show_bug.cgi?id=216667
     5
     6        Reviewed by Robin Morisset.
     7
     8        * wtf/Hasher.h:
     9        (WTF::Hasher::hash const):
     10        (WTF::add):
     11
    1122020-09-21  Mark Lam  <mark.lam@apple.com>
    213
  • trunk/Source/WTF/wtf/Hasher.h

    r264277 r267373  
    4848template<typename... Types> uint32_t computeHash(const Types&...);
    4949template<typename T, typename... OtherTypes> uint32_t computeHash(std::initializer_list<T>, std::initializer_list<OtherTypes>...);
     50template<typename UnsignedInteger> std::enable_if_t<std::is_unsigned<UnsignedInteger>::value && sizeof(UnsignedInteger) <= sizeof(uint32_t), void> add(Hasher&, UnsignedInteger);
    5051
    5152class Hasher {
     
    7677    }
    7778
     79    unsigned hash() const
     80    {
     81        return m_underlyingHasher.hash();
     82    }
     83
    7884private:
    7985    StringHasher m_underlyingHasher;
     
    9096    // We overloaded for double and float below, just deal with integers here.
    9197    add(hasher, static_cast<std::make_unsigned_t<SignedArithmetic>>(number));
     98}
     99
     100inline void add(Hasher& hasher, bool boolean)
     101{
     102    add(hasher, static_cast<uint8_t>(boolean));
    92103}
    93104
  • trunk/Source/WebCore/ChangeLog

    r267372 r267373  
     12020-09-21  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] BigInt should work with Map / Set
     4        https://bugs.webkit.org/show_bug.cgi?id=216667
     5        <rdar://problem/69107221>
     6
     7        Reviewed by Robin Morisset.
     8
     9        Strongly ensure that BigInt32 is always selected since Map / Set could use it as a key.
     10
     11        * bindings/js/SerializedScriptValue.cpp:
     12        (WebCore::CloneDeserializer::readBigInt):
     13
    1142020-09-21  Peng Liu  <peng.liu6@apple.com>
    215
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r266470 r267373  
    30553055            }
    30563056            m_gcBuffer.appendWithCrashOnOverflow(bigInt);
    3057             return bigInt;
     3057            return tryConvertToBigInt32(bigInt);
    30583058        }
    30593059#endif
     
    30953095        }
    30963096        m_gcBuffer.appendWithCrashOnOverflow(bigInt);
    3097         return bigInt;
     3097        return tryConvertToBigInt32(bigInt);
    30983098    }
    30993099
Note: See TracChangeset for help on using the changeset viewer.