Changeset 276039 in webkit


Ignore:
Timestamp:
Apr 15, 2021, 12:18:50 PM (4 years ago)
Author:
mark.lam@apple.com
Message:

Refactor inline functions out of HashMapImpl.h into HashMapImplInlines.h.
https://bugs.webkit.org/show_bug.cgi?id=224616
rdar://76713709

Reviewed by Yusuke Suzuki.

Source/JavaScriptCore:

Also do the same for clients of HashMapImpl that require similar refactoring.
This fixes the #include of JSCJSValueInlines.h in HashMapImpl.h, as well as makes
it easier to use other inline functions from other classes in the implementation
of HashMapImpl's inline functions in the future.

This patch only moves inline functions out to their respective *Inlines.h.
There are no behavior changes.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • dfg/DFGAbstractInterpreterInlines.h:
  • dfg/DFGOperations.cpp:
  • runtime/AbstractModuleRecord.cpp:
  • runtime/HashMapImpl.cpp:
  • runtime/HashMapImpl.h:

(JSC::areKeysEqual): Deleted.
(JSC::normalizeMapKey): Deleted.
(JSC::wangsInt64Hash): Deleted.
(JSC::jsMapHash): Deleted.
(JSC::concurrentJSMapHash): Deleted.
(JSC::shouldShrink): Deleted.
(JSC::shouldRehashAfterAdd): Deleted.
(JSC::nextCapacity): Deleted.
(JSC::HashMapImpl::finishCreation): Deleted.
(JSC::HashMapImpl::findBucket): Deleted.
(JSC::HashMapImpl::get): Deleted.
(JSC::HashMapImpl::has): Deleted.
(JSC::HashMapImpl::add): Deleted.
(JSC::HashMapImpl::addNormalized): Deleted.
(JSC::HashMapImpl::remove): Deleted.
(JSC::HashMapImpl::clear): Deleted.
(JSC::HashMapImpl::setUpHeadAndTail): Deleted.
(JSC::HashMapImpl::addNormalizedNonExistingForCloning): Deleted.
(JSC::HashMapImpl::addNormalizedInternal): Deleted.
(JSC::HashMapImpl::findBucketAlreadyHashedAndNormalized): Deleted.
(JSC::HashMapImpl::rehash): Deleted.
(JSC::HashMapImpl::checkConsistency const): Deleted.
(JSC::HashMapImpl::makeAndSetNewBuffer): Deleted.
(JSC::HashMapImpl::assertBufferIsEmpty const): Deleted.

  • runtime/HashMapImplInlines.h: Added.

(JSC::areKeysEqual):
(JSC::normalizeMapKey):
(JSC::wangsInt64Hash):
(JSC::jsMapHash):
(JSC::concurrentJSMapHash):
(JSC::shouldShrink):
(JSC::shouldRehashAfterAdd):
(JSC::nextCapacity):
(JSC::HashMapImpl<HashMapBucketType>::finishCreation):
(JSC::HashMapImpl<HashMapBucketType>::findBucket):
(JSC::HashMapImpl<HashMapBucketType>::get):
(JSC::HashMapImpl<HashMapBucketType>::has):
(JSC::HashMapImpl<HashMapBucketType>::add):
(JSC::HashMapImpl<HashMapBucketType>::addNormalized):
(JSC::HashMapImpl<HashMapBucketType>::remove):
(JSC::HashMapImpl<HashMapBucketType>::clear):
(JSC::HashMapImpl<HashMapBucketType>::setUpHeadAndTail):
(JSC::HashMapImpl<HashMapBucketType>::addNormalizedNonExistingForCloning):
(JSC::HashMapImpl<HashMapBucketType>::addNormalizedInternal):
(JSC::HashMapImpl<HashMapBucketType>::findBucketAlreadyHashedAndNormalized):
(JSC::HashMapImpl<HashMapBucketType>::rehash):
(JSC::HashMapImpl<HashMapBucketType>::checkConsistency const):
(JSC::HashMapImpl<HashMapBucketType>::makeAndSetNewBuffer):
(JSC::HashMapImpl<HashMapBucketType>::assertBufferIsEmpty const):

  • runtime/JSMap.h:
  • runtime/JSMapInlines.h: Added.

(JSC::JSMap::set):

  • runtime/JSSetInlines.h: Added.
  • runtime/JSWeakMap.h:
  • runtime/JSWeakMapInlines.h: Added.

(JSC::JSWeakMap::set):

  • runtime/MapConstructor.cpp:
  • runtime/MapPrototype.cpp:
  • runtime/SetConstructor.cpp:
  • runtime/WeakMapConstructor.cpp:
  • runtime/WeakMapImpl.h:

(JSC::jsWeakMapHash): Deleted.
(JSC::nextCapacityAfterBatchRemoval): Deleted.
(JSC::WeakMapImpl::add): Deleted.
(JSC::WeakMapImpl::shouldRehashAfterAdd const): Deleted.
(JSC::WeakMapImpl::rehash): Deleted.

  • runtime/WeakMapImplInlines.h:

(JSC::jsWeakMapHash):
(JSC::nextCapacityAfterBatchRemoval):
(JSC::WeakMapImpl<WeakMapBucket>::add):
(JSC::WeakMapImpl<WeakMapBucket>::rehash):
(JSC::WeakMapImpl<WeakMapBucket>::shouldRehashAfterAdd const):

  • runtime/WeakMapPrototype.cpp:

Source/WebCore:

  • bindings/js/SerializedScriptValue.cpp:
