mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 19:08:50 +00:00
20% faster deserialize (#3655)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user