Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (285954 => 285955)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2021-11-17 22:28:11 UTC (rev 285954)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2021-11-17 22:51:04 UTC (rev 285955)
@@ -1085,6 +1085,7 @@
runtime/JSModuleLoader.h
runtime/JSModuleRecord.h
runtime/JSNativeStdFunction.h
+ runtime/JSONAtomStringCache.h
runtime/JSONObject.h
runtime/JSObject.h
runtime/JSObjectInlines.h
Modified: trunk/Source/_javascript_Core/ChangeLog (285954 => 285955)
--- trunk/Source/_javascript_Core/ChangeLog 2021-11-17 22:28:11 UTC (rev 285954)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-11-17 22:51:04 UTC (rev 285955)
@@ -1,3 +1,86 @@
+2021-11-17 Yusuke Suzuki <[email protected]>
+
+ [JSC] Revise JSON.parse atomize policy
+ https://bugs.webkit.org/show_bug.cgi?id=233231
+
+ Reviewed by Mark Lam.
+
+ This patch improves JSON.parse performance by the following two changes.
+
+ 1. Introduce JSONAtomStringCache. It is inspired from HTMLAtomStringCache. It offers cheap
+ fixed-sized cache stored in VM. Since it is in VM, we do not need to clear it every time
+ we call JSON.parse. We clear this cache when full GC happens. It contributes to
+ flight-todomvc-json-parse by 5%.
+ 2. Do not atomize long string. Profiling of JSON.parse said that most of time is used for
+ atomizing of Strings. There is a tradeoff that, atomizing strings can reduce duplicate string
+ allocations, but it has a performance penalty. V8 limits atomizing for <= 10 length strings,
+ and SpiderMonkey does not atomize strings. In this patch, we aligned our atomizing policy to
+ V8, so we do not atomize strings if the length is longer than 10. It contributes to
+ flight-todomvc-json-parse by 50%.
+
+ Many microbenchmarks show the improvement.
+ ToT Patched
+
+ json-parse-object-reviver-same-value 78.2683+-0.9598 77.7784+-0.9488
+ vanilla-es2015-babel-webpack-todomvc-json-parse
+ 99.9129+-0.5508 ^ 85.8160+-0.8721 ^ definitely 1.1643x faster
+ json-parse-array-reviver-same-value 63.5891+-0.8066 63.2895+-0.7336
+ flight-todomvc-json-parse 52.4230+-0.4474 ^ 34.1159+-0.2378 ^ definitely 1.5366x faster
+ json-parse-object-reviver 80.8417+-0.5042 80.6393+-0.8087
+ json-parse-leaf-object 51.6836+-0.6754 ^ 46.8983+-0.1578 ^ definitely 1.1020x faster
+ vanilla-es2015-todomvc-json-parse 100.5916+-0.9399 ^ 85.9522+-0.8470 ^ definitely 1.1703x faster
+ vanilla-todomvc-json-parse 76.4518+-0.4341 ^ 64.2318+-0.7621 ^ definitely 1.1902x faster
+ json-parse-array-reviver 76.1276+-0.8529 75.9747+-0.9002
+
+ And Speedometer2 shows 0.8% improvement.
+
+ ----------------------------------------------------------------------------------------------------------------------------------
+ | subtest | ms | ms | b / a | pValue (significance using False Discovery Rate) |
+ ----------------------------------------------------------------------------------------------------------------------------------
+ | Elm-TodoMVC |109.046667 |108.546667 |0.995415 | 0.197186 |
+ | VueJS-TodoMVC |21.813333 |21.566667 |0.988692 | 0.313141 |
+ | EmberJS-TodoMVC |117.796667 |118.086667 |1.002462 | 0.558244 |
+ | Flight-TodoMVC |64.273333 |62.260000 |0.968675 | 0.000000 (significant) |
+ | BackboneJS-TodoMVC |42.856667 |42.863333 |1.000156 | 0.975025 |
+ | Preact-TodoMVC |16.326667 |16.673333 |1.021233 | 0.298674 |
+ | AngularJS-TodoMVC |123.146667 |122.413333 |0.994045 | 0.160282 |
+ | Inferno-TodoMVC |57.510000 |57.533333 |1.000406 | 0.947767 |
+ | Vanilla-ES2015-TodoMVC |61.133333 |59.200000 |0.968375 | 0.000000 (significant) |
+ | Angular2-TypeScript-TodoMVC |38.863333 |38.963333 |1.002573 | 0.860359 |
+ | VanillaJS-TodoMVC |51.296667 |49.423333 |0.963480 | 0.000000 (significant) |
+ | jQuery-TodoMVC |210.933333 |210.596667 |0.998404 | 0.590132 |
+ | EmberJS-Debug-TodoMVC |326.093333 |324.890000 |0.996310 | 0.156955 |
+ | React-TodoMVC |81.113333 |81.360000 |1.003041 | 0.335615 |
+ | React-Redux-TodoMVC |132.560000 |132.256667 |0.997712 | 0.306072 |
+ | Vanilla-ES2015-Babel-Webpack-TodoMVC |60.073333 |59.026667 |0.982577 | 0.000883 (significant) |
+ ----------------------------------------------------------------------------------------------------------------------------------
+ a mean = 280.29390
+ b mean = 282.51413
+ pValue = 0.0000083325
+ (Bigger means are better.)
+ 1.008 times better
+ Results ARE significant
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * heap/Heap.cpp:
+ (JSC::Heap::finalize):
+ * runtime/JSONAtomStringCache.h: Added.
+ (JSC::JSONAtomStringCache::makeIdentifier):
+ (JSC::JSONAtomStringCache::clear):
+ (JSC::JSONAtomStringCache::cacheSlot):
+ (JSC::JSONAtomStringCache::cache):
+ * runtime/JSONAtomStringCacheInlines.h: Added.
+ (JSC::JSONAtomStringCache::make):
+ (JSC::JSONAtomStringCache::vm const):
+ * runtime/LiteralParser.cpp:
+ (JSC::LiteralParser<CharType>::makeIdentifier):
+ (JSC::LiteralParser<CharType>::makeJSString):
+ (JSC::LiteralParser<CharType>::parsePrimitiveValue):
+ (JSC::LiteralParser<CharType>::parse):
+ * runtime/LiteralParser.h:
+ * runtime/VM.h:
+
2021-11-15 Yusuke Suzuki <[email protected]>
[JSC] Use operation path when PutByVal child1 is not speculated as a Cell
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (285954 => 285955)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2021-11-17 22:28:11 UTC (rev 285954)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2021-11-17 22:51:04 UTC (rev 285955)
@@ -1875,6 +1875,8 @@
E32D4DE726DAFD4300D4533A /* TemporalCalendarPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D4DE126DAFD4200D4533A /* TemporalCalendarPrototype.h */; };
E32D4DE926DAFD4300D4533A /* TemporalCalendar.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D4DE326DAFD4300D4533A /* TemporalCalendar.h */; };
E32D4DEA26DAFD4300D4533A /* TemporalCalendarConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D4DE426DAFD4300D4533A /* TemporalCalendarConstructor.h */; };
+ E32FEA2C27448F3700FF41C1 /* JSONAtomStringCacheInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E32FEA2A27448F3600FF41C1 /* JSONAtomStringCacheInlines.h */; };
+ E32FEA2D27448F3700FF41C1 /* JSONAtomStringCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E32FEA2B27448F3600FF41C1 /* JSONAtomStringCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
E33095DD23210A1B00EB7856 /* JSInternalFieldObjectImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = E33095DC23210A1400EB7856 /* JSInternalFieldObjectImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
E334CBB521FD96A9000EB178 /* RegExpGlobalData.h in Headers */ = {isa = PBXBuildFile; fileRef = E334CBB321FD96A9000EB178 /* RegExpGlobalData.h */; settings = {ATTRIBUTES = (Private, ); }; };
E33637A61B63220200EE0840 /* ReflectObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E33637A41B63220200EE0840 /* ReflectObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -5176,6 +5178,8 @@
E32D4DE326DAFD4300D4533A /* TemporalCalendar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalCalendar.h; sourceTree = "<group>"; };
E32D4DE426DAFD4300D4533A /* TemporalCalendarConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalCalendarConstructor.h; sourceTree = "<group>"; };
E32D4DE526DAFD4300D4533A /* TemporalCalendarConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalCalendarConstructor.cpp; sourceTree = "<group>"; };
+ E32FEA2A27448F3600FF41C1 /* JSONAtomStringCacheInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONAtomStringCacheInlines.h; sourceTree = "<group>"; };
+ E32FEA2B27448F3600FF41C1 /* JSONAtomStringCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONAtomStringCache.h; sourceTree = "<group>"; };
E3305FB020B0F78700CEB82B /* InByVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InByVariant.cpp; sourceTree = "<group>"; };
E3305FB120B0F78800CEB82B /* InByVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InByVariant.h; sourceTree = "<group>"; };
E33095DC23210A1400EB7856 /* JSInternalFieldObjectImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSInternalFieldObjectImpl.h; sourceTree = "<group>"; };
@@ -7809,6 +7813,8 @@
BC22A3980E16E14800AF21C8 /* JSObject.cpp */,
BC22A3990E16E14800AF21C8 /* JSObject.h */,
0F93275E1C21EF7F00CF6564 /* JSObjectInlines.h */,
+ E32FEA2B27448F3600FF41C1 /* JSONAtomStringCache.h */,
+ E32FEA2A27448F3600FF41C1 /* JSONAtomStringCacheInlines.h */,
A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */,
A7F9935D0FD7325100A0B2D0 /* JSONObject.h */,
7C184E1817BEDBD3007CB63A /* JSPromise.cpp */,
@@ -10430,6 +10436,8 @@
0F93275F1C21EF7F00CF6564 /* JSObjectInlines.h in Headers */,
BC18C4250E16F5CD00B34460 /* JSObjectRef.h in Headers */,
A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */,
+ E32FEA2D27448F3700FF41C1 /* JSONAtomStringCache.h in Headers */,
+ E32FEA2C27448F3700FF41C1 /* JSONAtomStringCacheInlines.h in Headers */,
A7F9935F0FD7325100A0B2D0 /* JSONObject.h in Headers */,
BC87CDB910712AD4000614CF /* JSONObject.lut.h in Headers */,
7C184E1B17BEDBD3007CB63A /* JSPromise.h in Headers */,
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (285954 => 285955)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2021-11-17 22:28:11 UTC (rev 285954)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2021-11-17 22:51:04 UTC (rev 285955)
@@ -2048,6 +2048,9 @@
if (HasOwnPropertyCache* cache = vm().hasOwnPropertyCache())
cache->clear();
+ if (m_lastCollectionScope && m_lastCollectionScope.value() == CollectionScope::Full)
+ vm().jsonAtomStringCache.clear();
+
immutableButterflyToStringCache.clear();
for (const HeapFinalizerCallback& callback : m_heapFinalizerCallbacks)
Added: trunk/Source/_javascript_Core/runtime/JSONAtomStringCache.h (0 => 285955)
--- trunk/Source/_javascript_Core/runtime/JSONAtomStringCache.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/JSONAtomStringCache.h 2021-11-17 22:51:04 UTC (rev 285955)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/text/AtomStringImpl.h>
+
+namespace JSC {
+
+class VM;
+
+class JSONAtomStringCache {
+public:
+ static constexpr auto maxStringLengthForCache = 32;
+ static constexpr auto capacity = 512;
+ using Cache = std::array<RefPtr<AtomStringImpl>, capacity>;
+
+ enum class Type : bool { Identifier };
+ static constexpr unsigned numberOfTypes = 1;
+
+ template<typename CharacterType>
+ ALWAYS_INLINE Ref<AtomStringImpl> makeIdentifier(const CharacterType* characters, unsigned length)
+ {
+ return make(Type::Identifier, characters, length);
+ }
+
+ ALWAYS_INLINE void clear()
+ {
+ for (unsigned i = 0; i < numberOfTypes; ++i)
+ cache(static_cast<Type>(i)).fill({ });
+ }
+
+ VM& vm() const;
+
+private:
+ template<typename CharacterType>
+ Ref<AtomStringImpl> make(Type, const CharacterType*, unsigned length);
+
+ ALWAYS_INLINE RefPtr<AtomStringImpl>& cacheSlot(Type type, UChar firstCharacter, UChar lastCharacter, UChar length)
+ {
+ unsigned hash = (firstCharacter << 6) ^ ((lastCharacter << 14) ^ firstCharacter);
+ hash += (hash >> 14) + (length << 14);
+ hash ^= hash << 14;
+ return cache(type)[(hash + (hash >> 6)) % capacity];
+ }
+
+ ALWAYS_INLINE Cache& cache(Type type) { return m_caches[static_cast<size_t>(type)]; }
+
+ Cache m_caches[numberOfTypes] { };
+};
+
+} // namespace JSC
Added: trunk/Source/_javascript_Core/runtime/JSONAtomStringCacheInlines.h (0 => 285955)
--- trunk/Source/_javascript_Core/runtime/JSONAtomStringCacheInlines.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/JSONAtomStringCacheInlines.h 2021-11-17 22:51:04 UTC (rev 285955)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Identifier.h"
+#include "JSONAtomStringCache.h"
+#include "SmallStrings.h"
+#include "VM.h"
+
+namespace JSC {
+
+template<typename CharacterType>
+ALWAYS_INLINE Ref<AtomStringImpl> JSONAtomStringCache::make(Type type, const CharacterType* characters, unsigned length)
+{
+ if (!length)
+ return *static_cast<AtomStringImpl*>(StringImpl::empty());
+
+ auto firstCharacter = characters[0];
+ if (length == 1) {
+ if (firstCharacter <= maxSingleCharacterString)
+ return vm().smallStrings.singleCharacterStringRep(firstCharacter);
+ } else if (length > maxStringLengthForCache)
+ return AtomStringImpl::add(characters, length).releaseNonNull();
+
+ auto lastCharacter = characters[length - 1];
+ auto& slot = cacheSlot(type, firstCharacter, lastCharacter, length);
+ if (!equal(slot.get(), characters, length)) {
+ auto result = AtomStringImpl::add(characters, length);
+ slot = result;
+ return result.releaseNonNull();
+ }
+
+ return *slot;
+}
+
+ALWAYS_INLINE VM& JSONAtomStringCache::vm() const
+{
+ return *bitwise_cast<VM*>(bitwise_cast<uintptr_t>(this) - OBJECT_OFFSETOF(VM, jsonAtomStringCache));
+}
+
+} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/LiteralParser.cpp (285954 => 285955)
--- trunk/Source/_javascript_Core/runtime/LiteralParser.cpp 2021-11-17 22:28:11 UTC (rev 285954)
+++ trunk/Source/_javascript_Core/runtime/LiteralParser.cpp 2021-11-17 22:51:04 UTC (rev 285955)
@@ -30,6 +30,7 @@
#include "CodeBlock.h"
#include "JSArray.h"
#include "JSCInlines.h"
+#include "JSONAtomStringCacheInlines.h"
#include "Lexer.h"
#include "ObjectConstructor.h"
#include <wtf/ASCIICType.h>
@@ -143,51 +144,25 @@
}
template <typename CharType>
-ALWAYS_INLINE Identifier LiteralParser<CharType>::makeIdentifier(typename Lexer::LiteralParserTokenPtr token)
+ALWAYS_INLINE Identifier LiteralParser<CharType>::makeIdentifier(VM& vm, typename Lexer::LiteralParserTokenPtr token)
{
if (token->stringIs8Bit)
- return makeIdentifier(token->stringToken8, token->stringLength);
- return makeIdentifier(token->stringToken16, token->stringLength);
+ return Identifier::fromString(vm, vm.jsonAtomStringCache.makeIdentifier(token->stringToken8, token->stringLength));
+ return Identifier::fromString(vm, vm.jsonAtomStringCache.makeIdentifier(token->stringToken16, token->stringLength));
}
-
template <typename CharType>
-template <typename LiteralCharType>
-ALWAYS_INLINE Identifier LiteralParser<CharType>::makeIdentifier(const LiteralCharType* characters, size_t length)
+ALWAYS_INLINE JSString* LiteralParser<CharType>::makeJSString(VM& vm, typename Lexer::LiteralParserTokenPtr token)
{
- VM& vm = m_globalObject->vm();
- if (!length)
- return vm.propertyNames->emptyIdentifier;
-
- auto firstCharacter = characters[0];
- if (length == 1) {
- if constexpr (sizeof(LiteralCharType) == 1)
- return Identifier::fromString(vm, vm.smallStrings.singleCharacterStringRep(firstCharacter));
- if (firstCharacter <= maxSingleCharacterString)
- return Identifier::fromString(vm, vm.smallStrings.singleCharacterStringRep(firstCharacter));
- return Identifier::fromString(vm, characters, length);
+ constexpr unsigned maxAtomizeStringLength = 10;
+ if (token->stringIs8Bit) {
+ if (token->stringLength > maxAtomizeStringLength)
+ return jsString(vm, String(token->stringToken8, token->stringLength));
+ return jsString(vm, Identifier::fromString(vm, token->stringToken8, token->stringLength).string());
}
-
- if (firstCharacter >= maximumCachableCharacter)
- return Identifier::fromString(vm, characters, length);
-
- // 0 means no entry since m_recentIdentifiersIndex is zero-filled initially.
- uint8_t indexPlusOne = m_recentIdentifiersIndex[firstCharacter];
- if (indexPlusOne) {
- uint8_t index = indexPlusOne - 1;
- auto& ident = m_recentIdentifiers[index];
- if (Identifier::equal(ident.impl(), characters, length))
- return ident;
- auto result = Identifier::fromString(vm, characters, length);
- m_recentIdentifiers[index] = result;
- return result;
- }
-
- auto result = Identifier::fromString(vm, characters, length);
- m_recentIdentifiers.uncheckedAppend(result);
- indexPlusOne = m_recentIdentifiers.size();
- m_recentIdentifiersIndex[firstCharacter] = indexPlusOne;
- return result;
+ if (token->stringLength > maxAtomizeStringLength)
+ return jsString(vm, String(token->stringToken16, token->stringLength));
+ return jsString(vm, Identifier::fromString(vm, token->stringToken16, token->stringLength).string());
}
static ALWAYS_INLINE bool cannotBeIdentPartOrEscapeStart(LChar)
@@ -1144,7 +1119,7 @@
{
switch (m_lexer.currentToken()->type) {
case TokString: {
- JSValue result = jsString(vm, makeIdentifier(m_lexer.currentToken()).string());
+ JSString* result = makeJSString(vm, m_lexer.currentToken());
m_lexer.next();
return result;
}
@@ -1284,7 +1259,7 @@
TokenType type = m_lexer.next();
if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) {
while (true) {
- Identifier ident = makeIdentifier(m_lexer.currentToken());
+ Identifier ident = makeIdentifier(vm, m_lexer.currentToken());
if (UNLIKELY(m_lexer.next() != TokColon)) {
setErrorMessageForToken(TokColon);
@@ -1358,7 +1333,7 @@
m_parseErrorMessage = "Property name must be a string literal"_s;
return { };
}
- identifierStack.append(makeIdentifier(m_lexer.currentToken()));
+ identifierStack.append(makeIdentifier(vm, m_lexer.currentToken()));
// Check for colon
if (UNLIKELY(m_lexer.next() != TokColon)) {
Modified: trunk/Source/_javascript_Core/runtime/LiteralParser.h (285954 => 285955)
--- trunk/Source/_javascript_Core/runtime/LiteralParser.h 2021-11-17 22:28:11 UTC (rev 285954)
+++ trunk/Source/_javascript_Core/runtime/LiteralParser.h 2021-11-17 22:51:04 UTC (rev 285955)
@@ -197,9 +197,8 @@
JSValue parsePrimitiveValue(VM&);
- ALWAYS_INLINE Identifier makeIdentifier(typename Lexer::LiteralParserTokenPtr);
- template<typename LiteralCharType>
- ALWAYS_INLINE Identifier makeIdentifier(const LiteralCharType* characters, size_t length);
+ ALWAYS_INLINE Identifier makeIdentifier(VM&, typename Lexer::LiteralParserTokenPtr);
+ ALWAYS_INLINE JSString* makeJSString(VM&, typename Lexer::LiteralParserTokenPtr);
void setErrorMessageForToken(TokenType);
@@ -208,9 +207,6 @@
typename LiteralParser<CharType>::Lexer m_lexer;
ParserMode m_mode;
String m_parseErrorMessage;
- static constexpr unsigned maximumCachableCharacter = 128;
- std::array<uint8_t, maximumCachableCharacter> m_recentIdentifiersIndex { };
- Vector<Identifier, maximumCachableCharacter> m_recentIdentifiers;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/VM.h (285954 => 285955)
--- trunk/Source/_javascript_Core/runtime/VM.h 2021-11-17 22:28:11 UTC (rev 285954)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2021-11-17 22:51:04 UTC (rev 285955)
@@ -47,6 +47,7 @@
#include "JSCJSValue.h"
#include "JSDateMath.h"
#include "JSLock.h"
+#include "JSONAtomStringCache.h"
#include "MacroAssemblerCodeRef.h"
#include "Microtask.h"
#include "NumericStrings.h"
@@ -805,6 +806,7 @@
std::unique_ptr<SimpleStats> machineCodeBytesPerBytecodeWordForBaselineJIT;
WeakGCMap<StringImpl*, JSString, PtrHash<StringImpl*>> stringCache;
Strong<JSString> lastCachedString;
+ JSONAtomStringCache jsonAtomStringCache;
AtomStringTable* atomStringTable() const { return m_atomStringTable; }
WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; }