Changeset 188824 in webkit


Ignore:
Timestamp:
Aug 22, 2015, 11:05:50 AM (10 years ago)
Author:
[email protected]
Message:

[JSC] Static hash tables should be 100% compile-time constant.
<https://webkit.org/b/148359>

Reviewed by Michael Saboff.

Source/JavaScriptCore:

We were dirtying the memory pages containing static hash tables the
first time they were used, when a dynamically allocated index-to-key
table was built and cached in the HashTable struct.

It turns out that this "optimization" was completely useless, since
we've long since decoupled static hash tables from the JSC::VM and
we can get the key for an index via HashTable::values[index].m_key!

We also get rid of VM::keywords which was a little wrapper around
a VM-specific copy of JSC::mainTable. There was nothing VM-specific
about it at all, so clients now use JSC::mainTable directly.

After this change all fooHashTable structs end up in DATA const
and no runtime initialization/allocation takes place.

  • create_hash_table:
  • jsc.cpp:
  • parser/Lexer.cpp:

(JSC::isLexerKeyword):
(JSC::Lexer<LChar>::parseIdentifier):
(JSC::Lexer<UChar>::parseIdentifier):
(JSC::Lexer<CharacterType>::parseIdentifierSlowCase):
(JSC::Keywords::Keywords): Deleted.

  • parser/Lexer.h:

(JSC::Keywords::isKeyword): Deleted.
(JSC::Keywords::getKeyword): Deleted.
(JSC::Keywords::~Keywords): Deleted.

  • runtime/LiteralParser.cpp:

(JSC::LiteralParser<CharType>::tryJSONPParse):

  • runtime/Lookup.cpp:

(JSC::HashTable::createTable): Deleted.
(JSC::HashTable::deleteTable): Deleted.

  • runtime/Lookup.h:

(JSC::HashTable::entry):
(JSC::HashTable::ConstIterator::key):
(JSC::HashTable::ConstIterator::skipInvalidKeys):
(JSC::HashTable::copy): Deleted.
(JSC::HashTable::initializeIfNeeded): Deleted.
(JSC::HashTable::begin): Deleted.
(JSC::HashTable::end): Deleted.

  • runtime/VM.cpp:

(JSC::VM::VM): Deleted.

  • runtime/VM.h:
  • testRegExp.cpp:

Source/WebCore:

Adjust WebCore bindings generator for new JSC::HashTable layout
and rebaseline the bindings tests for that change.

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateHashTable):

  • bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:
  • bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp:
  • bindings/scripts/test/JS/JSTestEventTarget.cpp:
  • bindings/scripts/test/JS/JSTestException.cpp:
  • bindings/scripts/test/JS/JSTestInterface.cpp:
  • bindings/scripts/test/JS/JSTestObj.cpp:
  • bindings/scripts/test/JS/JSTestOverrideBuiltins.cpp:
  • bindings/scripts/test/JS/JSTestTypedefs.cpp:
Location:
trunk/Source
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r188810 r188824  
     12015-08-22  Andreas Kling  <[email protected]>
     2
     3        [JSC] Static hash tables should be 100% compile-time constant.
     4        <https://webkit.org/b/148359>
     5
     6        Reviewed by Michael Saboff.
     7
     8        We were dirtying the memory pages containing static hash tables the
     9        first time they were used, when a dynamically allocated index-to-key
     10        table was built and cached in the HashTable struct.
     11
     12        It turns out that this "optimization" was completely useless, since
     13        we've long since decoupled static hash tables from the JSC::VM and
     14        we can get the key for an index via HashTable::values[index].m_key!
     15
     16        We also get rid of VM::keywords which was a little wrapper around
     17        a VM-specific copy of JSC::mainTable. There was nothing VM-specific
     18        about it at all, so clients now use JSC::mainTable directly.
     19
     20        After this change all fooHashTable structs end up in __DATA __const
     21        and no runtime initialization/allocation takes place.
     22
     23        * create_hash_table:
     24        * jsc.cpp:
     25        * parser/Lexer.cpp:
     26        (JSC::isLexerKeyword):
     27        (JSC::Lexer<LChar>::parseIdentifier):
     28        (JSC::Lexer<UChar>::parseIdentifier):
     29        (JSC::Lexer<CharacterType>::parseIdentifierSlowCase):
     30        (JSC::Keywords::Keywords): Deleted.
     31        * parser/Lexer.h:
     32        (JSC::Keywords::isKeyword): Deleted.
     33        (JSC::Keywords::getKeyword): Deleted.
     34        (JSC::Keywords::~Keywords): Deleted.
     35        * runtime/LiteralParser.cpp:
     36        (JSC::LiteralParser<CharType>::tryJSONPParse):
     37        * runtime/Lookup.cpp:
     38        (JSC::HashTable::createTable): Deleted.
     39        (JSC::HashTable::deleteTable): Deleted.
     40        * runtime/Lookup.h:
     41        (JSC::HashTable::entry):
     42        (JSC::HashTable::ConstIterator::key):
     43        (JSC::HashTable::ConstIterator::skipInvalidKeys):
     44        (JSC::HashTable::copy): Deleted.
     45        (JSC::HashTable::initializeIfNeeded): Deleted.
     46        (JSC::HashTable::begin): Deleted.
     47        (JSC::HashTable::end): Deleted.
     48        * runtime/VM.cpp:
     49        (JSC::VM::VM): Deleted.
     50        * runtime/VM.h:
     51        * testRegExp.cpp:
     52
    1532015-08-21  Commit Queue  <[email protected]>
    254
  • trunk/Source/JavaScriptCore/create_hash_table

    r185370 r188824  
    331331    }
    332332    print "};\n\n";
    333     print "JS_EXPORT_PRIVATE extern const struct HashTable $name =\n";
    334     print "    \{ $packedSize, $compactHashSizeMask, $hasSetter, $nameEntries, 0, $nameIndex \};\n";
     333    print "static const struct HashTable $name =\n";
     334    print "    \{ $packedSize, $compactHashSizeMask, $hasSetter, $nameEntries, $nameIndex \};\n";
    335335    print "} // namespace\n";
    336336}
  • trunk/Source/JavaScriptCore/jsc.cpp

    r188752 r188824  
    104104using namespace WTF;
    105105
    106 namespace JSC {
    107 WTF_IMPORT extern const struct HashTable globalObjectTable;
    108 }
    109 
    110106namespace {
    111107
     
    721717};
    722718
    723 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, &globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
     719const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
    724720const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, nullptr, &moduleLoaderFetch, nullptr, nullptr };
    725721
  • trunk/Source/JavaScriptCore/parser/Lexer.cpp

    r188752 r188824  
    4545namespace JSC {
    4646
    47 Keywords::Keywords(VM& vm)
    48     : m_vm(vm)
    49     , m_keywordTable(JSC::mainTable)
    50 {
     47bool isLexerKeyword(const Identifier& identifier)
     48{
     49    return JSC::mainTable.entry(identifier);
    5150}
    5251
     
    949948        ASSERT(shouldCreateIdentifier);
    950949        if (remaining < maxTokenLength) {
    951             const HashTableValue* entry = m_vm->keywords->getKeyword(*ident);
     950            const HashTableValue* entry = JSC::mainTable.entry(*ident);
    952951            ASSERT((remaining < maxTokenLength) || !entry);
    953952            if (!entry)
     
    10261025        ASSERT(shouldCreateIdentifier);
    10271026        if (remaining < maxTokenLength) {
    1028             const HashTableValue* entry = m_vm->keywords->getKeyword(*ident);
     1027            const HashTableValue* entry = JSC::mainTable.entry(*ident);
    10291028            ASSERT((remaining < maxTokenLength) || !entry);
    10301029            if (!entry)
     
    10901089    if (LIKELY(!(lexerFlags & LexerFlagsIgnoreReservedWords))) {
    10911090        ASSERT(shouldCreateIdentifier);
    1092         const HashTableValue* entry = m_vm->keywords->getKeyword(*ident);
     1091        const HashTableValue* entry = JSC::mainTable.entry(*ident);
    10931092        if (!entry)
    10941093            return IDENT;
  • trunk/Source/JavaScriptCore/parser/Lexer.h

    r187587 r188824  
    3434namespace JSC {
    3535
    36 class Keywords {
    37     WTF_MAKE_FAST_ALLOCATED;
    38 public:
    39     bool isKeyword(const Identifier& ident) const
    40     {
    41         return m_keywordTable.entry(ident);
    42     }
    43    
    44     const HashTableValue* getKeyword(const Identifier& ident) const
    45     {
    46         return m_keywordTable.entry(ident);
    47     }
    48 
    49     explicit Keywords(VM&);
    50 
    51     ~Keywords()
    52     {
    53         m_keywordTable.deleteTable();
    54     }
    55    
    56 private:
    57     friend class VM;
    58    
    59     VM& m_vm;
    60     const HashTable m_keywordTable;
    61 };
    62 
    6336enum LexerFlags {
    6437    LexerFlagsIgnoreReservedWords = 1,
     
    6841
    6942struct ParsedUnicodeEscapeValue;
     43
     44bool isLexerKeyword(const Identifier&);
    7045
    7146template <typename T>
  • trunk/Source/JavaScriptCore/runtime/LiteralParser.cpp

    r188085 r188824  
    7171            path.append(entry);
    7272        }
    73         if (m_exec->vm().keywords->isKeyword(entry.m_pathEntryName))
     73        if (isLexerKeyword(entry.m_pathEntryName))
    7474            return false;
    7575        TokenType tokenType = m_lexer.next();
  • trunk/Source/JavaScriptCore/runtime/Lookup.cpp

    r185370 r188824  
    2727
    2828namespace JSC {
    29 
    30 void HashTable::createTable() const
    31 {
    32     ASSERT(!keys);
    33     keys = static_cast<const char**>(fastMalloc(sizeof(char*) * numberOfValues));
    34 
    35     for (int i = 0; i < numberOfValues; ++i) {
    36         if (values[i].m_key)
    37             keys[i] = values[i].m_key;
    38         else
    39             keys[i] = 0;
    40     }
    41 }
    42 
    43 void HashTable::deleteTable() const
    44 {
    45     if (keys) {
    46         fastFree(keys);
    47         keys = nullptr;
    48     }
    49 }
    5029
    5130void reifyStaticAccessor(VM& vm, const HashTableValue& value, JSObject& thisObj, PropertyName propertyName)
  • trunk/Source/JavaScriptCore/runtime/Lookup.h

    r185370 r188824  
    7373
    7474struct HashTable {
    75     mutable int numberOfValues;
     75    int numberOfValues;
    7676    int indexMask;
    7777    bool hasSetterOrReadonlyProperties;
    7878
    7979    const HashTableValue* values; // Fixed values generated by script.
    80     mutable const char** keys; // Table allocated at runtime.
    8180    const CompactHashIndex* index;
    82 
    83     ALWAYS_INLINE HashTable copy() const
    84     {
    85         // Don't copy dynamic table since it's thread specific.
    86         HashTable result = { numberOfValues, indexMask, hasSetterOrReadonlyProperties, values, 0, index };
    87         return result;
    88     }
    89 
    90     ALWAYS_INLINE void initializeIfNeeded() const
    91     {
    92         if (!keys)
    93             createTable();
    94     }
    95 
    96     JS_EXPORT_PRIVATE void deleteTable() const;
    9781
    9882    // Find an entry in the table, and return the entry.
    9983    ALWAYS_INLINE const HashTableValue* entry(PropertyName propertyName) const
    10084    {
    101         initializeIfNeeded();
    102 
    10385        if (propertyName.isSymbol())
    10486            return nullptr;
     
    10789        if (!uid)
    10890            return nullptr;
    109 
    110         ASSERT(keys);
    11191
    11292        int indexEntry = IdentifierRepHash::hash(uid) & indexMask;
     
    11696
    11797        while (true) {
    118             if (WTF::equal(uid, keys[valueIndex]))
     98            if (WTF::equal(uid, values[valueIndex].m_key))
    11999                return &values[valueIndex];
    120100
     
    143123        const char* key()
    144124        {
    145             return m_table->keys[m_position];
     125            return m_table->values[m_position].m_key;
    146126        }
    147127
     
    169149        {
    170150            ASSERT(m_position <= m_table->numberOfValues);
    171             while (m_position < m_table->numberOfValues && !m_table->keys[m_position])
     151            while (m_position < m_table->numberOfValues && !m_table->values[m_position].m_key)
    172152                ++m_position;
    173153            ASSERT(m_position <= m_table->numberOfValues);
     
    180160    ConstIterator begin() const
    181161    {
    182         initializeIfNeeded();
    183162        return ConstIterator(this, 0);
    184163    }
    185164    ConstIterator end() const
    186165    {
    187         initializeIfNeeded();
    188166        return ConstIterator(this, numberOfValues);
    189167    }
    190 
    191 private:
    192     // Convert the hash table keys to identifiers.
    193     JS_EXPORT_PRIVATE void createTable() const;
    194168};
    195169
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r188810 r188824  
    155155    , stringCache(*this)
    156156    , prototypeMap(*this)
    157     , keywords(std::make_unique<Keywords>(*this))
    158157    , interpreter(0)
    159158    , jsArrayClassInfo(JSArray::info())
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r188810 r188824  
    8787class JSGlobalObject;
    8888class JSObject;
    89 class Keywords;
    9089class LLIntOffsetsExtractor;
    9190class LegacyProfiler;
     
    350349    typedef HashMap<RefPtr<SourceProvider>, RefPtr<SourceProviderCache>> SourceProviderCacheMap;
    351350    SourceProviderCacheMap sourceProviderCacheMap;
    352     std::unique_ptr<Keywords> keywords;
    353351    Interpreter* interpreter;
    354352#if ENABLE(JIT)
  • trunk/Source/JavaScriptCore/testRegExp.cpp

    r185346 r188824  
    4646#endif
    4747
    48 namespace JSC {
    49 WTF_IMPORT extern const struct HashTable globalObjectTable;
    50 }
    51 
    5248const int MaxLineLength = 100 * 1024;
    5349
     
    138134};
    139135
    140 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, &globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
     136const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
    141137
    142138GlobalObject::GlobalObject(VM& vm, Structure* structure, const Vector<String>& arguments)
  • trunk/Source/WebCore/ChangeLog

    r188823 r188824  
     12015-08-22  Andreas Kling  <[email protected]>
     2
     3        [JSC] Static hash tables should be 100% compile-time constant.
     4        <https://webkit.org/b/148359>
     5
     6        Reviewed by Michael Saboff.
     7
     8        Adjust WebCore bindings generator for new JSC::HashTable layout
     9        and rebaseline the bindings tests for that change.
     10
     11        * bindings/scripts/CodeGeneratorJS.pm:
     12        (GenerateHashTable):
     13        * bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:
     14        * bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp:
     15        * bindings/scripts/test/JS/JSTestEventTarget.cpp:
     16        * bindings/scripts/test/JS/JSTestException.cpp:
     17        * bindings/scripts/test/JS/JSTestInterface.cpp:
     18        * bindings/scripts/test/JS/JSTestObj.cpp:
     19        * bindings/scripts/test/JS/JSTestOverrideBuiltins.cpp:
     20        * bindings/scripts/test/JS/JSTestTypedefs.cpp:
     21
    1222015-08-22  Michael Catanzaro  <[email protected]>
    223
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r188663 r188824  
    42294229
    42304230    my $compactSizeMask = $numEntries - 1;
    4231     push(@implContent, "static const HashTable $name = { $packedSize, $compactSizeMask, $hasSetter, $nameEntries, 0, $nameIndex };\n");
     4231    push(@implContent, "static const HashTable $name = { $packedSize, $compactSizeMask, $hasSetter, $nameEntries, $nameIndex };\n");
    42324232}
    42334233
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.cpp

    r188590 r188824  
    105105};
    106106
    107 static const HashTable JSTestActiveDOMObjectTable = { 2, 3, true, JSTestActiveDOMObjectTableValues, 0, JSTestActiveDOMObjectTableIndex };
     107static const HashTable JSTestActiveDOMObjectTable = { 2, 3, true, JSTestActiveDOMObjectTableValues, JSTestActiveDOMObjectTableIndex };
    108108const ClassInfo JSTestActiveDOMObjectConstructor::s_info = { "TestActiveDOMObjectConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSTestActiveDOMObjectConstructor) };
    109109
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp

    r188663 r188824  
    100100};
    101101
    102 static const HashTable JSTestCustomNamedGetterTable = { 1, 1, true, JSTestCustomNamedGetterTableValues, 0, JSTestCustomNamedGetterTableIndex };
     102static const HashTable JSTestCustomNamedGetterTable = { 1, 1, true, JSTestCustomNamedGetterTableValues, JSTestCustomNamedGetterTableIndex };
    103103const ClassInfo JSTestCustomNamedGetterConstructor::s_info = { "TestCustomNamedGetterConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSTestCustomNamedGetterConstructor) };
    104104
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventTarget.cpp

    r188663 r188824  
    109109};
    110110
    111 static const HashTable JSTestEventTargetTable = { 1, 1, true, JSTestEventTargetTableValues, 0, JSTestEventTargetTableIndex };
     111static const HashTable JSTestEventTargetTable = { 1, 1, true, JSTestEventTargetTableValues, JSTestEventTargetTableIndex };
    112112const ClassInfo JSTestEventTargetConstructor::s_info = { "TestEventTargetConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSTestEventTargetConstructor) };
    113113
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestException.cpp

    r188590 r188824  
    9696};
    9797
    98 static const HashTable JSTestExceptionTable = { 1, 1, true, JSTestExceptionTableValues, 0, JSTestExceptionTableIndex };
     98static const HashTable JSTestExceptionTable = { 1, 1, true, JSTestExceptionTableValues, JSTestExceptionTableIndex };
    9999const ClassInfo JSTestExceptionConstructor::s_info = { "TestExceptionConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSTestExceptionConstructor) };
    100100
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp

    r188590 r188824  
    195195};
    196196
    197 static const HashTable JSTestInterfaceTable = { 2, 3, true, JSTestInterfaceTableValues, 0, JSTestInterfaceTableIndex };
     197static const HashTable JSTestInterfaceTable = { 2, 3, true, JSTestInterfaceTableValues, JSTestInterfaceTableIndex };
    198198/* Hash table for constructor */
    199199
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp

    r188590 r188824  
    395395};
    396396
    397 static const HashTable JSTestObjTable = { 6, 15, true, JSTestObjTableValues, 0, JSTestObjTableIndex };
     397static const HashTable JSTestObjTable = { 6, 15, true, JSTestObjTableValues, JSTestObjTableIndex };
    398398/* Hash table for constructor */
    399399
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestOverrideBuiltins.cpp

    r188663 r188824  
    102102};
    103103
    104 static const HashTable JSTestOverrideBuiltinsTable = { 1, 1, true, JSTestOverrideBuiltinsTableValues, 0, JSTestOverrideBuiltinsTableIndex };
     104static const HashTable JSTestOverrideBuiltinsTable = { 1, 1, true, JSTestOverrideBuiltinsTableValues, JSTestOverrideBuiltinsTableIndex };
    105105const ClassInfo JSTestOverrideBuiltinsConstructor::s_info = { "TestOverrideBuiltinsConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSTestOverrideBuiltinsConstructor) };
    106106
  • trunk/Source/WebCore/bindings/scripts/test/JS/JSTestTypedefs.cpp

    r188590 r188824  
    136136};
    137137
    138 static const HashTable JSTestTypedefsTable = { 0, 1, false, JSTestTypedefsTableValues, 0, JSTestTypedefsTableIndex };
     138static const HashTable JSTestTypedefsTable = { 0, 1, false, JSTestTypedefsTableValues, JSTestTypedefsTableIndex };
    139139/* Hash table for constructor */
    140140
Note: See TracChangeset for help on using the changeset viewer.