From bcd0e12cc3bc5a1b4bb72a7de26a63fdbf374eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lancelot=20de=20Ferri=C3=A8re?= Date: Thu, 8 May 2025 14:54:04 +0200 Subject: [PATCH] BinarySerializer: avoid creating unnecessary ScriptRequest --- .../serialization/BinarySerializer.cpp | 33 +++++++++---------- .../serialization/BinarySerializer.h | 9 ++--- .../serialization/StdDeserializer.cpp | 3 +- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/source/simulation2/serialization/BinarySerializer.cpp b/source/simulation2/serialization/BinarySerializer.cpp index fb44255732..93b5eacd5a 100644 --- a/source/simulation2/serialization/BinarySerializer.cpp +++ b/source/simulation2/serialization/BinarySerializer.cpp @@ -72,10 +72,13 @@ CBinarySerializerScriptImpl::~CBinarySerializerScriptImpl() JS_RemoveExtraGCRootsTracer(rq.cx, Trace, this); } -void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) +void CBinarySerializerScriptImpl::PutScriptVal(JS::HandleValue val) { - ScriptRequest rq(m_ScriptInterface); + HandleScriptVal(ScriptRequest(m_ScriptInterface), val); +} +void CBinarySerializerScriptImpl::HandleScriptVal(const ScriptRequest& rq, JS::HandleValue val) +{ switch (JS_TypeOfValue(rq.cx, val)) { case JSTYPE_UNDEFINED: @@ -94,7 +97,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) JS::RootedObject obj(rq.cx, &val.toObject()); // If we've already serialized this object, just output a reference to it - u32 tag = GetScriptBackrefTag(obj); + u32 tag = GetScriptBackrefTag(rq, obj); if (tag != 0) { m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_BACKREF); @@ -131,7 +134,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) // Now handle its array buffer // this may be a backref, since ArrayBuffers can be shared by multiple views JS::RootedValue bufferVal(rq.cx, JS::ObjectValue(*JS_GetArrayBufferViewBuffer(rq.cx, obj, &sharedMemory))); - HandleScriptVal(bufferVal); + HandleScriptVal(rq, bufferVal); break; } else if (JS::IsArrayBufferObject(obj)) @@ -179,8 +182,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) ENSURE(JS_GetElement(rq.cx, keyValuePairObj, 0, &key)); ENSURE(JS_GetElement(rq.cx, keyValuePairObj, 1, &value)); - HandleScriptVal(key); - HandleScriptVal(value); + HandleScriptVal(rq, key); + HandleScriptVal(rq, value); } break; } @@ -208,7 +211,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) if (done) break; - HandleScriptVal(value); + HandleScriptVal(rq, value); } break; } @@ -283,7 +286,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) JS::RootedString str(rq.cx, JS::ToString(rq.cx, val)); if (!str) throw PSERROR_Serialize_ScriptError("JS_ValueToString failed"); - ScriptString("value", str); + ScriptString(rq, "value", str); break; } else if (protokey == JSProto_Boolean) @@ -332,12 +335,12 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) if (!idstr) throw PSERROR_Serialize_ScriptError("JS_ValueToString failed"); - ScriptString("prop name", idstr); + ScriptString(rq, "prop name", idstr); if (!JS_GetPropertyById(rq.cx, obj, id, &propval)) throw PSERROR_Serialize_ScriptError("JS_GetPropertyById failed"); - HandleScriptVal(propval); + HandleScriptVal(rq, propval); } break; @@ -378,7 +381,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) { m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_STRING); JS::RootedString stringVal(rq.cx, val.toString()); - ScriptString("string", stringVal); + ScriptString(rq, "string", stringVal); break; } case JSTYPE_NUMBER: @@ -427,10 +430,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) } } -void CBinarySerializerScriptImpl::ScriptString(const char* name, JS::HandleString string) +void CBinarySerializerScriptImpl::ScriptString(const ScriptRequest& rq, const char* name, JS::HandleString string) { - ScriptRequest rq(m_ScriptInterface); - #if BYTE_ORDER != LITTLE_ENDIAN #error TODO: probably need to convert JS strings to little-endian #endif @@ -465,15 +466,13 @@ void CBinarySerializerScriptImpl::Trace(JSTracer *trc, void *data) serializer->m_ScriptBackrefTags.trace(trc); } -u32 CBinarySerializerScriptImpl::GetScriptBackrefTag(JS::HandleObject obj) +u32 CBinarySerializerScriptImpl::GetScriptBackrefTag(const ScriptRequest& rq, JS::HandleObject obj) { // To support non-tree structures (e.g. "var x = []; var y = [x, x];"), we need a way // to indicate multiple references to one object(/array). So every time we serialize a // new object, we give it a new tag; when we serialize it a second time we just refer // to that tag. - ScriptRequest rq(m_ScriptInterface); - ObjectTagMap::Ptr ptr = m_ScriptBackrefTags.lookup(JS::Heap(obj.get())); if (!ptr.found()) { diff --git a/source/simulation2/serialization/BinarySerializer.h b/source/simulation2/serialization/BinarySerializer.h index 675fa0df3b..a7eb90c3aa 100644 --- a/source/simulation2/serialization/BinarySerializer.h +++ b/source/simulation2/serialization/BinarySerializer.h @@ -86,9 +86,10 @@ public: CBinarySerializerScriptImpl(const ScriptInterface& scriptInterface, ISerializer& serializer); ~CBinarySerializerScriptImpl(); - void ScriptString(const char* name, JS::HandleString string); - void HandleScriptVal(JS::HandleValue val); + void PutScriptVal(JS::HandleValue val); private: + void ScriptString(const ScriptRequest& rq, const char* name, JS::HandleString string); + void HandleScriptVal(const ScriptRequest& rq, JS::HandleValue val); static void Trace(JSTracer* trc, void* data); const ScriptInterface& m_ScriptInterface; @@ -97,7 +98,7 @@ private: using ObjectTagMap = JS::GCHashMap, u32, js::StableCellHasher, js::SystemAllocPolicy>; ObjectTagMap m_ScriptBackrefTags; u32 m_ScriptBackrefsNext; - u32 GetScriptBackrefTag(JS::HandleObject obj); + u32 GetScriptBackrefTag(const ScriptRequest& rq, JS::HandleObject obj); JS::PropertyKey m_SerializePropId; JS::PropertyKey m_DeserializePropId; @@ -205,7 +206,7 @@ protected: virtual void PutScriptVal(const char* UNUSED(name), JS::MutableHandleValue value) { - m_ScriptImpl->HandleScriptVal(value); + m_ScriptImpl->PutScriptVal(value); } virtual void PutRaw(const char* name, const u8* data, size_t len) diff --git a/source/simulation2/serialization/StdDeserializer.cpp b/source/simulation2/serialization/StdDeserializer.cpp index 0b984062e2..c0976941fd 100644 --- a/source/simulation2/serialization/StdDeserializer.cpp +++ b/source/simulation2/serialization/StdDeserializer.cpp @@ -35,7 +35,8 @@ CStdDeserializer::CStdDeserializer(const ScriptInterface& scriptInterface, std::istream& stream) : m_ScriptInterface(scriptInterface), m_Stream(stream) { - JS_AddExtraGCRootsTracer(ScriptRequest(scriptInterface).cx, CStdDeserializer::Trace, this); + ScriptRequest rq(m_ScriptInterface); + JS_AddExtraGCRootsTracer(rq.cx, CStdDeserializer::Trace, this); m_SerializePropId = JS::PropertyKey::fromPinnedString(JS_AtomizeAndPinString(rq.cx, "Serialize")); m_DeserializePropId = JS::PropertyKey::fromPinnedString(JS_AtomizeAndPinString(rq.cx, "Deserialize"));