diff options
| author | 2023-07-17 02:22:00 -0700 | |
|---|---|---|
| committer | 2023-07-17 02:22:00 -0700 | |
| commit | 13b5d9d4de4e9fe897d373a6ed7fdf2c9884c71f (patch) | |
| tree | 430b4913b4002cf320360b9f2fb175b1118da931 /src | |
| parent | fa4db1de428c80b561f66ac2dc38a67852c83225 (diff) | |
| download | bun-13b5d9d4de4e9fe897d373a6ed7fdf2c9884c71f.tar.gz bun-13b5d9d4de4e9fe897d373a6ed7fdf2c9884c71f.tar.zst bun-13b5d9d4de4e9fe897d373a6ed7fdf2c9884c71f.zip | |
20% faster `deserialize` (#3655)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/bun.js/bindings/webcore/SerializedScriptValue.cpp | 88 |
1 files changed, 85 insertions, 3 deletions
diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp index 60729ea65..176e805b8 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp @@ -2571,6 +2571,19 @@ private: { } + CachedString(const Identifier& identifier) + : m_identifier(identifier) + , m_string(identifier.string()) + { + } + + Identifier identifier(JSC::VM& vm) + { + if (m_identifier.isEmpty()) + m_identifier = Identifier::fromString(vm, string()); + return m_identifier; + } + JSValue jsString(JSGlobalObject* lexicalGlobalObject) { if (!m_jsString) @@ -2583,6 +2596,7 @@ private: private: String m_string; JSValue m_jsString; + Identifier m_identifier; }; struct CachedStringRef { @@ -2956,6 +2970,38 @@ private: return true; } + static bool readIdentifier(JSC::VM& vm, const uint8_t*& ptr, const uint8_t* end, Identifier& str, unsigned length, bool is8Bit) + { + if (length >= std::numeric_limits<int32_t>::max() / sizeof(UChar)) + return false; + + if (is8Bit) { + if ((end - ptr) < static_cast<int>(length)) + return false; + str = Identifier::fromString(vm, reinterpret_cast<const LChar*>(ptr), length); + ptr += length; + return true; + } + + unsigned size = length * sizeof(UChar); + if ((end - ptr) < static_cast<int>(size)) + return false; + +#if ASSUME_LITTLE_ENDIAN + str = Identifier::fromString(vm, reinterpret_cast<const UChar*>(ptr), length); + ptr += length * sizeof(UChar); +#else + UChar* characters; + str = String::createUninitialized(length, characters); + for (unsigned i = 0; i < length; ++i) { + uint16_t c; + readLittleEndian(ptr, end, c); + characters[i] = c; + } +#endif + return true; + } + bool readStringData(CachedStringRef& cachedString) { bool scratch; @@ -2998,6 +3044,42 @@ private: return true; } + bool readIdentifierData(JSC::VM& vm, CachedStringRef& cachedString, bool& wasTerminator) + { + if (m_failed) + return false; + uint32_t length = 0; + if (!read(length)) + return false; + if (length == TerminatorTag) { + wasTerminator = true; + return false; + } + if (length == StringPoolTag) { + unsigned index = 0; + if (!readStringIndex(index)) { + fail(); + return false; + } + if (index >= m_constantPool.size()) { + fail(); + return false; + } + cachedString = CachedStringRef(&m_constantPool, index); + return true; + } + bool is8Bit = length & StringDataIs8BitFlag; + length &= ~StringDataIs8BitFlag; + Identifier identifier; + if (!readIdentifier(vm, m_ptr, m_end, identifier, length, is8Bit)) { + fail(); + return false; + } + m_constantPool.append(identifier); + cachedString = CachedStringRef(&m_constantPool, m_constantPool.size() - 1); + return true; + } + SerializationTag readTag() { if (m_ptr >= m_end) @@ -4658,7 +4740,7 @@ DeserializationResult CloneDeserializer::deserialize() case ObjectStartVisitMember: { CachedStringRef cachedString; bool wasTerminator = false; - if (!readStringData(cachedString, wasTerminator)) { + if (!readIdentifierData(vm, cachedString, wasTerminator)) { if (!wasTerminator) goto error; @@ -4669,11 +4751,11 @@ DeserializationResult CloneDeserializer::deserialize() } if (JSValue terminal = readTerminal()) { - putProperty(outputObjectStack.last(), Identifier::fromString(vm, cachedString->string()), terminal); + putProperty(outputObjectStack.last(), cachedString->identifier(vm), terminal); goto objectStartVisitMember; } stateStack.append(ObjectEndVisitMember); - propertyNameStack.append(Identifier::fromString(vm, cachedString->string())); + propertyNameStack.append(cachedString->identifier(vm)); goto stateUnknown; } case ObjectEndVisitMember: { |