Location:
trunk/Source
Files:
4 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r275797 r276039  
    918918    runtime/GlobalExecutable.h
    919919    runtime/HashMapImpl.h
     920    runtime/HashMapImplInlines.h
    920921    runtime/Identifier.h
    921922    runtime/IdentifierInlines.h
     
    975976    runtime/JSLock.h
    976977    runtime/JSMap.h
     978    runtime/JSMapInlines.h
    977979    runtime/JSMapIterator.h
    978980    runtime/JSModuleLoader.h
     
    992994    runtime/JSSegmentedVariableObject.h
    993995    runtime/JSSet.h
     996    runtime/JSSetInlines.h
    994997    runtime/JSSetIterator.h
    995998    runtime/JSSourceCode.h
     
    10001003    runtime/JSTypeInfo.h
    10011004    runtime/JSTypedArrays.h
     1005    runtime/JSWeakMap.h
     1006    runtime/JSWeakMapInlines.h
    10021007    runtime/JSWithScope.h
    10031008    runtime/JSWrapperObject.h
  • trunk/Source/JavaScriptCore/ChangeLog

    r276005 r276039  
     12021-04-15  Mark Lam  <mark.lam@apple.com>
     2
     3        Refactor inline functions out of HashMapImpl.h into HashMapImplInlines.h.
     4        https://bugs.webkit.org/show_bug.cgi?id=224616
     5        rdar://76713709
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        Also do the same for clients of HashMapImpl that require similar refactoring.
     10        This fixes the #include of JSCJSValueInlines.h in HashMapImpl.h, as well as makes
     11        it easier to use other inline functions from other classes in the implementation
     12        of HashMapImpl's inline functions in the future.
     13
     14        This patch only moves inline functions out to their respective *Inlines.h.
     15        There are no behavior changes.
     16
     17        * CMakeLists.txt:
     18        * JavaScriptCore.xcodeproj/project.pbxproj:
     19        * dfg/DFGAbstractInterpreterInlines.h:
     20        * dfg/DFGOperations.cpp:
     21        * runtime/AbstractModuleRecord.cpp:
     22        * runtime/HashMapImpl.cpp:
     23        * runtime/HashMapImpl.h:
     24        (JSC::areKeysEqual): Deleted.
     25        (JSC::normalizeMapKey): Deleted.
     26        (JSC::wangsInt64Hash): Deleted.
     27        (JSC::jsMapHash): Deleted.
     28        (JSC::concurrentJSMapHash): Deleted.
     29        (JSC::shouldShrink): Deleted.
     30        (JSC::shouldRehashAfterAdd): Deleted.
     31        (JSC::nextCapacity): Deleted.
     32        (JSC::HashMapImpl::finishCreation): Deleted.
     33        (JSC::HashMapImpl::findBucket): Deleted.
     34        (JSC::HashMapImpl::get): Deleted.
     35        (JSC::HashMapImpl::has): Deleted.
     36        (JSC::HashMapImpl::add): Deleted.
     37        (JSC::HashMapImpl::addNormalized): Deleted.
     38        (JSC::HashMapImpl::remove): Deleted.
     39        (JSC::HashMapImpl::clear): Deleted.
     40        (JSC::HashMapImpl::setUpHeadAndTail): Deleted.
     41        (JSC::HashMapImpl::addNormalizedNonExistingForCloning): Deleted.
     42        (JSC::HashMapImpl::addNormalizedInternal): Deleted.
     43        (JSC::HashMapImpl::findBucketAlreadyHashedAndNormalized): Deleted.
     44        (JSC::HashMapImpl::rehash): Deleted.
     45        (JSC::HashMapImpl::checkConsistency const): Deleted.
     46        (JSC::HashMapImpl::makeAndSetNewBuffer): Deleted.
     47        (JSC::HashMapImpl::assertBufferIsEmpty const): Deleted.
     48        * runtime/HashMapImplInlines.h: Added.
     49        (JSC::areKeysEqual):
     50        (JSC::normalizeMapKey):
     51        (JSC::wangsInt64Hash):
     52        (JSC::jsMapHash):
     53        (JSC::concurrentJSMapHash):
     54        (JSC::shouldShrink):
     55        (JSC::shouldRehashAfterAdd):
     56        (JSC::nextCapacity):
     57        (JSC::HashMapImpl<HashMapBucketType>::finishCreation):
     58        (JSC::HashMapImpl<HashMapBucketType>::findBucket):
     59        (JSC::HashMapImpl<HashMapBucketType>::get):
     60        (JSC::HashMapImpl<HashMapBucketType>::has):
     61        (JSC::HashMapImpl<HashMapBucketType>::add):
     62        (JSC::HashMapImpl<HashMapBucketType>::addNormalized):
     63        (JSC::HashMapImpl<HashMapBucketType>::remove):
     64        (JSC::HashMapImpl<HashMapBucketType>::clear):
     65        (JSC::HashMapImpl<HashMapBucketType>::setUpHeadAndTail):
     66        (JSC::HashMapImpl<HashMapBucketType>::addNormalizedNonExistingForCloning):
     67        (JSC::HashMapImpl<HashMapBucketType>::addNormalizedInternal):
     68        (JSC::HashMapImpl<HashMapBucketType>::findBucketAlreadyHashedAndNormalized):
     69        (JSC::HashMapImpl<HashMapBucketType>::rehash):
     70        (JSC::HashMapImpl<HashMapBucketType>::checkConsistency const):
     71        (JSC::HashMapImpl<HashMapBucketType>::makeAndSetNewBuffer):
     72        (JSC::HashMapImpl<HashMapBucketType>::assertBufferIsEmpty const):
     73        * runtime/JSMap.h:
     74        * runtime/JSMapInlines.h: Added.
     75        (JSC::JSMap::set):
     76        * runtime/JSSetInlines.h: Added.
     77        * runtime/JSWeakMap.h:
     78        * runtime/JSWeakMapInlines.h: Added.
     79        (JSC::JSWeakMap::set):
     80        * runtime/MapConstructor.cpp:
     81        * runtime/MapPrototype.cpp:
     82        * runtime/SetConstructor.cpp:
     83        * runtime/WeakMapConstructor.cpp:
     84        * runtime/WeakMapImpl.h:
     85        (JSC::jsWeakMapHash): Deleted.
     86        (JSC::nextCapacityAfterBatchRemoval): Deleted.
     87        (JSC::WeakMapImpl::add): Deleted.
     88        (JSC::WeakMapImpl::shouldRehashAfterAdd const): Deleted.
     89        (JSC::WeakMapImpl::rehash): Deleted.
     90        * runtime/WeakMapImplInlines.h:
     91        (JSC::jsWeakMapHash):
     92        (JSC::nextCapacityAfterBatchRemoval):
     93        (JSC::WeakMapImpl<WeakMapBucket>::add):
     94        (JSC::WeakMapImpl<WeakMapBucket>::rehash):
     95        (JSC::WeakMapImpl<WeakMapBucket>::shouldRehashAfterAdd const):
     96        * runtime/WeakMapPrototype.cpp:
     97
    1982021-04-15  Yusuke Suzuki  <ysuzuki@apple.com>
    299
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r275920 r276039  
    20122012                FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
    20132013                FEF49AAB1EB9484B00653BDB /* MultithreadedMultiVMExecutionTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF49AA91EB947FE00653BDB /* MultithreadedMultiVMExecutionTest.cpp */; };
     2014                FEF5B4232628A0EE0016E776 /* HashMapImplInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF5B4222628A0EE0016E776 /* HashMapImplInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
     2015                FEF5B4252628A8500016E776 /* JSMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF5B4242628A8500016E776 /* JSMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
     2016                FEF5B4272628ABD90016E776 /* JSWeakMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF5B4262628ABD90016E776 /* JSWeakMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
     2017                FEF5B4292628B5240016E776 /* JSSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF5B4282628B5240016E776 /* JSSetInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20142018                FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20152019/* End PBXBuildFile section */
     
    54185422                FEF49AA91EB947FE00653BDB /* MultithreadedMultiVMExecutionTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MultithreadedMultiVMExecutionTest.cpp; path = API/tests/MultithreadedMultiVMExecutionTest.cpp; sourceTree = "<group>"; };
    54195423                FEF49AAA1EB947FE00653BDB /* MultithreadedMultiVMExecutionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MultithreadedMultiVMExecutionTest.h; path = API/tests/MultithreadedMultiVMExecutionTest.h; sourceTree = "<group>"; };
     5424                FEF5B4222628A0EE0016E776 /* HashMapImplInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashMapImplInlines.h; sourceTree = "<group>"; };
     5425                FEF5B4242628A8500016E776 /* JSMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMapInlines.h; sourceTree = "<group>"; };
     5426                FEF5B4262628ABD90016E776 /* JSWeakMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakMapInlines.h; sourceTree = "<group>"; };
     5427                FEF5B4282628B5240016E776 /* JSSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSetInlines.h; sourceTree = "<group>"; };
    54205428                FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
    54215429/* End PBXFileReference section */
     
    73937401                                79A0907D1D768465008B889B /* HashMapImpl.cpp */,
    73947402                                79A0907E1D768465008B889B /* HashMapImpl.h */,
     7403                                FEF5B4222628A0EE0016E776 /* HashMapImplInlines.h */,
    73957404                                79DFCBDA1D88C59600527D03 /* HasOwnPropertyCache.h */,
    73967405                                933A349D038AE80F008635CE /* Identifier.cpp */,
     
    75907599                                A700873F17CBE8EB00C3E643 /* JSMap.cpp */,
    75917600                                A700874017CBE8EB00C3E643 /* JSMap.h */,
     7601                                FEF5B4242628A8500016E776 /* JSMapInlines.h */,
    75927602                                A74DEF8F182D991400522C22 /* JSMapIterator.cpp */,
    75937603                                A74DEF90182D991400522C22 /* JSMapIterator.h */,
     
    76317641                                A7299D9B17D12837005F5FF9 /* JSSet.cpp */,
    76327642                                A7299D9C17D12837005F5FF9 /* JSSet.h */,
     7643                                FEF5B4282628B5240016E776 /* JSSetInlines.h */,
    76337644                                A790DD69182F499700588807 /* JSSetIterator.cpp */,
    76347645                                A790DD6A182F499700588807 /* JSSetIterator.h */,
     
    76657676                                A7CA3AE117DA41AE006538AF /* JSWeakMap.cpp */,
    76667677                                A7CA3AE217DA41AE006538AF /* JSWeakMap.h */,
     7678                                FEF5B4262628ABD90016E776 /* JSWeakMapInlines.h */,
    76677679                                539BFBB122AD3D8C0023F4C0 /* JSWeakObjectRef.cpp */,
    76687680                                539BFBAF22AD3CDC0023F4C0 /* JSWeakObjectRef.h */,
     
    94369448                                A7C1EAF017987AB600299DB2 /* CLoopStackInlines.h in Headers */,
    94379449                                969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */,
     9450                                FEF5B4292628B5240016E776 /* JSSetInlines.h in Headers */,
    94389451                                0F8F94411667633200D61971 /* CodeBlockHash.h in Headers */,
    94399452                                0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */,
     
    96349647                                0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
    96359648                                0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */,
     9649                                FEF5B4272628ABD90016E776 /* JSWeakMapInlines.h in Headers */,
    96369650                                0F235BEC17178E7300690C7F /* DFGOSRExitBase.h in Headers */,
    96379651                                0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */,
     
    97649778                                0F9D4C0D1C3E1C11006CD984 /* FTLExceptionTarget.h in Headers */,
    97659779                                0F235BD417178E1C00690C7F /* FTLExitArgument.h in Headers */,
     9780                                FEF5B4232628A0EE0016E776 /* HashMapImplInlines.h in Headers */,
    97669781                                0F235BD617178E1C00690C7F /* FTLExitArgumentForOperand.h in Headers */,
    97679782                                0F2B9CF519D0BAC100B1D1B5 /* FTLExitPropertyValue.h in Headers */,
     
    1054110556                                7986943B1F8C0ACC009232AE /* StructureCache.h in Headers */,
    1054210557                                7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */,
     10558                                FEF5B4252628A8500016E776 /* JSMapInlines.h in Headers */,
    1054310559                                2AAAA31218BD49D100394CC8 /* StructureIDBlob.h in Headers */,
    1054410560                                2AF7382D18BBBF92008A5A37 /* StructureIDTable.h in Headers */,
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r274037 r276039  
    11/*
    2  * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3838#include "GetByStatus.h"
    3939#include "GetterSetter.h"
    40 #include "HashMapImpl.h"
     40#include "HashMapImplInlines.h"
    4141#include "JITOperations.h"
    4242#include "JSAsyncGenerator.h"
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r275995 r276039  
    6161#include "JSSet.h"
    6262#include "JSSetIterator.h"
    63 #include "JSWeakMap.h"
     63#include "JSWeakMapInlines.h"
    6464#include "JSWeakSet.h"
    6565#include "NumberConstructor.h"
  • trunk/Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp

    r273225 r276039  
    3030#include "JSCInlines.h"
    3131#include "JSInternalFieldObjectImplInlines.h"
    32 #include "JSMap.h"
     32#include "JSMapInlines.h"
    3333#include "JSModuleEnvironment.h"
    3434#include "JSModuleNamespaceObject.h"
  • trunk/Source/JavaScriptCore/runtime/HashMapImpl.cpp

    r273138 r276039  
    2727#include "HashMapImpl.h"
    2828
     29#include "HashMapImplInlines.h"
    2930#include "JSCInlines.h"
    3031
  • trunk/Source/JavaScriptCore/runtime/HashMapImpl.h

    r275969 r276039  
    2727
    2828#include "ExceptionHelpers.h"
    29 #include "JSCJSValueInlines.h"
     29#include "JSCJSValue.h"
    3030#include "JSObject.h"
    3131
     
    231231};
    232232
    233 ALWAYS_INLINE static bool areKeysEqual(JSGlobalObject* globalObject, JSValue a, JSValue b)
    234 {
    235     // We want +0 and -0 to be compared to true here. sameValue() itself doesn't
    236     // guarantee that, however, we normalize all keys before comparing and storing
    237     // them in the map. The normalization will convert -0.0 and 0.0 to the integer
    238     // representation for 0.
    239     return sameValue(globalObject, a, b);
    240 }
     233ALWAYS_INLINE static bool areKeysEqual(JSGlobalObject*, JSValue, JSValue);
    241234
    242235// Note that normalization is inlined in DFG's NormalizeMapKey.
    243236// Keep in sync with the implementation of DFG and FTL normalization.
    244 ALWAYS_INLINE JSValue normalizeMapKey(JSValue key)
    245 {
    246     if (!key.isNumber()) {
    247         if (key.isHeapBigInt())
    248             return tryConvertToBigInt32(key.asHeapBigInt());
    249         return key;
    250     }
    251 
    252     if (key.isInt32())
    253         return key;
    254 
    255     double d = key.asDouble();
    256     if (std::isnan(d))
    257         return jsNaN();
    258 
    259     int i = static_cast<int>(d);
    260     if (i == d) {
    261         // When a key is -0, we convert it to positive zero.
    262         // When a key is the double representation for an integer, we convert it to an integer.
    263         return jsNumber(i);
    264     }
    265     // This means key is definitely not negative zero, and it's definitely not a double representation of an integer.
    266     return key;
    267 }
    268 
    269 static ALWAYS_INLINE uint32_t wangsInt64Hash(uint64_t key)
    270 {
    271     key += ~(key << 32);
    272     key ^= (key >> 22);
    273     key += ~(key << 13);
    274     key ^= (key >> 8);
    275     key += (key << 3);
    276     key ^= (key >> 15);
    277     key += ~(key << 27);
    278     key ^= (key >> 31);
    279     return static_cast<unsigned>(key);
    280 }
    281 
    282 ALWAYS_INLINE uint32_t jsMapHash(JSBigInt* bigInt)
    283 {
    284     return bigInt->hash();
    285 }
    286 
    287 ALWAYS_INLINE uint32_t jsMapHash(JSGlobalObject* globalObject, VM& vm, JSValue value)
    288 {
    289     ASSERT_WITH_MESSAGE(normalizeMapKey(value) == value, "We expect normalized values flowing into this function.");
    290 
    291     if (value.isString()) {
    292         auto scope = DECLARE_THROW_SCOPE(vm);
    293         const String& wtfString = asString(value)->value(globalObject);
    294         RETURN_IF_EXCEPTION(scope, UINT_MAX);
    295         return wtfString.impl()->hash();
    296     }
    297 
    298     if (value.isHeapBigInt())
    299         return jsMapHash(value.asHeapBigInt());
    300 
    301     return wangsInt64Hash(JSValue::encode(value));
    302 }
    303 
    304 ALWAYS_INLINE Optional<uint32_t> concurrentJSMapHash(JSValue key)
    305 {
    306     key = normalizeMapKey(key);
    307     if (key.isString()) {
    308         JSString* string = asString(key);
    309         if (string->length() > 10 * 1024)
    310             return WTF::nullopt;
    311         const StringImpl* impl = string->tryGetValueImpl();
    312         if (!impl)
    313             return WTF::nullopt;
    314         return impl->concurrentHash();
    315     }
    316 
    317     if (key.isHeapBigInt())
    318         return key.asHeapBigInt()->concurrentHash();
    319 
    320     uint64_t rawValue = JSValue::encode(key);
    321     return wangsInt64Hash(rawValue);
    322 }
    323 
    324 ALWAYS_INLINE uint32_t shouldShrink(uint32_t capacity, uint32_t keyCount)
    325 {
    326     return 8 * keyCount <= capacity && capacity > 4;
    327 }
    328 
    329 ALWAYS_INLINE uint32_t shouldRehashAfterAdd(uint32_t capacity, uint32_t keyCount, uint32_t deleteCount)
    330 {
    331     return 2 * (keyCount + deleteCount) >= capacity;
    332 }
    333 
    334 ALWAYS_INLINE uint32_t nextCapacity(uint32_t capacity, uint32_t keyCount)
    335 {
    336     if (shouldShrink(capacity, keyCount)) {
    337         ASSERT((capacity / 2) >= 4);
    338         return capacity / 2;
    339     }
    340 
    341     if (3 * keyCount <= capacity && capacity > 64) {
    342         // We stay at the same size if rehashing would cause us to be no more than
    343         // 1/3rd full. This comes up for programs like this:
    344         // Say the hash table grew to a key count of 64, causing it to grow to a capacity of 256.
    345         // Then, the table added 63 items. The load is now 127. Then, 63 items are deleted.
    346         // The load is still 127. Then, another item is added. The load is now 128, and we
    347         // decide that we need to rehash. The key count is 65, almost exactly what it was
    348         // when we grew to a capacity of 256. We don't really need to grow to a capacity
    349         // of 512 in this situation. Instead, we choose to rehash at the same size. This
    350         // will bring the load down to 65. We rehash into the same size when we determine
    351         // that the new load ratio will be under 1/3rd. (We also pick a minumum capacity
    352         // at which this rule kicks in because otherwise we will be too sensitive to rehashing
    353         // at the same capacity).
    354         return capacity;
    355     }
    356     return (Checked<uint32_t>(capacity) * 2).unsafeGet();
    357 }
     237ALWAYS_INLINE JSValue normalizeMapKey(JSValue key);
     238static ALWAYS_INLINE uint32_t wangsInt64Hash(uint64_t key);
     239ALWAYS_INLINE uint32_t jsMapHash(JSBigInt*);
     240ALWAYS_INLINE uint32_t jsMapHash(JSGlobalObject*, VM&, JSValue);
     241ALWAYS_INLINE uint32_t shouldShrink(uint32_t capacity, uint32_t keyCount);
     242ALWAYS_INLINE uint32_t shouldRehashAfterAdd(uint32_t capacity, uint32_t keyCount, uint32_t deleteCount);
     243ALWAYS_INLINE uint32_t nextCapacity(uint32_t capacity, uint32_t keyCount);
    358244
    359245template <typename HashMapBucketType>
     
    392278    }
    393279
    394     void finishCreation(JSGlobalObject* globalObject, VM& vm)
    395     {
    396         ASSERT_WITH_MESSAGE(HashMapBucket<HashMapBucketDataKey>::offsetOfKey() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfKey(), "We assume this to be true in the DFG and FTL JIT.");
    397 
    398         auto scope = DECLARE_THROW_SCOPE(vm);
    399         Base::finishCreation(vm);
    400 
    401         makeAndSetNewBuffer(globalObject, vm);
    402         RETURN_IF_EXCEPTION(scope, void());
    403 
    404         setUpHeadAndTail(globalObject, vm);
    405     }
    406 
    407     void finishCreation(JSGlobalObject* globalObject, VM& vm, HashMapImpl* base)
    408     {
    409         auto scope = DECLARE_THROW_SCOPE(vm);
    410         Base::finishCreation(vm);
    411 
    412         // This size should be the same to the case when you clone the map by calling add() repeatedly.
    413         uint32_t capacity = ((Checked<uint32_t>(base->m_keyCount) * 2) + 1).unsafeGet();
    414         RELEASE_ASSERT(capacity <= (1U << 31));
    415         capacity = std::max<uint32_t>(WTF::roundUpToPowerOfTwo(capacity), 4U);
    416         m_capacity = capacity;
    417         makeAndSetNewBuffer(globalObject, vm);
    418         RETURN_IF_EXCEPTION(scope, void());
    419 
    420         setUpHeadAndTail(globalObject, vm);
    421 
    422         HashMapBucketType* bucket = base->m_head.get()->next();
    423         while (bucket) {
    424             if (!bucket->deleted()) {
    425                 addNormalizedNonExistingForCloning(globalObject, bucket->key(), HashMapBucketType::extractValue(*bucket));
    426                 RETURN_IF_EXCEPTION(scope, void());
    427             }
    428             bucket = bucket->next();
    429         }
    430         checkConsistency();
    431     }
     280    void finishCreation(JSGlobalObject*, VM&);
     281    void finishCreation(JSGlobalObject*, VM&, HashMapImpl* base);
    432282
    433283    static HashMapBucketType* emptyValue()
     
    451301    }
    452302
    453     ALWAYS_INLINE HashMapBucketType** findBucket(JSGlobalObject* globalObject, JSValue key)
    454     {
    455         VM& vm = getVM(globalObject);
    456         auto scope = DECLARE_THROW_SCOPE(vm);
    457         key = normalizeMapKey(key);
    458         uint32_t hash = jsMapHash(globalObject, vm, key);
    459         RETURN_IF_EXCEPTION(scope, nullptr);
    460         return findBucket(globalObject, key, hash);
    461     }
    462 
    463     ALWAYS_INLINE HashMapBucketType** findBucket(JSGlobalObject* globalObject, JSValue key, uint32_t hash)
    464     {
    465         ASSERT_WITH_MESSAGE(normalizeMapKey(key) == key, "We expect normalized values flowing into this function.");
    466         return findBucketAlreadyHashedAndNormalized(globalObject, key, hash);
    467     }
     303    ALWAYS_INLINE HashMapBucketType** findBucket(JSGlobalObject*, JSValue key);
     304
     305    ALWAYS_INLINE HashMapBucketType** findBucket(JSGlobalObject*, JSValue key, uint32_t hash);
    468306
    469307    template <typename T = HashMapBucketType>
    470     ALWAYS_INLINE typename std::enable_if<std::is_same<T, HashMapBucket<HashMapBucketDataKeyValue>>::value, JSValue>::type get(JSGlobalObject* globalObject, JSValue key)
    471     {
    472         if (HashMapBucketType** bucket = findBucket(globalObject, key))
    473             return (*bucket)->value();
    474         return jsUndefined();
    475     }
    476 
    477     ALWAYS_INLINE bool has(JSGlobalObject* globalObject, JSValue key)
    478     {
    479         return !!findBucket(globalObject, key);
    480     }
    481 
    482     ALWAYS_INLINE void add(JSGlobalObject* globalObject, JSValue key, JSValue value = JSValue())
    483     {
    484         VM& vm = getVM(globalObject);
    485         auto scope = DECLARE_THROW_SCOPE(vm);
    486 
    487         key = normalizeMapKey(key);
    488         addNormalizedInternal(globalObject, key, value, [&] (HashMapBucketType* bucket) {
    489             return !isDeleted(bucket) && areKeysEqual(globalObject, key, bucket->key());
    490         });
    491         RETURN_IF_EXCEPTION(scope, void());
    492         scope.release();
    493         if (shouldRehashAfterAdd())
    494             rehash(globalObject);
    495     }
    496 
    497     ALWAYS_INLINE HashMapBucketType* addNormalized(JSGlobalObject* globalObject, JSValue key, JSValue value, uint32_t hash)
    498     {
    499         VM& vm = getVM(globalObject);
    500         ASSERT_WITH_MESSAGE(normalizeMapKey(key) == key, "We expect normalized values flowing into this function.");
    501         DEFER_TERMINATION_AND_ASSERT_WITH_MESSAGE(vm, jsMapHash(globalObject, getVM(globalObject), key) == hash, "We expect hash value is what we expect.");
    502 
    503         auto* bucket = addNormalizedInternal(vm, key, value, hash, [&] (HashMapBucketType* bucket) {
    504             return !isDeleted(bucket) && areKeysEqual(globalObject, key, bucket->key());
    505         });
    506         if (shouldRehashAfterAdd())
    507             rehash(globalObject);
    508         return bucket;
    509     }
    510 
    511     ALWAYS_INLINE bool remove(JSGlobalObject* globalObject, JSValue key)
    512     {
    513         HashMapBucketType** bucket = findBucket(globalObject, key);
    514         if (!bucket)
    515             return false;
    516 
    517         VM& vm = getVM(globalObject);
    518         HashMapBucketType* impl = *bucket;
    519         impl->next()->setPrev(vm, impl->prev());
    520         impl->prev()->setNext(vm, impl->next());
    521         impl->makeDeleted(vm);
    522 
    523         *bucket = deletedValue();
    524 
    525         ++m_deleteCount;
    526         ASSERT(m_keyCount > 0);
    527         --m_keyCount;
    528 
    529         if (shouldShrink())
    530             rehash(globalObject);
    531 
    532         return true;
    533     }
     308    ALWAYS_INLINE typename std::enable_if<std::is_same<T, HashMapBucket<HashMapBucketDataKeyValue>>::value, JSValue>::type get(JSGlobalObject*, JSValue key);
     309
     310    ALWAYS_INLINE bool has(JSGlobalObject*, JSValue key);
     311
     312    ALWAYS_INLINE void add(JSGlobalObject*, JSValue key, JSValue = JSValue());
     313
     314    ALWAYS_INLINE HashMapBucketType* addNormalized(JSGlobalObject*, JSValue key, JSValue, uint32_t hash);
     315
     316    ALWAYS_INLINE bool remove(JSGlobalObject*, JSValue key);
    534317
    535318    ALWAYS_INLINE uint32_t size() const
     
    538321    }
    539322
    540     ALWAYS_INLINE void clear(JSGlobalObject* globalObject)
    541     {
    542         VM& vm = getVM(globalObject);
    543         m_keyCount = 0;
    544         m_deleteCount = 0;
    545         HashMapBucketType* head = m_head.get();
    546         HashMapBucketType* bucket = m_head->next();
    547         HashMapBucketType* tail = m_tail.get();
    548         while (bucket != tail) {
    549             HashMapBucketType* next = bucket->next();
    550             // We restart each iterator by pointing it to the head of the list.
    551             bucket->setNext(vm, head);
    552             bucket->makeDeleted(vm);
    553             bucket = next;
    554         }
    555         m_head->setNext(vm, m_tail.get());
    556         m_tail->setPrev(vm, m_head.get());
    557         m_capacity = 4;
    558         makeAndSetNewBuffer(globalObject, vm);
    559         checkConsistency();
    560     }
     323    ALWAYS_INLINE void clear(JSGlobalObject*);
    561324
    562325    ALWAYS_INLINE size_t bufferSizeInBytes() const
     
    603366    }
    604367
    605     ALWAYS_INLINE void setUpHeadAndTail(JSGlobalObject*, VM& vm)
    606     {
    607         m_head.set(vm, this, HashMapBucketType::create(vm));
    608         m_tail.set(vm, this, HashMapBucketType::create(vm));
    609 
    610         m_head->setNext(vm, m_tail.get());
    611         m_tail->setPrev(vm, m_head.get());
    612         ASSERT(m_head->deleted());
    613         ASSERT(m_tail->deleted());
    614     }
    615 
    616     ALWAYS_INLINE void addNormalizedNonExistingForCloning(JSGlobalObject* globalObject, JSValue key, JSValue value = JSValue())
    617     {
    618         addNormalizedInternal(globalObject, key, value, [&] (HashMapBucketType*) {
    619             return false;
    620         });
    621     }
     368    ALWAYS_INLINE void setUpHeadAndTail(JSGlobalObject*, VM&);
     369
     370    ALWAYS_INLINE void addNormalizedNonExistingForCloning(JSGlobalObject*, JSValue key, JSValue = JSValue());
    622371
    623372    template<typename CanUseBucket>
    624     ALWAYS_INLINE void addNormalizedInternal(JSGlobalObject* globalObject, JSValue key, JSValue value, const CanUseBucket& canUseBucket)
    625     {
    626         VM& vm = getVM(globalObject);
    627         auto scope = DECLARE_THROW_SCOPE(vm);
    628 
    629         uint32_t hash = jsMapHash(globalObject, vm, key);
    630         RETURN_IF_EXCEPTION(scope, void());
    631         scope.release();
    632         addNormalizedInternal(vm, key, value, hash, canUseBucket);
    633     }
     373    ALWAYS_INLINE void addNormalizedInternal(JSGlobalObject*, JSValue key, JSValue, const CanUseBucket&);
    634374
    635375    template<typename CanUseBucket>
    636     ALWAYS_INLINE HashMapBucketType* addNormalizedInternal(VM& vm, JSValue key, JSValue value, uint32_t hash, const CanUseBucket& canUseBucket)
    637     {
    638         ASSERT_WITH_MESSAGE(normalizeMapKey(key) == key, "We expect normalized values flowing into this function.");
    639 
    640         const uint32_t mask = m_capacity - 1;
    641         uint32_t index = hash & mask;
    642         HashMapBucketType** buffer = this->buffer();
    643         HashMapBucketType* bucket = buffer[index];
    644         while (!isEmpty(bucket)) {
    645             if (canUseBucket(bucket)) {
    646                 bucket->setValue(vm, value);
    647                 return bucket;
    648             }
    649             index = (index + 1) & mask;
    650             bucket = buffer[index];
    651         }
    652 
    653         HashMapBucketType* newEntry = m_tail.get();
    654         buffer[index] = newEntry;
    655         newEntry->setKey(vm, key);
    656         newEntry->setValue(vm, value);
    657         ASSERT(!newEntry->deleted());
    658         HashMapBucketType* newTail = HashMapBucketType::create(vm);
    659         m_tail.set(vm, this, newTail);
    660         newTail->setPrev(vm, newEntry);
    661         ASSERT(newTail->deleted());
    662         newEntry->setNext(vm, newTail);
    663 
    664         ++m_keyCount;
    665         return newEntry;
    666     }
    667 
    668     ALWAYS_INLINE HashMapBucketType** findBucketAlreadyHashedAndNormalized(JSGlobalObject* globalObject, JSValue key, uint32_t hash)
    669     {
    670         const uint32_t mask = m_capacity - 1;
    671         uint32_t index = hash & mask;
    672         HashMapBucketType** buffer = this->buffer();
    673         HashMapBucketType* bucket = buffer[index];
    674 
    675         while (!isEmpty(bucket)) {
    676             if (!isDeleted(bucket) && areKeysEqual(globalObject, key, bucket->key()))
    677                 return buffer + index;
    678             index = (index + 1) & mask;
    679             bucket = buffer[index];
    680         }
    681         return nullptr;
    682     }
    683 
    684     void rehash(JSGlobalObject* globalObject)
    685     {
    686         VM& vm = getVM(globalObject);
    687         auto scope = DECLARE_THROW_SCOPE(vm);
    688 
    689         uint32_t oldCapacity = m_capacity;
    690         m_capacity = nextCapacity(m_capacity, m_keyCount);
    691 
    692         if (m_capacity != oldCapacity) {
    693             makeAndSetNewBuffer(globalObject, vm);
    694             RETURN_IF_EXCEPTION(scope, void());
    695         } else {
    696             m_buffer->reset(m_capacity);
    697             assertBufferIsEmpty();
    698         }
    699 
    700         HashMapBucketType* iter = m_head->next();
    701         HashMapBucketType* end = m_tail.get();
    702         const uint32_t mask = m_capacity - 1;
    703         RELEASE_ASSERT(!(m_capacity & (m_capacity - 1)));
    704         HashMapBucketType** buffer = this->buffer();
    705         while (iter != end) {
    706             uint32_t index = jsMapHash(globalObject, vm, iter->key()) & mask;
    707             EXCEPTION_ASSERT_WITH_MESSAGE(!scope.exception(), "All keys should already be hashed before, so this should not throw because it won't resolve ropes.");
    708             {
    709                 HashMapBucketType* bucket = buffer[index];
    710                 while (!isEmpty(bucket)) {
    711                     index = (index + 1) & mask;
    712                     bucket = buffer[index];
    713                 }
    714             }
    715             buffer[index] = iter;
    716             iter = iter->next();
    717         }
    718 
    719         m_deleteCount = 0;
    720 
    721         checkConsistency();
    722     }
    723 
    724     ALWAYS_INLINE void checkConsistency() const
    725     {
    726         if (ASSERT_ENABLED) {
    727             HashMapBucketType* iter = m_head->next();
    728             HashMapBucketType* end = m_tail.get();
    729             uint32_t size = 0;
    730             while (iter != end) {
    731                 ++size;
    732                 iter = iter->next();
    733             }
    734             ASSERT(size == m_keyCount);
    735         }
    736     }
    737 
    738     void makeAndSetNewBuffer(JSGlobalObject* globalObject, VM& vm)
    739     {
    740         ASSERT(!(m_capacity & (m_capacity - 1)));
    741 
    742         HashMapBufferType* buffer = HashMapBufferType::create(globalObject, vm, this, m_capacity);
    743         if (UNLIKELY(!buffer))
    744             return;
    745 
    746         m_buffer.set(vm, this, buffer);
    747         assertBufferIsEmpty();
    748     }
    749 
    750     ALWAYS_INLINE void assertBufferIsEmpty() const
    751     {
    752         if (ASSERT_ENABLED) {
    753             for (unsigned i = 0; i < m_capacity; i++)
    754                 ASSERT(isEmpty(buffer()[i]));
    755         }
    756     }
     376    ALWAYS_INLINE HashMapBucketType* addNormalizedInternal(VM&, JSValue key, JSValue, uint32_t hash, const CanUseBucket&);
     377
     378    ALWAYS_INLINE HashMapBucketType** findBucketAlreadyHashedAndNormalized(JSGlobalObject*, JSValue key, uint32_t hash);
     379
     380    void rehash(JSGlobalObject*);
     381
     382    ALWAYS_INLINE void checkConsistency() const;
     383
     384    void makeAndSetNewBuffer(JSGlobalObject*, VM&);
     385
     386    ALWAYS_INLINE void assertBufferIsEmpty() const;
    757387
    758388    WriteBarrier<HashMapBucketType> m_head;
  • trunk/Source/JavaScriptCore/runtime/JSMap.h

    r275271 r276039  
    11/*
    2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5555    }
    5656
    57     ALWAYS_INLINE void set(JSGlobalObject* globalObject, JSValue key, JSValue value)
    58     {
    59         add(globalObject, key, value);
    60     }
     57    ALWAYS_INLINE void set(JSGlobalObject*, JSValue key, JSValue);
    6158
    6259    static bool isSetFastAndNonObservable(Structure*);
  • trunk/Source/JavaScriptCore/runtime/JSWeakMap.h

    r261159 r276039  
    11/*
    2  * Copyright (C) 2013 Apple, Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple, Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4949    }
    5050
    51     ALWAYS_INLINE void set(VM& vm, JSObject* key, JSValue value)
    52     {
    53         add(vm, key, value);
    54     }
     51    ALWAYS_INLINE void set(VM&, JSObject* key, JSValue);
    5552
    5653private:
  • trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp

    r275271 r276039  
    11/*
    2  * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#include "IteratorOperations.h"
    3030#include "JSCInlines.h"
    31 #include "JSMap.h"
     31#include "JSMapInlines.h"
    3232#include "MapPrototype.h"
    3333
  • trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp

    r267594 r276039  
    11/*
    2  * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#include "BuiltinNames.h"
    3030#include "JSCInlines.h"
    31 #include "JSMap.h"
     31#include "JSMapInlines.h"
    3232#include "JSMapIterator.h"
    3333
  • trunk/Source/JavaScriptCore/runtime/SetConstructor.cpp

    r275271 r276039  
    11/*
    2  * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#include "IteratorOperations.h"
    3030#include "JSCInlines.h"
    31 #include "JSSet.h"
     31#include "JSSetInlines.h"
    3232#include "SetPrototype.h"
    3333
  • trunk/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp

    r275271 r276039  
    11/*
    2  * Copyright (C) 2013-2017 Apple, Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple, Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#include "IteratorOperations.h"
    3030#include "JSCInlines.h"
    31 #include "JSWeakMap.h"
     31#include "JSWeakMapInlines.h"
    3232#include "WeakMapPrototype.h"
    3333
  • trunk/Source/JavaScriptCore/runtime/WeakMapImpl.h

    r273138 r276039  
    5151static_assert(sizeof(WeakMapBucketDataKeyValue) == 16, "");
    5252
    53 ALWAYS_INLINE uint32_t jsWeakMapHash(JSObject* key)
    54 {
    55     return wangsInt64Hash(JSValue::encode(key));
    56 }
    57 
    58 ALWAYS_INLINE uint32_t nextCapacityAfterBatchRemoval(uint32_t capacity, uint32_t keyCount)
    59 {
    60     while (shouldShrink(capacity, keyCount))
    61         capacity = nextCapacity(capacity, keyCount);
    62     return capacity;
    63 }
     53ALWAYS_INLINE uint32_t jsWeakMapHash(JSObject* key);
     54ALWAYS_INLINE uint32_t nextCapacityAfterBatchRemoval(uint32_t capacity, uint32_t keyCount);
    6455
    6556template <typename Data>
     
    242233    }
    243234
    244     ALWAYS_INLINE void add(VM& vm, JSObject* key, JSValue value = JSValue())
    245     {
    246         DisallowGC disallowGC;
    247         add(vm, key, value, jsWeakMapHash(key));
    248     }
    249 
    250     ALWAYS_INLINE void add(VM& vm, JSObject* key, JSValue value, uint32_t hash)
    251     {
    252         DisallowGC disallowGC;
    253         ASSERT_WITH_MESSAGE(jsWeakMapHash(key) == hash, "We expect hash value is what we expect.");
    254 
    255         addInternal(vm, key, value, hash);
    256         if (shouldRehashAfterAdd())
    257             rehash();
    258     }
     235    ALWAYS_INLINE void add(VM&, JSObject* key, JSValue = JSValue());
     236    ALWAYS_INLINE void add(VM&, JSObject* key, JSValue, uint32_t hash);
    259237
    260238    ALWAYS_INLINE bool remove(JSObject* key)
     
    348326    }
    349327
    350     ALWAYS_INLINE uint32_t shouldRehashAfterAdd() const
    351     {
    352         return JSC::shouldRehashAfterAdd(m_capacity, m_keyCount, m_deleteCount);
    353     }
     328    ALWAYS_INLINE uint32_t shouldRehashAfterAdd() const;
    354329
    355330    ALWAYS_INLINE uint32_t shouldShrink() const
     
    404379
    405380    enum class RehashMode { Normal, RemoveBatching };
    406     void rehash(RehashMode mode = RehashMode::Normal)
    407     {
    408         // Since shrinking is done just after GC runs (finalizeUnconditionally), WeakMapImpl::rehash()
    409         // function must not touch any GC related features. This is why we do not allocate WeakMapBuffer
    410         // in auxiliary buffer.
    411 
    412         // This rehash modifies m_buffer which is not GC-managed buffer. But m_buffer can be touched in
    413         // visitOutputConstraints. Thus, we should guard it with cellLock.
    414         auto locker = holdLock(cellLock());
    415 
    416         uint32_t oldCapacity = m_capacity;
    417         MallocPtr<WeakMapBufferType, JSValueMalloc> oldBuffer = WTFMove(m_buffer);
    418 
    419         uint32_t capacity = m_capacity;
    420         if (mode == RehashMode::RemoveBatching) {
    421             ASSERT(shouldShrink());
    422             capacity = nextCapacityAfterBatchRemoval(capacity, m_keyCount);
    423         } else
    424             capacity = nextCapacity(capacity, m_keyCount);
    425         makeAndSetNewBuffer(locker, capacity);
    426 
    427         auto* buffer = this->buffer();
    428         const uint32_t mask = m_capacity - 1;
    429         for (uint32_t oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) {
    430             auto* entry = oldBuffer->buffer() + oldIndex;
    431             if (entry->isEmpty() || entry->isDeleted())
    432                 continue;
    433 
    434             uint32_t index = jsWeakMapHash(entry->key()) & mask;
    435             WeakMapBucketType* bucket = buffer + index;
    436             while (!bucket->isEmpty()) {
    437                 index = (index + 1) & mask;
    438                 bucket = buffer + index;
    439             }
    440             bucket->copyFrom(*entry);
    441         }
    442 
    443         m_deleteCount = 0;
    444 
    445         checkConsistency();
    446     }
     381    void rehash(RehashMode = RehashMode::Normal);
    447382
    448383    ALWAYS_INLINE void checkConsistency() const
  • trunk/Source/JavaScriptCore/runtime/WeakMapImplInlines.h

    r243467 r276039  
    2626#pragma once
    2727
     28#include "HashMapImplInlines.h"
    2829#include "WeakMapImpl.h"
    2930
    3031namespace JSC {
     32
     33ALWAYS_INLINE uint32_t jsWeakMapHash(JSObject* key)
     34{
     35    return wangsInt64Hash(JSValue::encode(key));
     36}
     37
     38ALWAYS_INLINE uint32_t nextCapacityAfterBatchRemoval(uint32_t capacity, uint32_t keyCount)
     39{
     40    while (shouldShrink(capacity, keyCount))
     41        capacity = nextCapacity(capacity, keyCount);
     42    return capacity;
     43}
     44
     45template <typename WeakMapBucket>
     46ALWAYS_INLINE void WeakMapImpl<WeakMapBucket>::add(VM& vm, JSObject* key, JSValue value)
     47{
     48    DisallowGC disallowGC;
     49    add(vm, key, value, jsWeakMapHash(key));
     50}
     51
     52template <typename WeakMapBucket>
     53ALWAYS_INLINE void WeakMapImpl<WeakMapBucket>::add(VM& vm, JSObject* key, JSValue value, uint32_t hash)
     54{
     55    DisallowGC disallowGC;
     56    ASSERT_WITH_MESSAGE(jsWeakMapHash(key) == hash, "We expect hash value is what we expect.");
     57
     58    addInternal(vm, key, value, hash);
     59    if (shouldRehashAfterAdd())
     60        rehash();
     61}
    3162
    3263// Note that this function can be executed in parallel as long as the mutator stops.
     
    5384}
    5485
     86template<typename WeakMapBucket>
     87void WeakMapImpl<WeakMapBucket>::rehash(RehashMode mode)
     88{
     89    // Since shrinking is done just after GC runs (finalizeUnconditionally), WeakMapImpl::rehash()
     90    // function must not touch any GC related features. This is why we do not allocate WeakMapBuffer
     91    // in auxiliary buffer.
     92
     93    // This rehash modifies m_buffer which is not GC-managed buffer. But m_buffer can be touched in
     94    // visitOutputConstraints. Thus, we should guard it with cellLock.
     95    auto locker = holdLock(cellLock());
     96
     97    uint32_t oldCapacity = m_capacity;
     98    MallocPtr<WeakMapBufferType, JSValueMalloc> oldBuffer = WTFMove(m_buffer);
     99
     100    uint32_t capacity = m_capacity;
     101    if (mode == RehashMode::RemoveBatching) {
     102        ASSERT(shouldShrink());
     103        capacity = nextCapacityAfterBatchRemoval(capacity, m_keyCount);
     104    } else
     105        capacity = nextCapacity(capacity, m_keyCount);
     106    makeAndSetNewBuffer(locker, capacity);
     107
     108    auto* buffer = this->buffer();
     109    const uint32_t mask = m_capacity - 1;
     110    for (uint32_t oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) {
     111        auto* entry = oldBuffer->buffer() + oldIndex;
     112        if (entry->isEmpty() || entry->isDeleted())
     113            continue;
     114
     115        uint32_t index = jsWeakMapHash(entry->key()) & mask;
     116        WeakMapBucket* bucket = buffer + index;
     117        while (!bucket->isEmpty()) {
     118            index = (index + 1) & mask;
     119            bucket = buffer + index;
     120        }
     121        bucket->copyFrom(*entry);
     122    }
     123
     124    m_deleteCount = 0;
     125
     126    checkConsistency();
    55127}
     128
     129template<typename WeakMapBucket>
     130ALWAYS_INLINE uint32_t WeakMapImpl<WeakMapBucket>::shouldRehashAfterAdd() const
     131{
     132    return JSC::shouldRehashAfterAdd(m_capacity, m_keyCount, m_deleteCount);
     133}
     134
     135} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/WeakMapPrototype.cpp

    r275271 r276039  
    11/*
    2  * Copyright (C) 2013-2019 Apple, Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple, Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828
    2929#include "JSCInlines.h"
    30 #include "JSWeakMap.h"
     30#include "JSWeakMapInlines.h"
    3131
    3232namespace JSC {
  • trunk/Source/WebCore/ChangeLog

    r276033 r276039  
     12021-04-15  Mark Lam  <mark.lam@apple.com>
     2
     3        Refactor inline functions out of HashMapImpl.h into HashMapImplInlines.h.
     4        https://bugs.webkit.org/show_bug.cgi?id=224616
     5        rdar://76713709
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        * bindings/js/SerializedScriptValue.cpp:
     10
    1112021-04-15  Alex Christensen  <achristensen@webkit.org>
    212
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r275882 r276039  
    7272#include <JavaScriptCore/JSCInlines.h>
    7373#include <JavaScriptCore/JSDataView.h>
    74 #include <JavaScriptCore/JSMap.h>
     74#include <JavaScriptCore/JSMapInlines.h>
    7575#include <JavaScriptCore/JSMapIterator.h>
    76 #include <JavaScriptCore/JSSet.h>
     76#include <JavaScriptCore/JSSetInlines.h>
    7777#include <JavaScriptCore/JSSetIterator.h>
    7878#include <JavaScriptCore/JSTypedArrays.h>
Note: See TracChangeset for help on using the changeset viewer.