20% faster deserialize (#3655)

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
Jarred Sumner
2023-07-17 02:22:00 -07:00
committed by GitHub
parent fa4db1de42
commit 13b5d9d4de
2 changed files with 197 additions and 12 deletions

View File

@@ -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: {