Ignore:
Timestamp:
Feb 29, 2020, 12:04:13 AM (5 years ago)
Author:
[email protected]
Message:

[JSC] BuiltinNames' HashMap should be small
https://bugs.webkit.org/show_bug.cgi?id=208404

Reviewed by Mark Lam.

Source/JavaScriptCore:

This patch converts public-to-private-name-map from HashMap<RefPtr<UniquedStringImpl>, SymbolImpl*> to HashSet<String> to save half of memory.
The key is that private names have the same string content to the public names. We can just query with string content to the HashSet of
private names, and we can get private names.

The problem is that we also have a hack inserting string <-> non-private well-known Symbol mappings into this table. These symbols do not have
the same content to the public string. So the above assumption is broken.

To make the above assumption valid, we have a separate small HashMap which holds string <-> non-private well-known Symbol mappings. Since # of
well-known Symbols are only 13, this new HashMap is taking at most 512B for entries, which is much smaller compared to the saved memory by
converting HashMap to HashSet for private names (32KB).

To allow it, we introduce new well-known Symbol identifier syntax to builtin JS, which is "@@iterator" format. If there is two "@", we parse this
identifier as a well-known Symbol.

  • builtins/ArrayConstructor.js:

(from.wrapper.iterator):
(from):
(from.wrapper.iteratorSymbol): Deleted.

  • builtins/ArrayPrototype.js:

(globalPrivate.concatSlowPath):
(concat):

  • builtins/BuiltinNames.cpp:

(JSC::BuiltinNames::BuiltinNames):
(JSC::CharBufferSeacher::hash):
(JSC::CharBufferSeacher::equal):
(JSC::lookUpPrivateNameImpl):
(JSC::lookUpWellKnownSymbolImpl):
(JSC::BuiltinNames::lookUpPrivateName const):
(JSC::BuiltinNames::lookUpWellKnownSymbol const):

  • builtins/BuiltinNames.h:

(JSC::BuiltinNames::lookUpPrivateName const):
(JSC::BuiltinNames::lookUpWellKnownSymbol const):
(JSC::BuiltinNames::checkPublicToPrivateMapConsistency):
(JSC::BuiltinNames::appendExternalName):
(JSC::BuiltinNames::getPublicName const): Deleted.

  • builtins/GlobalOperations.js:

(globalPrivate.speciesConstructor):

  • builtins/IteratorHelpers.js:

(performIteration):

  • builtins/StringPrototype.js:

(match):
(matchAll):
(intrinsic.StringPrototypeReplaceIntrinsic.replace):
(replaceAll):
(search):
(split):

  • builtins/TypedArrayConstructor.js:

(from.wrapper.iterator):
(from):
(from.wrapper.iteratorSymbol): Deleted.

  • builtins/TypedArrayPrototype.js:

(globalPrivate.typedArraySpeciesConstructor):
(map):
(filter):

  • bytecompiler/NodesCodegen.cpp:

(JSC::BytecodeIntrinsicNode::emit_intrinsic_getByIdDirectPrivate):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirectPrivate):

  • parser/Lexer.cpp:

(JSC::Lexer<LChar>::parseIdentifier):
(JSC::Lexer<UChar>::parseIdentifier):

  • runtime/CachedTypes.cpp:

(JSC::CachedUniquedStringImplBase::encode):
(JSC::CachedUniquedStringImplBase::decode const):

  • runtime/CommonIdentifiers.cpp:

(JSC::CommonIdentifiers::CommonIdentifiers):
(JSC::CommonIdentifiers::lookUpPrivateName const): Deleted.
(JSC::CommonIdentifiers::getPublicName const): Deleted.

  • runtime/CommonIdentifiers.h:
  • tools/JSDollarVM.cpp:

(JSC::functionGetPrivateProperty):

Source/WTF:

  • wtf/text/AtomStringImpl.cpp:

(WTF::HashTranslatorCharBuffer::HashTranslatorCharBuffer): Deleted.

  • wtf/text/StringImpl.h:

(WTF::HashTranslatorCharBuffer::HashTranslatorCharBuffer):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.cpp

    r249175 r257681  
    5353
    5454#define INITIALIZE_BUILTIN_NAMES_IN_JSC(name) , m_##name(JSC::Identifier::fromString(vm, #name))
    55 #define INITIALIZE_BUILTIN_SYMBOLS_IN_JSC(name) , m_##name##Symbol(JSC::Identifier::fromUid(vm, &static_cast<SymbolImpl&>(JSC::Symbols::name##Symbol))), m_##name##SymbolPrivateIdentifier(JSC::Identifier::fromString(vm, #name "Symbol"))
     55#define INITIALIZE_BUILTIN_SYMBOLS_IN_JSC(name) \
     56    , m_##name##Symbol(JSC::Identifier::fromUid(vm, &static_cast<SymbolImpl&>(JSC::Symbols::name##Symbol))) \
     57    , m_##name##SymbolPrivateIdentifier(JSC::Identifier::fromString(vm, #name))
    5658
    5759#define INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY(name) \
    5860    do { \
    5961        SymbolImpl* symbol = &static_cast<SymbolImpl&>(JSC::Symbols::name##PrivateName); \
    60         checkPublicToPrivateMapConsistency(m_##name.impl(), symbol); \
    61         m_publicToPrivateMap.add(m_##name.impl(), symbol); \
     62        checkPublicToPrivateMapConsistency(symbol); \
     63        m_privateNameSet.add(symbol); \
    6264    } while (0);
    6365
    64 // We commandeer the publicToPrivateMap to allow us to convert private symbol names into the appropriate symbol.
    65 // e.g. @iteratorSymbol points to Symbol.iterator in this map rather than to a an actual private name.
    66 // FIXME: This is a weird hack and we shouldn't need to do this.
    67 #define INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY(name) \
     66#define INITIALIZE_WELL_KNOWN_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY(name) \
    6867    do { \
    6968        SymbolImpl* symbol = static_cast<SymbolImpl*>(m_##name##Symbol.impl()); \
    70         checkPublicToPrivateMapConsistency(m_##name##SymbolPrivateIdentifier.impl(), symbol); \
    71         m_publicToPrivateMap.add(m_##name##SymbolPrivateIdentifier.impl(), symbol); \
     69        m_wellKnownSymbolsMap.add(m_##name##SymbolPrivateIdentifier.impl(), symbol); \
    7270    } while (0);
    7371
     
    8583    JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY)
    8684    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY)
    87     JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY)
    88     m_publicToPrivateMap.add(m_dollarVMName.impl(), static_cast<SymbolImpl*>(m_dollarVMPrivateName.impl()));
     85    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_WELL_KNOWN_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY)
     86    m_privateNameSet.add(static_cast<SymbolImpl*>(m_dollarVMPrivateName.impl()));
    8987}
    9088
     
    9290#undef INITIALIZE_BUILTIN_SYMBOLS_IN_JSC
    9391#undef INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY
    94 #undef INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY
     92#undef INITIALIZE_WELL_KNOWN_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY
     93
     94
     95using LCharBuffer = WTF::HashTranslatorCharBuffer<LChar>;
     96using UCharBuffer = WTF::HashTranslatorCharBuffer<UChar>;
     97
     98template<typename CharacterType>
     99struct CharBufferSeacher {
     100    using Buffer = WTF::HashTranslatorCharBuffer<CharacterType>;
     101    static unsigned hash(const Buffer& buf)
     102    {
     103        return buf.hash;
     104    }
     105
     106    static bool equal(const String& str, const Buffer& buf)
     107    {
     108        return WTF::equal(str.impl(), buf.characters, buf.length);
     109    }
     110};
     111
     112template<typename CharacterType>
     113static PrivateSymbolImpl* lookUpPrivateNameImpl(const HashSet<String>& set, const WTF::HashTranslatorCharBuffer<CharacterType>& buffer)
     114{
     115    auto iterator = set.find<CharBufferSeacher<CharacterType>>(buffer);
     116    if (iterator == set.end())
     117        return nullptr;
     118    StringImpl* impl = iterator->impl();
     119    ASSERT(impl->isSymbol());
     120    SymbolImpl* symbol = static_cast<SymbolImpl*>(impl);
     121    ASSERT(symbol->isPrivate());
     122    return static_cast<PrivateSymbolImpl*>(symbol);
     123}
     124
     125template<typename CharacterType>
     126static SymbolImpl* lookUpWellKnownSymbolImpl(const HashMap<String, SymbolImpl*>& map, const WTF::HashTranslatorCharBuffer<CharacterType>& buffer)
     127{
     128    auto iterator = map.find<CharBufferSeacher<CharacterType>>(buffer);
     129    if (iterator == map.end())
     130        return nullptr;
     131    return iterator->value;
     132}
     133
     134PrivateSymbolImpl* BuiltinNames::lookUpPrivateName(const LChar* characters, unsigned length) const
     135{
     136    LCharBuffer buffer { characters, length };
     137    return lookUpPrivateNameImpl(m_privateNameSet, buffer);
     138}
     139
     140PrivateSymbolImpl* BuiltinNames::lookUpPrivateName(const UChar* characters, unsigned length) const
     141{
     142    UCharBuffer buffer { characters, length };
     143    return lookUpPrivateNameImpl(m_privateNameSet, buffer);
     144}
     145
     146PrivateSymbolImpl* BuiltinNames::lookUpPrivateName(const String& string) const
     147{
     148    if (string.is8Bit()) {
     149        LCharBuffer buffer { string.characters8(), string.length(), string.hash() };
     150        return lookUpPrivateNameImpl(m_privateNameSet, buffer);
     151    }
     152    UCharBuffer buffer { string.characters16(), string.length(), string.hash() };
     153    return lookUpPrivateNameImpl(m_privateNameSet, buffer);
     154}
     155
     156SymbolImpl* BuiltinNames::lookUpWellKnownSymbol(const LChar* characters, unsigned length) const
     157{
     158    LCharBuffer buffer { characters, length };
     159    return lookUpWellKnownSymbolImpl(m_wellKnownSymbolsMap, buffer);
     160}
     161
     162SymbolImpl* BuiltinNames::lookUpWellKnownSymbol(const UChar* characters, unsigned length) const
     163{
     164    UCharBuffer buffer { characters, length };
     165    return lookUpWellKnownSymbolImpl(m_wellKnownSymbolsMap, buffer);
     166}
     167
     168SymbolImpl* BuiltinNames::lookUpWellKnownSymbol(const String& string) const
     169{
     170    if (string.is8Bit()) {
     171        LCharBuffer buffer { string.characters8(), string.length(), string.hash() };
     172        return lookUpWellKnownSymbolImpl(m_wellKnownSymbolsMap, buffer);
     173    }
     174    UCharBuffer buffer { string.characters16(), string.length(), string.hash() };
     175    return lookUpWellKnownSymbolImpl(m_wellKnownSymbolsMap, buffer);
     176}
    95177
    96178} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.