Avoid unnecessary dynamic allocation when calling script functions.
Use tracer instead of rooting in ValueCloner, to avoid memory allocations. This was SVN commit r7770.
This commit is contained in:
parent
9674c3c0fe
commit
c4350d86de
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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<JSObject*> m_Objects;
|
||||
std::vector<jsval> m_Vals;
|
||||
// TODO: add vectors of other value types
|
||||
};
|
||||
|
||||
|
@ -426,17 +426,11 @@ jsval ScriptInterface::CallConstructor(jsval ctor)
|
||||
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name)
|
||||
{
|
||||
jsval jsRet;
|
||||
std::vector<jsval> argv;
|
||||
return CallFunction_(val, name, argv, jsRet);
|
||||
return CallFunction_(val, name, 0, NULL, jsRet);
|
||||
}
|
||||
|
||||
bool ScriptInterface::CallFunction_(jsval val, const char* name, std::vector<jsval>& 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<jsval, jsval> m_Mapping;
|
||||
std::deque<CScriptValRooted> m_ValuesOld;
|
||||
std::deque<CScriptValRooted> 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);
|
||||
}
|
||||
|
@ -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<jsval>& 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<jsval> 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<jsval> 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<typename T0, typename T1>
|
||||
@ -277,10 +276,10 @@ bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0
|
||||
{
|
||||
LOCAL_ROOT_SCOPE;
|
||||
jsval jsRet;
|
||||
std::vector<jsval> 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<typename T0, typename T1, typename T2>
|
||||
@ -288,11 +287,11 @@ bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0
|
||||
{
|
||||
LOCAL_ROOT_SCOPE;
|
||||
jsval jsRet;
|
||||
std::vector<jsval> 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<typename T0, typename R>
|
||||
@ -300,9 +299,9 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, R&
|
||||
{
|
||||
LOCAL_ROOT_SCOPE;
|
||||
jsval jsRet;
|
||||
std::vector<jsval> 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<jsval> 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<jsval> 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);
|
||||
|
Loading…
Reference in New Issue
Block a user