BinarySerializer: avoid creating unnecessary ScriptRequest

This commit is contained in:
Lancelot de Ferrière 2025-05-08 14:54:04 +02:00 committed by wraitii
parent ab6a420f78
commit bcd0e12cc3
3 changed files with 23 additions and 22 deletions

View file

@ -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<JSObject*>(obj.get()));
if (!ptr.found())
{

View file

@ -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<JS::Heap<JSObject*>, u32, js::StableCellHasher<JSObject*>, 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)

View file

@ -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"));