From c4350d86de496ff02401890ef0a40266d2a30582 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Mon, 19 Jul 2010 23:03:33 +0000 Subject: [PATCH] Avoid unnecessary dynamic allocation when calling script functions. Use tracer instead of rooting in ValueCloner, to avoid memory allocations. This was SVN commit r7770. --- source/scriptinterface/AutoRooters.cpp | 5 ++ source/scriptinterface/AutoRooters.h | 2 + source/scriptinterface/ScriptInterface.cpp | 32 +++++-------- source/scriptinterface/ScriptInterface.h | 55 +++++++++++----------- 4 files changed, 46 insertions(+), 48 deletions(-) diff --git a/source/scriptinterface/AutoRooters.cpp b/source/scriptinterface/AutoRooters.cpp index 51ec4f3f9f..a6047d5547 100644 --- a/source/scriptinterface/AutoRooters.cpp +++ b/source/scriptinterface/AutoRooters.cpp @@ -42,4 +42,9 @@ void AutoGCRooter::Trace(JSTracer* trc) { JS_CALL_OBJECT_TRACER(trc, m_Objects[i], "AutoGCRooter object"); } + + for (size_t i = 0; i < m_Vals.size(); ++i) + { + JS_CALL_VALUE_TRACER(trc, m_Vals[i], "AutoGCRooter val"); + } } diff --git a/source/scriptinterface/AutoRooters.h b/source/scriptinterface/AutoRooters.h index 7096c0a309..acdf8740b5 100644 --- a/source/scriptinterface/AutoRooters.h +++ b/source/scriptinterface/AutoRooters.h @@ -60,6 +60,7 @@ public: ~AutoGCRooter(); void Push(JSObject* obj) { m_Objects.push_back(obj); } + void Push(jsval val) { m_Vals.push_back(val); } void Trace(JSTracer* trc); private: @@ -67,6 +68,7 @@ private: AutoGCRooter* m_Previous; std::vector m_Objects; + std::vector m_Vals; // TODO: add vectors of other value types }; diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp index d11bac87da..2efd9b4be0 100644 --- a/source/scriptinterface/ScriptInterface.cpp +++ b/source/scriptinterface/ScriptInterface.cpp @@ -426,17 +426,11 @@ jsval ScriptInterface::CallConstructor(jsval ctor) bool ScriptInterface::CallFunctionVoid(jsval val, const char* name) { jsval jsRet; - std::vector argv; - return CallFunction_(val, name, argv, jsRet); + return CallFunction_(val, name, 0, NULL, jsRet); } -bool ScriptInterface::CallFunction_(jsval val, const char* name, std::vector& args, jsval& ret) +bool ScriptInterface::CallFunction_(jsval val, const char* name, size_t argc, jsval* argv, jsval& ret) { - const uintN argc = args.size(); - jsval* argv = NULL; - if (argc) - argv = &args[0]; - JSObject* obj; if (!JS_ValueToObject(m->m_cx, val, &obj) || obj == NULL) return false; @@ -668,7 +662,8 @@ void ScriptInterface::DumpHeap() class ValueCloner { public: - ValueCloner(JSContext* cxFrom, JSContext* cxTo) : cxFrom(cxFrom), cxTo(cxTo) + ValueCloner(ScriptInterface& from, ScriptInterface& to) : + cxFrom(from.GetContext()), cxTo(to.GetContext()), m_RooterFrom(from), m_RooterTo(to) { } @@ -682,7 +677,7 @@ public: if (it != m_Mapping.end()) return it->second; - m_ValuesOld.push_back(CScriptValRooted(cxFrom, val)); // root it so our mapping doesn't get invalidated + m_RooterFrom.Push(val); // root it so our mapping doesn't get invalidated return Clone(val); } @@ -699,7 +694,7 @@ private: jsval rval; CLONE_REQUIRE(JS_NewNumberValue(cxTo, *JSVAL_TO_DOUBLE(val), &rval), L"JS_NewNumberValue"); m_Mapping[val] = rval; - m_ValuesNew.push_back(CScriptValRooted(cxTo, rval)); + m_RooterTo.Push(rval); return rval; } @@ -709,7 +704,7 @@ private: CLONE_REQUIRE(str, L"JS_NewUCStringCopyN"); jsval rval = STRING_TO_JSVAL(str); m_Mapping[val] = rval; - m_ValuesNew.push_back(CScriptValRooted(cxTo, rval)); + m_RooterTo.Push(rval); return rval; } @@ -730,7 +725,7 @@ private: } m_Mapping[val] = OBJECT_TO_JSVAL(newObj); - m_ValuesNew.push_back(CScriptValRooted(cxTo, OBJECT_TO_JSVAL(newObj))); + m_RooterTo.Push(newObj); JSIdArray* ida = JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val)); CLONE_REQUIRE(ida, L"JS_Enumerate"); @@ -769,17 +764,14 @@ private: JSContext* cxFrom; JSContext* cxTo; std::map m_Mapping; - std::deque m_ValuesOld; - std::deque m_ValuesNew; + AutoGCRooter m_RooterFrom; + AutoGCRooter m_RooterTo; }; -jsval ScriptInterface::CloneValueFromOtherContext(const ScriptInterface& otherContext, jsval val) +jsval ScriptInterface::CloneValueFromOtherContext(ScriptInterface& otherContext, jsval val) { PROFILE("CloneValueFromOtherContext"); - JSContext* cxTo = GetContext(); - JSContext* cxFrom = otherContext.GetContext(); - - ValueCloner cloner(cxFrom, cxTo); + ValueCloner cloner(otherContext, *this); return cloner.GetOrClone(val); } diff --git a/source/scriptinterface/ScriptInterface.h b/source/scriptinterface/ScriptInterface.h index 0d87fe562e..009bdb0f90 100644 --- a/source/scriptinterface/ScriptInterface.h +++ b/source/scriptinterface/ScriptInterface.h @@ -174,7 +174,7 @@ public: * Complex values (functions, XML, etc) won't be cloned correctly, but basic * types and cyclic references should be fine. */ - jsval CloneValueFromOtherContext(const ScriptInterface& otherContext, jsval val); + jsval CloneValueFromOtherContext(ScriptInterface& otherContext, jsval val); /** * Convert a jsval to a C++ type. (This might trigger GC.) @@ -216,7 +216,7 @@ public: #define LOCAL_ROOT_SCOPE LocalRootScope scope(GetContext()); if (! scope.OK()) return false private: - bool CallFunction_(jsval val, const char* name, std::vector& args, jsval& ret); + bool CallFunction_(jsval val, const char* name, size_t argc, jsval* argv, jsval& ret); bool Eval_(const char* code, jsval& ret); bool Eval_(const wchar_t* code, jsval& ret); bool SetGlobal_(const char* name, jsval value, bool replace); @@ -255,8 +255,7 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, R& ret) { LOCAL_ROOT_SCOPE; jsval jsRet; - std::vector argv; - bool ok = CallFunction_(val, name, argv, jsRet); + bool ok = CallFunction_(val, name, 0, NULL, jsRet); if (!ok) return false; return FromJSVal(GetContext(), jsRet, ret); @@ -267,9 +266,9 @@ bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0 { LOCAL_ROOT_SCOPE; jsval jsRet; - std::vector argv; - argv.push_back(ToJSVal(GetContext(), a0)); - return CallFunction_(val, name, argv, jsRet); + jsval argv[1]; + argv[0] = ToJSVal(GetContext(), a0); + return CallFunction_(val, name, 1, argv, jsRet); } template @@ -277,10 +276,10 @@ bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0 { LOCAL_ROOT_SCOPE; jsval jsRet; - std::vector argv; - argv.push_back(ToJSVal(GetContext(), a0)); - argv.push_back(ToJSVal(GetContext(), a1)); - return CallFunction_(val, name, argv, jsRet); + jsval argv[2]; + argv[0] = ToJSVal(GetContext(), a0); + argv[1] = ToJSVal(GetContext(), a1); + return CallFunction_(val, name, 2, argv, jsRet); } template @@ -288,11 +287,11 @@ bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0 { LOCAL_ROOT_SCOPE; jsval jsRet; - std::vector argv; - argv.push_back(ToJSVal(GetContext(), a0)); - argv.push_back(ToJSVal(GetContext(), a1)); - argv.push_back(ToJSVal(GetContext(), a2)); - return CallFunction_(val, name, argv, jsRet); + jsval argv[3]; + argv[0] = ToJSVal(GetContext(), a0); + argv[1] = ToJSVal(GetContext(), a1); + argv[2] = ToJSVal(GetContext(), a2); + return CallFunction_(val, name, 3, argv, jsRet); } template @@ -300,9 +299,9 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, R& { LOCAL_ROOT_SCOPE; jsval jsRet; - std::vector argv; - argv.push_back(ToJSVal(GetContext(), a0)); - bool ok = CallFunction_(val, name, argv, jsRet); + jsval argv[1]; + argv[0] = ToJSVal(GetContext(), a0); + bool ok = CallFunction_(val, name, 1, argv, jsRet); if (!ok) return false; return FromJSVal(GetContext(), jsRet, ret); @@ -313,10 +312,10 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, co { LOCAL_ROOT_SCOPE; jsval jsRet; - std::vector argv; - argv.push_back(ToJSVal(GetContext(), a0)); - argv.push_back(ToJSVal(GetContext(), a1)); - bool ok = CallFunction_(val, name, argv, jsRet); + jsval argv[2]; + argv[0] = ToJSVal(GetContext(), a0); + argv[1] = ToJSVal(GetContext(), a1); + bool ok = CallFunction_(val, name, 2, argv, jsRet); if (!ok) return false; return FromJSVal(GetContext(), jsRet, ret); @@ -327,11 +326,11 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, co { LOCAL_ROOT_SCOPE; jsval jsRet; - std::vector argv; - argv.push_back(ToJSVal(GetContext(), a0)); - argv.push_back(ToJSVal(GetContext(), a1)); - argv.push_back(ToJSVal(GetContext(), a2)); - bool ok = CallFunction_(val, name, argv, jsRet); + jsval argv[3]; + argv[0] = ToJSVal(GetContext(), a0); + argv[1] = ToJSVal(GetContext(), a1); + argv[2] = ToJSVal(GetContext(), a2); + bool ok = CallFunction_(val, name, 3, argv, jsRet); if (!ok) return false; return FromJSVal(GetContext(), jsRet, ret);