Changeset 278971 in webkit
- Timestamp:
- Jun 16, 2021 8:09:57 PM (13 months ago)
- Location:
- trunk
- Files:
-
- 1 added
- 6 edited
-
JSTests/stress/json-parse-256.js (added)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/runtime/Identifier.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/Identifier.h (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/IdentifierInlines.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/LiteralParser.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/LiteralParser.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r278966 r278971 1 2021-06-16 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Optimize JSON.parse with small data by changing Identifier pool mechanism 4 https://bugs.webkit.org/show_bug.cgi?id=227101 5 6 Reviewed by Mark Lam. 7 8 Found that std::array<Identifier, 128> pool in LiteralParser is too costly for construction and destruction 9 if JSON.parse is invoked for small data. This patch changes this pool mechanism so that we do not waste effort 10 allocating null Identifiers to pre-populate the recent identifiers pool. Instead, we now use a m_recentIdentifiersIndex 11 uint8_t array to indicate whether there's a cached recent identifier for each given first character. 12 13 We also use KeywordLookup.h's COMPARE_XCHARS to perform "true" / "false" / "null" lexing in JSON parser. 14 Roughly 20% improvement in microbenchmark. And roughly 2-3% improvement in Speedometer2/Flight-TodoMVC. 15 16 ToT Patched 17 18 flight-todomvc-json 67.8755+-1.1202 ^ 56.7114+-0.5048 ^ definitely 1.1969x faster 19 20 * runtime/Identifier.cpp: 21 (JSC::Identifier::add): 22 (JSC::Identifier::add8): 23 * runtime/Identifier.h: 24 (JSC::Identifier::Identifier): 25 (JSC::Identifier::add): 26 * runtime/IdentifierInlines.h: 27 (JSC::Identifier::add): 28 (JSC::Identifier::fromString): 29 * runtime/LiteralParser.cpp: 30 (JSC::compare3Chars): 31 (JSC::compare4Chars): 32 (JSC::LiteralParser<CharType>::makeIdentifier): 33 (JSC::LiteralParser<CharType>::Lexer::lex): 34 * runtime/LiteralParser.h: 35 1 36 2021-06-16 Mark Lam <mark.lam@apple.com> 2 37 -
trunk/Source/JavaScriptCore/runtime/Identifier.cpp
r261895 r278971 28 28 namespace JSC { 29 29 30 Ref< StringImpl> Identifier::add(VM& vm, const char* c)30 Ref<AtomStringImpl> Identifier::add(VM& vm, const char* c) 31 31 { 32 32 ASSERT(c); … … 38 38 } 39 39 40 Ref< StringImpl> Identifier::add8(VM& vm, const UChar* s, int length)40 Ref<AtomStringImpl> Identifier::add8(VM& vm, const UChar* s, int length) 41 41 { 42 42 if (length == 1) { … … 47 47 } 48 48 if (!length) 49 return * StringImpl::empty();49 return *static_cast<AtomStringImpl*>(StringImpl::empty()); 50 50 51 51 return *AtomStringImpl::add(s, length); -
trunk/Source/JavaScriptCore/runtime/Identifier.h
r278921 r278971 118 118 static Identifier fromString(VM&, const String&); 119 119 static Identifier fromString(VM&, AtomStringImpl*); 120 static Identifier fromString(VM&, Ref<AtomStringImpl>&&); 120 121 static Identifier fromString(VM&, const AtomString&); 121 122 static Identifier fromString(VM& vm, SymbolImpl*); … … 160 161 161 162 // Only to be used with string literals. 162 JS_EXPORT_PRIVATE static Ref< StringImpl> add(VM&, const char*);163 JS_EXPORT_PRIVATE static Ref<AtomStringImpl> add(VM&, const char*); 163 164 164 165 void dump(PrintStream&) const; … … 178 179 Identifier(VM& vm, StringImpl* rep) : m_string(add(vm, rep)) { ASSERT(m_string.impl()->isAtom()); } 179 180 181 Identifier(VM&, Ref<AtomStringImpl>&& impl) 182 : m_string(WTFMove(impl)) 183 { } 184 180 185 Identifier(SymbolImpl& uid) 181 186 : m_string(&uid) 182 { 183 } 187 { } 184 188 185 189 template <typename CharType> … … 189 193 static bool equal(const Identifier& a, const LChar* b) { return equal(a.m_string.impl(), b); } 190 194 191 template <typename T> static Ref< StringImpl> add(VM&, const T*, int length);192 static Ref< StringImpl> add8(VM&, const UChar*, int length);195 template <typename T> static Ref<AtomStringImpl> add(VM&, const T*, int length); 196 static Ref<AtomStringImpl> add8(VM&, const UChar*, int length); 193 197 template <typename T> ALWAYS_INLINE static constexpr bool canUseSingleCharacterString(T); 194 198 195 static Ref< StringImpl> add(VM&, StringImpl*);199 static Ref<AtomStringImpl> add(VM&, StringImpl*); 196 200 197 201 #ifndef NDEBUG … … 214 218 215 219 template <typename T> 216 Ref< StringImpl> Identifier::add(VM& vm, const T* s, int length)220 Ref<AtomStringImpl> Identifier::add(VM& vm, const T* s, int length) 217 221 { 218 222 if (length == 1) { … … 222 226 } 223 227 if (!length) 224 return * StringImpl::empty();228 return *static_cast<AtomStringImpl*>(StringImpl::empty()); 225 229 226 230 return *AtomStringImpl::add(s, length); -
trunk/Source/JavaScriptCore/runtime/IdentifierInlines.h
r249175 r278971 56 56 } 57 57 58 inline Ref< StringImpl> Identifier::add(VM& vm, StringImpl* r)58 inline Ref<AtomStringImpl> Identifier::add(VM& vm, StringImpl* r) 59 59 { 60 60 #ifndef NDEBUG … … 112 112 } 113 113 114 inline Identifier Identifier::fromString(VM& vm, Ref<AtomStringImpl>&& atomStringImpl) 115 { 116 return Identifier(vm, WTFMove(atomStringImpl)); 117 } 118 114 119 inline Identifier Identifier::fromString(VM& vm, const AtomString& atomString) 115 120 { -
trunk/Source/JavaScriptCore/runtime/LiteralParser.cpp
r278921 r278971 37 37 #include <wtf/text/StringConcatenate.h> 38 38 39 #include "KeywordLookup.h" 40 39 41 namespace JSC { 42 43 template<typename CharType> 44 ALWAYS_INLINE bool compare3Chars(const CharType* source, CharType c0, CharType c1, CharType c2) 45 { 46 if constexpr (sizeof(CharType) == 1) 47 return COMPARE_3CHARS(source, c0, c1, c2); 48 else 49 return COMPARE_3UCHARS(source, c0, c1, c2); 50 } 51 52 template<typename CharType> 53 ALWAYS_INLINE bool compare4Chars(const CharType* source, CharType c0, CharType c1, CharType c2, CharType c3) 54 { 55 if constexpr (sizeof(CharType) == 1) 56 return COMPARE_4CHARS(source, c0, c1, c2, c3); 57 else 58 return COMPARE_4UCHARS(source, c0, c1, c2, c3); 59 } 40 60 41 61 template <typename CharType> … … 142 162 if (length == 1) { 143 163 if constexpr (sizeof(LiteralCharType) == 1) 144 return Identifier::fromString(vm, vm.smallStrings.singleCharacterStringRep(firstCharacter) .ptr());164 return Identifier::fromString(vm, vm.smallStrings.singleCharacterStringRep(firstCharacter)); 145 165 if (firstCharacter <= maxSingleCharacterString) 146 return Identifier::fromString(vm, vm.smallStrings.singleCharacterStringRep(firstCharacter) .ptr());166 return Identifier::fromString(vm, vm.smallStrings.singleCharacterStringRep(firstCharacter)); 147 167 return Identifier::fromString(vm, characters, length); 148 168 } … … 150 170 if (firstCharacter >= maximumCachableCharacter) 151 171 return Identifier::fromString(vm, characters, length); 152 if (!m_recentIdentifiers[firstCharacter].isNull() && Identifier::equal(m_recentIdentifiers[firstCharacter].impl(), characters, length)) 153 return m_recentIdentifiers[firstCharacter]; 154 m_recentIdentifiers[firstCharacter] = Identifier::fromString(vm, characters, length); 155 return m_recentIdentifiers[firstCharacter]; 172 173 // 0 means no entry since m_recentIdentifiersIndex is zero-filled initially. 174 uint8_t indexPlusOne = m_recentIdentifiersIndex[firstCharacter]; 175 if (indexPlusOne) { 176 uint8_t index = indexPlusOne - 1; 177 auto& ident = m_recentIdentifiers[index]; 178 if (Identifier::equal(ident.impl(), characters, length)) 179 return ident; 180 auto result = Identifier::fromString(vm, characters, length); 181 m_recentIdentifiers[index] = result; 182 return result; 183 } 184 185 auto result = Identifier::fromString(vm, characters, length); 186 m_recentIdentifiers.uncheckedAppend(result); 187 indexPlusOne = m_recentIdentifiers.size(); 188 m_recentIdentifiersIndex[firstCharacter] = indexPlusOne; 189 return result; 156 190 } 157 191 … … 709 743 switch (character) { 710 744 case 't': 711 if (m_end - m_ptr >= 4 && m_ptr[1] == 'r' && m_ptr[2] == 'u' && m_ptr[3] == 'e') {745 if (m_end - m_ptr >= 4 && compare3Chars<CharType>(m_ptr + 1, 'r', 'u', 'e')) { 712 746 m_ptr += 4; 713 747 token.type = TokTrue; … … 717 751 break; 718 752 case 'f': 719 if (m_end - m_ptr >= 5 && m_ptr[1] == 'a' && m_ptr[2] == 'l' && m_ptr[3] == 's' && m_ptr[4] == 'e') {753 if (m_end - m_ptr >= 5 && compare4Chars<CharType>(m_ptr + 1, 'a', 'l', 's', 'e')) { 720 754 m_ptr += 5; 721 755 token.type = TokFalse; … … 725 759 break; 726 760 case 'n': 727 if (m_end - m_ptr >= 4 && m_ptr[1] == 'u' && m_ptr[2] == 'l' && m_ptr[3] == 'l') {761 if (m_end - m_ptr >= 4 && compare3Chars<CharType>(m_ptr + 1, 'u', 'l', 'l')) { 728 762 m_ptr += 4; 729 763 token.type = TokNull; -
trunk/Source/JavaScriptCore/runtime/LiteralParser.h
r278921 r278971 176 176 177 177 private: 178 String m_lexErrorMessage;179 178 TokenType lex(LiteralParserToken<CharType>&); 180 179 ALWAYS_INLINE TokenType lexIdentifier(LiteralParserToken<CharType>&); … … 182 181 TokenType lexStringSlow(LiteralParserToken<CharType>&, const CharType* runStart, CharType terminator); 183 182 ALWAYS_INLINE TokenType lexNumber(LiteralParserToken<CharType>&); 183 184 String m_lexErrorMessage; 184 185 LiteralParserToken<CharType> m_currentToken; 185 186 ParserMode m_mode; … … 195 196 JSValue parse(ParserState); 196 197 198 template<typename LiteralCharType> 199 ALWAYS_INLINE Identifier makeIdentifier(const LiteralCharType* characters, size_t length); 200 197 201 JSGlobalObject* m_globalObject; 198 202 CodeBlock* m_nullOrCodeBlock; … … 201 205 String m_parseErrorMessage; 202 206 static constexpr unsigned maximumCachableCharacter = 128; 203 std::array<Identifier, maximumCachableCharacter> m_recentIdentifiers; 204 template<typename LiteralCharType> 205 ALWAYS_INLINE Identifier makeIdentifier(const LiteralCharType* characters, size_t length); 207 std::array<uint8_t, maximumCachableCharacter> m_recentIdentifiersIndex { }; 208 Vector<Identifier, maximumCachableCharacter> m_recentIdentifiers; 206 209 }; 207 210
Note: See TracChangeset
for help on using the changeset viewer.