void XPCJSRuntime::UnsetContextGlobals() { if(!mClearedGlobalObjects.ops) return; RestoreContextGlobals(); JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { if(nsXPConnect::GetXPConnect()->GetRequestDepth(acx) == 0) { JS_ClearNewbornRoots(acx); if(acx->globalObject) { JSDHashEntryHdr* entry = JS_DHashTableOperate(&mClearedGlobalObjects, acx, JS_DHASH_ADD); ClearedGlobalObject* clearedGlobal = reinterpret_cast<ClearedGlobalObject*>(entry); if(clearedGlobal) { clearedGlobal->mContext = acx; clearedGlobal->mGlobalObject = acx->globalObject; acx->globalObject = nsnull; } } } } }
RuntimeContext::~RuntimeContext() { JS_SetContextThread(_context); JS_ClearNewbornRoots(_context); JS_ClearRegExpStatics(_context); JS_ClearPendingException(_context); JS_MaybeGC(_context); JS_DestroyContext(_context); }
void XPCJSRuntime::ClearWeakRoots() { JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { if(XPCPerThreadData::IsMainThread(acx) && nsXPConnect::GetXPConnect()->GetRequestDepth(acx) == 0) { JS_ClearNewbornRoots(acx); } } }
void XPCJSRuntime::UnrootContextGlobals() { mUnrootedGlobalCount = 0; JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { NS_ASSERTION(!JS_HAS_OPTION(acx, JSOPTION_UNROOTED_GLOBAL), "unrooted global should be set only during CC"); if(XPCPerThreadData::IsMainThread(acx) && nsXPConnect::GetXPConnect()->GetRequestDepth(acx) == 0) { JS_ClearNewbornRoots(acx); if(acx->globalObject) { JS_ToggleOptions(acx, JSOPTION_UNROOTED_GLOBAL); ++mUnrootedGlobalCount; } } } }
XPCCallContext::~XPCCallContext() { // do cleanup... PRBool shouldReleaseXPC = PR_FALSE; if(mXPCContext) { mXPCContext->SetCallingLangType(mPrevCallerLanguage); #ifdef DEBUG XPCCallContext* old = mThreadData->SetCallContext(mPrevCallContext); NS_ASSERTION(old == this, "bad pop from per thread data"); #else (void) mThreadData->SetCallContext(mPrevCallContext); #endif shouldReleaseXPC = mPrevCallContext == nsnull; } if(mContextPopRequired) { XPCJSContextStack* stack = mThreadData->GetJSContextStack(); NS_ASSERTION(stack, "bad!"); if(stack) { #ifdef DEBUG JSContext* poppedCX; nsresult rv = stack->Pop(&poppedCX); NS_ASSERTION(NS_SUCCEEDED(rv) && poppedCX == mJSContext, "bad pop"); #else (void) stack->Pop(nsnull); #endif } } if(mJSContext) { if(mCallerLanguage == NATIVE_CALLER) JS_EndRequest(mJSContext); if(mDestroyJSContextInDestructor) { #ifdef DEBUG_xpc_hacker printf("!xpc - doing deferred destruction of JSContext @ %0x\n", mJSContext); #endif NS_ASSERTION(!mThreadData->GetJSContextStack() || !mThreadData->GetJSContextStack()-> DEBUG_StackHasJSContext(mJSContext), "JSContext still in threadjscontextstack!"); JS_DestroyContext(mJSContext); } else { // Don't clear newborns if JS frames (compilation or execution) // are active! Doing so violates ancient invariants in the JS // engine, and it's not necessary to fix JS component leaks. if(!JS_IsRunning(mJSContext)) JS_ClearNewbornRoots(mJSContext); } } #ifdef DEBUG { StringWrapperEntry *se = reinterpret_cast<StringWrapperEntry*>(&mStringWrapperData); PRUint32 i; for(i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) { NS_ASSERTION(!se[i].mInUse, "Uh, string wrapper still in use!"); } } #endif if(shouldReleaseXPC && mXPC) NS_RELEASE(mXPC); }