Bug 915613 - Introduce a mechanism to get a default context for a runtime, and use that in js-ctypes. r=jorendorff

This causes us to use the SafeJSContext on main thread, and the singleton
JSContext on workers. I opted for the slightly-heavier-weight dynamic callback,
rather than just setting it as a member on the runtime, because we like to delay
the creation of the SafeJSContext a bit, so I didn't want to spin it up right
when we spin up the runtime.
This commit is contained in:
Bobby Holley 2013-09-24 08:03:23 -07:00
parent b1772a3a73
commit 986a60874a
8 changed files with 48 additions and 37 deletions

View File

@ -164,7 +164,6 @@ namespace CType {
static void Trace(JSTracer* trc, JSObject* obj);
static void Finalize(JSFreeOp *fop, JSObject* obj);
static void FinalizeProtoClass(JSFreeOp *fop, JSObject* obj);
static bool PrototypeGetter(JSContext* cx, HandleObject obj, HandleId idval,
MutableHandleValue vp);
@ -468,7 +467,7 @@ static const JSClass sCTypeProtoClass = {
"CType",
JSCLASS_HAS_RESERVED_SLOTS(CTYPEPROTO_SLOTS),
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, CType::FinalizeProtoClass,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
NULL, ConstructAbstract, NULL, ConstructAbstract
};
@ -3293,22 +3292,6 @@ CType::Finalize(JSFreeOp *fop, JSObject* obj)
}
}
void
CType::FinalizeProtoClass(JSFreeOp *fop, JSObject* obj)
{
// Finalize the CTypeProto class. The only important bit here is our
// SLOT_CLOSURECX -- it contains the JSContext that was (lazily) instantiated
// for use with FunctionType closures. And if we're here, in this finalizer,
// we're guaranteed to not need it anymore. Note that this slot will only
// be set for the object (of class CTypeProto) ctypes.FunctionType.prototype.
jsval slot = JS_GetReservedSlot(obj, SLOT_CLOSURECX);
if (JSVAL_IS_VOID(slot))
return;
JSContext* closureCx = static_cast<JSContext*>(JSVAL_TO_PRIVATE(slot));
JS_DestroyContextNoGC(closureCx);
}
void
CType::Trace(JSTracer* trc, JSObject* obj)
{
@ -6005,23 +5988,7 @@ CClosure::Create(JSContext* cx,
JS_ASSERT(CType::IsCTypeProto(proto));
// Get a JSContext for use with the closure.
jsval slot = JS_GetReservedSlot(proto, SLOT_CLOSURECX);
if (!JSVAL_IS_VOID(slot)) {
// Use the existing JSContext.
cinfo->cx = static_cast<JSContext*>(JSVAL_TO_PRIVATE(slot));
JS_ASSERT(cinfo->cx);
} else {
// Lazily instantiate a new JSContext, and stash it on
// ctypes.FunctionType.prototype.
JSRuntime* runtime = JS_GetRuntime(cx);
cinfo->cx = JS_NewContext(runtime, 8192);
if (!cinfo->cx) {
JS_ReportOutOfMemory(cx);
return NULL;
}
JS_SetReservedSlot(proto, SLOT_CLOSURECX, PRIVATE_TO_JSVAL(cinfo->cx));
}
cinfo->cx = js::DefaultJSContext(JS_GetRuntime(cx));
// Prepare the error sentinel value. It's important to do this now, because
// we might be unable to convert the value to the proper type. If so, we want

View File

@ -335,7 +335,6 @@ enum CTypeProtoSlot {
SLOT_UINT64PROTO = 10, // ctypes.UInt64.prototype object
SLOT_CTYPES = 11, // ctypes object
SLOT_OURDATAPROTO = 12, // the data prototype corresponding to this object
SLOT_CLOSURECX = 13, // JSContext for use with FunctionType closures
CTYPEPROTO_SLOTS
};

View File

@ -1068,6 +1068,24 @@ js::detail::IdMatchesAtom(jsid id, JSAtom *atom)
return id == INTERNED_STRING_TO_JSID(NULL, atom);
}
JS_FRIEND_API(JSContext *)
js::DefaultJSContext(JSRuntime *rt)
{
if (rt->defaultJSContextCallback) {
JSContext *cx = rt->defaultJSContextCallback(rt);
JS_ASSERT(cx);
return cx;
}
JS_ASSERT(rt->contextList.getFirst() == rt->contextList.getLast());
return rt->contextList.getFirst();
}
JS_FRIEND_API(void)
js::SetDefaultJSContextCallback(JSRuntime *rt, DefaultJSContextCallback cb)
{
rt->defaultJSContextCallback = cb;
}
JS_FRIEND_API(void)
js::SetCTypesActivityCallback(JSRuntime *rt, CTypesActivityCallback cb)
{

View File

@ -1507,6 +1507,20 @@ IsReadOnlyDateMethod(JS::IsAcceptableThis test, JS::NativeImpl method);
extern JS_FRIEND_API(bool)
IsTypedArrayThisCheck(JS::IsAcceptableThis test);
/*
* If the embedder has registered a default JSContext callback, returns the
* result of the callback. Otherwise, asserts that |rt| has exactly one
* JSContext associated with it, and returns that context.
*/
extern JS_FRIEND_API(JSContext *)
DefaultJSContext(JSRuntime *rt);
typedef JSContext*
(* DefaultJSContextCallback)(JSRuntime *rt);
JS_FRIEND_API(void)
SetDefaultJSContextCallback(JSRuntime *rt, DefaultJSContextCallback cb);
enum CTypesActivityType {
CTYPES_CALL_BEGIN,
CTYPES_CALL_END,

View File

@ -272,6 +272,7 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
jitSupportsFloatingPoint(false),
ionPcScriptCache(NULL),
threadPool(this),
defaultJSContextCallback(NULL),
ctypesActivityCallback(NULL),
parallelWarmup(0),
ionReturnOverride_(MagicValue(JS_ARG_POISON)),

View File

@ -1478,6 +1478,8 @@ struct JSRuntime : public JS::shadow::Runtime,
js::ThreadPool threadPool;
js::DefaultJSContextCallback defaultJSContextCallback;
js::CTypesActivityCallback ctypesActivityCallback;
// Non-zero if this is a parallel warmup execution. See

View File

@ -1209,7 +1209,15 @@ xpc::SimulateActivityCallback(bool aActive)
XPCJSRuntime::ActivityCallback(XPCJSRuntime::Get(), aActive);
}
//static
// static
JSContext*
XPCJSRuntime::DefaultJSContextCallback(JSRuntime *rt)
{
MOZ_ASSERT(rt == Get()->Runtime());
return Get()->GetJSContextStack()->GetSafeJSContext();
}
// static
void
XPCJSRuntime::ActivityCallback(void *arg, bool active)
{
@ -3019,6 +3027,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
stack->sampleRuntime(runtime);
#endif
JS_SetAccumulateTelemetryCallback(runtime, AccumulateTelemetryCallback);
js::SetDefaultJSContextCallback(runtime, DefaultJSContextCallback);
js::SetActivityCallback(runtime, ActivityCallback, this);
js::SetCTypesActivityCallback(runtime, CTypesActivityCallback);
JS_SetOperationCallback(runtime, OperationCallback);

View File

@ -764,6 +764,7 @@ public:
void AddContextCallback(xpcContextCallback cb);
void RemoveContextCallback(xpcContextCallback cb);
static JSContext* DefaultJSContextCallback(JSRuntime *rt);
static void ActivityCallback(void *arg, bool active);
static void CTypesActivityCallback(JSContext *cx,
js::CTypesActivityType type);