Bug 675068 - change off-main-thread cycle collection not to use a (thread-local) safe JS context (r=mrbkap)

--HG--
extra : rebase_source : b5a8a4ffa590bc9d0f2491d6a14bb95a37ff55e9
This commit is contained in:
Luke Wagner 2011-07-27 09:26:29 -07:00
parent 6fa760edaf
commit b79f27d2f5
3 changed files with 40 additions and 4 deletions

View File

@ -468,10 +468,22 @@ nsresult
nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
bool explainLiveExpectedGarbage)
{
// It is important not to call GetSafeJSContext while on the
// cycle-collector thread since this context will be destroyed
// asynchronously and race with the main thread. In particular, we must
// ensure that a context is passed to the XPCCallContext constructor.
JSContext *cx = mRuntime->GetJSCycleCollectionContext();
if (!cx)
return NS_ERROR_OUT_OF_MEMORY;
// Clear after mCycleCollectionContext is destroyed
JS_SetContextThread(cx);
NS_ASSERTION(!mCycleCollectionContext, "Didn't call FinishTraverse?");
mCycleCollectionContext = new XPCCallContext(NATIVE_CALLER);
mCycleCollectionContext = new XPCCallContext(NATIVE_CALLER, cx);
if (!mCycleCollectionContext->IsValid()) {
mCycleCollectionContext = nsnull;
JS_ClearContextThread(cx);
return NS_ERROR_FAILURE;
}
@ -521,8 +533,11 @@ nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
nsresult
nsXPConnect::FinishTraverse()
{
if (mCycleCollectionContext)
if (mCycleCollectionContext) {
JSContext *cx = mCycleCollectionContext->GetJSContext();
mCycleCollectionContext = nsnull;
JS_ClearContextThread(cx);
}
return NS_OK;
}

View File

@ -1057,6 +1057,18 @@ void XPCJSRuntime::SystemIsBeingShutDown(JSContext* cx)
Enumerate(DetachedWrappedNativeProtoShutdownMarker, cx);
}
JSContext *
XPCJSRuntime::GetJSCycleCollectionContext()
{
if(!mJSCycleCollectionContext) {
mJSCycleCollectionContext = JS_NewContext(mJSRuntime, 0);
if(!mJSCycleCollectionContext)
return nsnull;
JS_ClearContextThread(mJSCycleCollectionContext);
}
return mJSCycleCollectionContext;
}
XPCJSRuntime::~XPCJSRuntime()
{
if (mWatchdogWakeup)
@ -1077,6 +1089,12 @@ XPCJSRuntime::~XPCJSRuntime()
mWatchdogWakeup = nsnull;
}
if(mJSCycleCollectionContext)
{
JS_SetContextThread(mJSCycleCollectionContext);
JS_DestroyContextNoGC(mJSCycleCollectionContext);
}
#ifdef XPC_DUMP_AT_SHUTDOWN
{
// count the total JSContexts in use
@ -1905,6 +1923,7 @@ DiagnosticMemoryCallback(void *ptr, size_t size)
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
: mXPConnect(aXPConnect),
mJSRuntime(nsnull),
mJSCycleCollectionContext(nsnull),
mWrappedJSMap(JSObject2WrappedJSMap::newMap(XPC_JS_MAP_SIZE)),
mWrappedJSClassMap(IID2WrappedJSClassMap::newMap(XPC_JS_CLASS_MAP_SIZE)),
mIID2NativeInterfaceMap(IID2NativeInterfaceMap::newMap(XPC_NATIVE_INTERFACE_MAP_SIZE)),

View File

@ -654,6 +654,7 @@ public:
JSRuntime* GetJSRuntime() const {return mJSRuntime;}
nsXPConnect* GetXPConnect() const {return mXPConnect;}
JSContext* GetJSCycleCollectionContext();
JSObject2WrappedJSMap* GetWrappedJSMap() const
{return mWrappedJSMap;}
@ -800,8 +801,9 @@ private:
jsid mStrIDs[IDX_TOTAL_COUNT];
jsval mStrJSVals[IDX_TOTAL_COUNT];
nsXPConnect* mXPConnect;
JSRuntime* mJSRuntime;
nsXPConnect* mXPConnect;
JSRuntime* mJSRuntime;
JSContext* mJSCycleCollectionContext;
JSObject2WrappedJSMap* mWrappedJSMap;
IID2WrappedJSClassMap* mWrappedJSClassMap;
IID2NativeInterfaceMap* mIID2NativeInterfaceMap;