JSDContext* jsd_DebuggerOnForUser(JSTaskState* jstaskstate, JSD_UserCallbacks* callbacks, void* user) { JSDContext* jsdc; JSContext* iter = NULL; JSContext* cx; jsdc = _newJSDContext(jstaskstate, callbacks, user); if( ! jsdc ) return NULL; /* set hooks here */ JS_SetNewScriptHookProc(jsdc->jstaskstate, jsd_NewScriptHookProc, jsdc); JS_SetDestroyScriptHookProc(jsdc->jstaskstate, jsd_DestroyScriptHookProc, jsdc); #ifdef LIVEWIRE LWDBG_SetNewScriptHookProc(jsd_NewScriptHookProc, jsdc); #endif /* enumerate contexts for JSTaskState and add them to our table */ while( NULL != (cx = JS_ContextIterator(jsdc->jstaskstate, &iter)) ) jsd_JSContextUsed(jsdc, cx); if( jsdc->userCallbacks.setContext ) jsdc->userCallbacks.setContext(jsdc, jsdc->user); return jsdc; }
void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc) { if(mClearedGlobalObjects.ops) { JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { JSDHashEntryHdr* entry = JS_DHashTableOperate(&mClearedGlobalObjects, acx, JS_DHASH_LOOKUP); if(JS_DHASH_ENTRY_IS_BUSY(entry)) { ClearedGlobalObject* clearedGlobal = reinterpret_cast<ClearedGlobalObject*>(entry); JS_CALL_OBJECT_TRACER(trc, clearedGlobal->mGlobalObject, "global object"); } } } XPCWrappedNativeScope::TraceJS(trc, this); for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) static_cast<XPCTraceableVariant*>(e)->TraceJS(trc); for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc); if(mJSHolders.ops) JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc); }
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; } } } } }
void XPCJSRuntime::RootContextGlobals() { JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { if(JS_HAS_OPTION(acx, JSOPTION_UNROOTED_GLOBAL)) { JS_ToggleOptions(acx, JSOPTION_UNROOTED_GLOBAL); --mUnrootedGlobalCount; } } NS_ASSERTION(mUnrootedGlobalCount == 0, "bad state"); }
static void deallocate(JohnsonRuntime* runtime) { JS_RemoveRoot(johnson_get_current_context(runtime), &(runtime->global)); JSContext *context; JSContext *iterator = NULL; while ((context = JS_ContextIterator(runtime->js, &iterator)) != NULL) JS_DestroyContext(context); JS_DestroyRuntime(runtime->js); free(runtime); }
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); } } }
XPCContext* XPCJSRuntime::SyncXPCContextList(JSContext* cx /* = nsnull */) { // hold the map lock through this whole thing XPCAutoLock lock(GetMapLock()); XPCContext* found = nsnull; // add XPCContexts that represent any JSContexts we have not seen before JSContext *cur, *iter = nsnull; while(nsnull != (cur = JS_ContextIterator(mJSRuntime, &iter))) { XPCContext* xpcc = mContextMap->Find(cur); if(!xpcc) { xpcc = XPCContext::newXPCContext(this, cur); if(xpcc) mContextMap->Add(xpcc); } if(xpcc) { xpcc->Mark(); } // if it is our first context then we need to generate our string ids if(!mStrIDs[0]) { JSAutoRequest ar(cur); GenerateStringIDs(cur); } if(cx && cx == cur) found = xpcc; } // get rid of any XPCContexts that represent dead JSContexts mContextMap->Enumerate(SweepContextsCB, 0); XPCPerThreadData* tls = XPCPerThreadData::GetData(cx); if(tls) { if(found) tls->SetRecentContext(cx, found); else tls->ClearRecentContext(); } return found; }
/*---------------------------------------------------------------------------*/ WebcJSBrowserContext::~WebcJSBrowserContext (void) { JSContext* acx = 0; JSContext* iterp = WEBC_NULL; #if (WEBC_DEBUG_JSCRIPT) if (mJSDebug) WEBC_DELETE(mJSDebug); #endif while ((acx = JS_ContextIterator(mRuntime, &iterp)) != WEBC_NULL) { JS_GC(acx); JS_DestroyContext(acx); iterp = WEBC_NULL; } JS_DestroyRuntime(mRuntime); JS_ShutDown(); }
void XPCJSRuntime::RestoreContextGlobals() { if(!mClearedGlobalObjects.ops || mClearedGlobalObjects.entryCount == 0) return; JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { JSDHashEntryHdr* entry = JS_DHashTableOperate(&mClearedGlobalObjects, acx, JS_DHASH_LOOKUP); if(JS_DHASH_ENTRY_IS_BUSY(entry)) { ClearedGlobalObject* clearedGlobal = reinterpret_cast<ClearedGlobalObject*>(entry); acx->globalObject = clearedGlobal->mGlobalObject; } } JS_DHashTableEnumerate(&mClearedGlobalObjects, RemoveContextGlobal, nsnull); }
void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc) { JSContext *iter = nsnull, *acx; while ((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { JS_ASSERT(JS_HAS_OPTION(acx, JSOPTION_UNROOTED_GLOBAL)); if (acx->globalObject) JS_CALL_OBJECT_TRACER(trc, acx->globalObject, "global object"); } XPCWrappedNativeScope::TraceJS(trc, this); for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) static_cast<XPCTraceableVariant*>(e)->TraceJS(trc); for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc); if(mJSHolders.ops) JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc); }
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; } } } }
void XPCJSRuntime::AddXPConnectRoots(JSContext* cx, nsCycleCollectionTraversalCallback &cb) { // For all JS objects that are held by native objects but aren't held // through rooting or locking, we need to add all the native objects that // hold them so that the JS objects are colored correctly in the cycle // collector. This includes JSContexts that don't have outstanding requests, // because their global object wasn't marked by the JS GC. All other JS // roots were marked by the JS GC and will be colored correctly in the cycle // collector. JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { #ifndef DEBUG_CC // Only skip JSContexts with outstanding requests if DEBUG_CC is not // defined, else we do want to know about all JSContexts to get better // graphs and explanations. if(nsXPConnect::GetXPConnect()->GetRequestDepth(acx) != 0) continue; #endif cb.NoteRoot(nsIProgrammingLanguage::CPLUSPLUS, acx, nsXPConnect::JSContextParticipant()); } XPCWrappedNativeScope::SuspectAllWrappers(this, cx, cb); for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) cb.NoteXPCOMRoot(static_cast<XPCTraceableVariant*>(e)); for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) { nsIXPConnectWrappedJS *wrappedJS = static_cast<nsXPCWrappedJS*>(e); cb.NoteXPCOMRoot(wrappedJS); } if(mJSHolders.ops) JS_DHashTableEnumerate(&mJSHolders, NoteJSHolder, &cb); }
void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc, JSBool rootGlobals) { if(mUnrootedGlobalCount != 0) { JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(GetJSRuntime(), &iter))) { if(JS_HAS_OPTION(acx, JSOPTION_UNROOTED_GLOBAL)) { NS_ASSERTION(nsXPConnect::GetXPConnect()->GetRequestDepth(acx) == 0, "active cx must be always rooted"); NS_ASSERTION(acx->globalObject, "bad state"); JS_CALL_OBJECT_TRACER(trc, acx->globalObject, "global object"); if(rootGlobals) { NS_ASSERTION(mUnrootedGlobalCount != 0, "bad state"); NS_ASSERTION(trc == acx->runtime->gcMarkingTracer, "bad tracer"); JS_ToggleOptions(acx, JSOPTION_UNROOTED_GLOBAL); --mUnrootedGlobalCount; } } } } XPCWrappedNativeScope::TraceJS(trc, this); for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) static_cast<XPCTraceableVariant*>(e)->TraceJS(trc); for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc); if(mJSHolders.ops) JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc); }
static void check_context_valid(Closure *c) { JSContext *a_context; JSContext *iter; if (c->runtime == NULL) return; iter = NULL; while ((a_context = JS_ContextIterator(c->runtime, &iter)) != NULL) { if (a_context == c->context) { return; } } gjs_debug_closure("Context %p no longer exists, invalidating " "closure %p which calls object %p", c->context, c, c->obj); /* Did not find the context. */ invalidate_js_pointers(c); }
XPCJSRuntime::~XPCJSRuntime() { #ifdef XPC_DUMP_AT_SHUTDOWN { // count the total JSContexts in use JSContext* iter = nsnull; int count = 0; while(JS_ContextIterator(mJSRuntime, &iter)) count ++; if(count) printf("deleting XPCJSRuntime with %d live JSContexts\n", count); } #endif // clean up and destroy maps... if(mContextMap) { PurgeXPCContextList(); delete mContextMap; } if(mWrappedJSMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mWrappedJSMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live wrapped JSObject\n", (int)count); #endif mWrappedJSMap->Enumerate(WrappedJSShutdownMarker, mJSRuntime); delete mWrappedJSMap; } if(mWrappedJSClassMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mWrappedJSClassMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live nsXPCWrappedJSClass\n", (int)count); #endif delete mWrappedJSClassMap; } if(mIID2NativeInterfaceMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mIID2NativeInterfaceMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live XPCNativeInterfaces\n", (int)count); #endif delete mIID2NativeInterfaceMap; } if(mClassInfo2NativeSetMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mClassInfo2NativeSetMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live XPCNativeSets\n", (int)count); #endif delete mClassInfo2NativeSetMap; } if(mNativeSetMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mNativeSetMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live XPCNativeSets\n", (int)count); #endif delete mNativeSetMap; } if(mMapLock) XPCAutoLock::DestroyLock(mMapLock); NS_IF_RELEASE(mJSRuntimeService); if(mThisTranslatorMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mThisTranslatorMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live ThisTranslator\n", (int)count); #endif delete mThisTranslatorMap; } #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN if(DEBUG_WrappedNativeHashtable) { int LiveWrapperCount = 0; JS_DHashTableEnumerate(DEBUG_WrappedNativeHashtable, DEBUG_WrapperChecker, &LiveWrapperCount); if(LiveWrapperCount) printf("deleting XPCJSRuntime with %d live XPCWrappedNative (found in wrapper check)\n", (int)LiveWrapperCount); JS_DHashTableDestroy(DEBUG_WrappedNativeHashtable); } #endif if(mNativeScriptableSharedMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mNativeScriptableSharedMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live XPCNativeScriptableShared\n", (int)count); #endif delete mNativeScriptableSharedMap; } if(mDyingWrappedNativeProtoMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mDyingWrappedNativeProtoMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live but dying XPCWrappedNativeProto\n", (int)count); #endif delete mDyingWrappedNativeProtoMap; } if(mDetachedWrappedNativeProtoMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mDetachedWrappedNativeProtoMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live detached XPCWrappedNativeProto\n", (int)count); #endif delete mDetachedWrappedNativeProtoMap; } if(mExplicitNativeWrapperMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mExplicitNativeWrapperMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live explicit XPCNativeWrapper\n", (int)count); #endif delete mExplicitNativeWrapperMap; } // unwire the readable/JSString sharing magic XPCStringConvert::ShutdownDOMStringFinalizer(); XPCConvert::RemoveXPCOMUCStringFinalizer(); gOldJSGCCallback = NULL; gOldJSContextCallback = NULL; if(mJSHolders.ops) { JS_DHashTableFinish(&mJSHolders); mJSHolders.ops = nsnull; } if(mClearedGlobalObjects.ops) { JS_DHashTableFinish(&mClearedGlobalObjects); mClearedGlobalObjects.ops = nsnull; } }
// static JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status) { XPCJSRuntime* self = nsXPConnect::GetRuntimeInstance(); if(self) { switch(status) { case JSGC_BEGIN: { if(!NS_IsMainThread()) { return JS_FALSE; } // We seem to sometime lose the unrooted global flag. Restore it // here. FIXME: bug 584495. JSContext *iter = nsnull, *acx; while((acx = JS_ContextIterator(cx->runtime, &iter))) { if (!JS_HAS_OPTION(acx, JSOPTION_UNROOTED_GLOBAL)) JS_ToggleOptions(acx, JSOPTION_UNROOTED_GLOBAL); } break; } case JSGC_MARK_END: { NS_ASSERTION(!self->mDoingFinalization, "bad state"); // mThreadRunningGC indicates that GC is running { // scoped lock XPCAutoLock lock(self->GetMapLock()); NS_ASSERTION(!self->mThreadRunningGC, "bad state"); self->mThreadRunningGC = PR_GetCurrentThread(); } nsTArray<nsXPCWrappedJS*>* dyingWrappedJSArray = &self->mWrappedJSToReleaseArray; { JSDyingJSObjectData data = {cx, dyingWrappedJSArray}; // Add any wrappers whose JSObjects are to be finalized to // this array. Note that we do not want to be changing the // refcount of these wrappers. // We add them to the array now and Release the array members // later to avoid the posibility of doing any JS GCThing // allocations during the gc cycle. self->mWrappedJSMap-> Enumerate(WrappedJSDyingJSObjectFinder, &data); } // Do cleanup in NativeInterfaces. This part just finds // member cloned function objects that are about to be // collected. It does not deal with collection of interfaces or // sets at this point. CX_AND_XPCRT_Data data = {cx, self}; self->mIID2NativeInterfaceMap-> Enumerate(NativeInterfaceGC, &data); // Find dying scopes... XPCWrappedNativeScope::FinishedMarkPhaseOfGC(cx, self); self->mDoingFinalization = JS_TRUE; break; } case JSGC_FINALIZE_END: { NS_ASSERTION(self->mDoingFinalization, "bad state"); self->mDoingFinalization = JS_FALSE; // Release all the members whose JSObjects are now known // to be dead. DoDeferredRelease(self->mWrappedJSToReleaseArray); #ifdef XPC_REPORT_NATIVE_INTERFACE_AND_SET_FLUSHING printf("--------------------------------------------------------------\n"); int setsBefore = (int) self->mNativeSetMap->Count(); int ifacesBefore = (int) self->mIID2NativeInterfaceMap->Count(); #endif // We use this occasion to mark and sweep NativeInterfaces, // NativeSets, and the WrappedNativeJSClasses... // Do the marking... XPCWrappedNativeScope::MarkAllWrappedNativesAndProtos(); self->mDetachedWrappedNativeProtoMap-> Enumerate(DetachedWrappedNativeProtoMarker, nsnull); DOM_MarkInterfaces(); // Mark the sets used in the call contexts. There is a small // chance that a wrapper's set will change *while* a call is // happening which uses that wrapper's old interfface set. So, // we need to do this marking to avoid collecting those sets // that might no longer be otherwise reachable from the wrappers // or the wrapperprotos. // Skip this part if XPConnect is shutting down. We get into // bad locking problems with the thread iteration otherwise. if(!self->GetXPConnect()->IsShuttingDown()) { PRLock* threadLock = XPCPerThreadData::GetLock(); if(threadLock) { // scoped lock nsAutoLock lock(threadLock); XPCPerThreadData* iterp = nsnull; XPCPerThreadData* thread; while(nsnull != (thread = XPCPerThreadData::IterateThreads(&iterp))) { // Mark those AutoMarkingPtr lists! thread->MarkAutoRootsAfterJSFinalize(); XPCCallContext* ccxp = thread->GetCallContext(); while(ccxp) { // Deal with the strictness of callcontext that // complains if you ask for a set when // it is in a state where the set could not // possibly be valid. if(ccxp->CanGetSet()) { XPCNativeSet* set = ccxp->GetSet(); if(set) set->Mark(); } if(ccxp->CanGetInterface()) { XPCNativeInterface* iface = ccxp->GetInterface(); if(iface) iface->Mark(); } ccxp = ccxp->GetPrevCallContext(); } } } } // Do the sweeping... // We don't want to sweep the JSClasses at shutdown time. // At this point there may be JSObjects using them that have // been removed from the other maps. if(!self->GetXPConnect()->IsShuttingDown()) { self->mNativeScriptableSharedMap-> Enumerate(JSClassSweeper, nsnull); } self->mClassInfo2NativeSetMap-> Enumerate(NativeUnMarkedSetRemover, nsnull); self->mNativeSetMap-> Enumerate(NativeSetSweeper, nsnull); self->mIID2NativeInterfaceMap-> Enumerate(NativeInterfaceSweeper, nsnull); #ifdef DEBUG XPCWrappedNativeScope::ASSERT_NoInterfaceSetsAreMarked(); #endif #ifdef XPC_REPORT_NATIVE_INTERFACE_AND_SET_FLUSHING int setsAfter = (int) self->mNativeSetMap->Count(); int ifacesAfter = (int) self->mIID2NativeInterfaceMap->Count(); printf("\n"); printf("XPCNativeSets: before: %d collected: %d remaining: %d\n", setsBefore, setsBefore - setsAfter, setsAfter); printf("XPCNativeInterfaces: before: %d collected: %d remaining: %d\n", ifacesBefore, ifacesBefore - ifacesAfter, ifacesAfter); printf("--------------------------------------------------------------\n"); #endif // Sweep scopes needing cleanup XPCWrappedNativeScope::FinishedFinalizationPhaseOfGC(cx); // Now we are going to recycle any unused WrappedNativeTearoffs. // We do this by iterating all the live callcontexts (on all // threads!) and marking the tearoffs in use. And then we // iterate over all the WrappedNative wrappers and sweep their // tearoffs. // // This allows us to perhaps minimize the growth of the // tearoffs. And also makes us not hold references to interfaces // on our wrapped natives that we are not actually using. // // XXX We may decide to not do this on *every* gc cycle. // Skip this part if XPConnect is shutting down. We get into // bad locking problems with the thread iteration otherwise. if(!self->GetXPConnect()->IsShuttingDown()) { PRLock* threadLock = XPCPerThreadData::GetLock(); if(threadLock) { // Do the marking... { // scoped lock nsAutoLock lock(threadLock); XPCPerThreadData* iterp = nsnull; XPCPerThreadData* thread; while(nsnull != (thread = XPCPerThreadData::IterateThreads(&iterp))) { XPCCallContext* ccxp = thread->GetCallContext(); while(ccxp) { // Deal with the strictness of callcontext that // complains if you ask for a tearoff when // it is in a state where the tearoff could not // possibly be valid. if(ccxp->CanGetTearOff()) { XPCWrappedNativeTearOff* to = ccxp->GetTearOff(); if(to) to->Mark(); } ccxp = ccxp->GetPrevCallContext(); } } } // Do the sweeping... XPCWrappedNativeScope::SweepAllWrappedNativeTearOffs(); } } // Now we need to kill the 'Dying' XPCWrappedNativeProtos. // We transfered these native objects to this table when their // JSObject's were finalized. We did not destroy them immediately // at that point because the ordering of JS finalization is not // deterministic and we did not yet know if any wrappers that // might still be referencing the protos where still yet to be // finalized and destroyed. We *do* know that the protos' // JSObjects would not have been finalized if there were any // wrappers that referenced the proto but where not themselves // slated for finalization in this gc cycle. So... at this point // we know that any and all wrappers that might have been // referencing the protos in the dying list are themselves dead. // So, we can safely delete all the protos in the list. self->mDyingWrappedNativeProtoMap-> Enumerate(DyingProtoKiller, nsnull); // mThreadRunningGC indicates that GC is running. // Clear it and notify waiters. { // scoped lock XPCAutoLock lock(self->GetMapLock()); NS_ASSERTION(self->mThreadRunningGC == PR_GetCurrentThread(), "bad state"); self->mThreadRunningGC = nsnull; xpc_NotifyAll(self->GetMapLock()); } break; } case JSGC_END: { // NOTE that this event happens outside of the gc lock in // the js engine. So this could be simultaneous with the // events above. // Do any deferred released of native objects. #ifdef XPC_TRACK_DEFERRED_RELEASES printf("XPC - Begin deferred Release of %d nsISupports pointers\n", self->mNativesToReleaseArray.Length()); #endif DoDeferredRelease(self->mNativesToReleaseArray); #ifdef XPC_TRACK_DEFERRED_RELEASES printf("XPC - End deferred Releases\n"); #endif break; } default: break; } } nsTArray<JSGCCallback> callbacks(self->extraGCCallbacks); for (PRUint32 i = 0; i < callbacks.Length(); ++i) { if (!callbacks[i](cx, status)) return JS_FALSE; } return JS_TRUE; }
void XPCJSRuntime::DebugDump(PRInt16 depth) { #ifdef DEBUG depth--; XPC_LOG_ALWAYS(("XPCJSRuntime @ %x", this)); XPC_LOG_INDENT(); XPC_LOG_ALWAYS(("mXPConnect @ %x", mXPConnect)); XPC_LOG_ALWAYS(("mJSRuntime @ %x", mJSRuntime)); XPC_LOG_ALWAYS(("mMapLock @ %x", mMapLock)); XPC_LOG_ALWAYS(("mWrappedJSToReleaseArray @ %x with %d wrappers(s)", \ &mWrappedJSToReleaseArray, mWrappedJSToReleaseArray.Length())); int cxCount = 0; JSContext* iter = nsnull; while(JS_ContextIterator(mJSRuntime, &iter)) ++cxCount; XPC_LOG_ALWAYS(("%d JS context(s)", cxCount)); iter = nsnull; while(JS_ContextIterator(mJSRuntime, &iter)) { XPCContext *xpc = XPCContext::GetXPCContext(iter); XPC_LOG_INDENT(); xpc->DebugDump(depth); XPC_LOG_OUTDENT(); } XPC_LOG_ALWAYS(("mWrappedJSClassMap @ %x with %d wrapperclasses(s)", \ mWrappedJSClassMap, mWrappedJSClassMap ? \ mWrappedJSClassMap->Count() : 0)); // iterate wrappersclasses... if(depth && mWrappedJSClassMap && mWrappedJSClassMap->Count()) { XPC_LOG_INDENT(); mWrappedJSClassMap->Enumerate(WrappedJSClassMapDumpEnumerator, &depth); XPC_LOG_OUTDENT(); } XPC_LOG_ALWAYS(("mWrappedJSMap @ %x with %d wrappers(s)", \ mWrappedJSMap, mWrappedJSMap ? \ mWrappedJSMap->Count() : 0)); // iterate wrappers... if(depth && mWrappedJSMap && mWrappedJSMap->Count()) { XPC_LOG_INDENT(); mWrappedJSMap->Enumerate(WrappedJSMapDumpEnumerator, &depth); XPC_LOG_OUTDENT(); } XPC_LOG_ALWAYS(("mIID2NativeInterfaceMap @ %x with %d interface(s)", \ mIID2NativeInterfaceMap, mIID2NativeInterfaceMap ? \ mIID2NativeInterfaceMap->Count() : 0)); XPC_LOG_ALWAYS(("mClassInfo2NativeSetMap @ %x with %d sets(s)", \ mClassInfo2NativeSetMap, mClassInfo2NativeSetMap ? \ mClassInfo2NativeSetMap->Count() : 0)); XPC_LOG_ALWAYS(("mThisTranslatorMap @ %x with %d translator(s)", \ mThisTranslatorMap, mThisTranslatorMap ? \ mThisTranslatorMap->Count() : 0)); XPC_LOG_ALWAYS(("mNativeSetMap @ %x with %d sets(s)", \ mNativeSetMap, mNativeSetMap ? \ mNativeSetMap->Count() : 0)); // iterate sets... if(depth && mNativeSetMap && mNativeSetMap->Count()) { XPC_LOG_INDENT(); mNativeSetMap->Enumerate(NativeSetDumpEnumerator, &depth); XPC_LOG_OUTDENT(); } XPC_LOG_OUTDENT(); #endif }
XPCJSRuntime::~XPCJSRuntime() { if (mWatchdogWakeup) { // If the watchdog thread is running, tell it to terminate waking it // up if necessary and wait until it signals that it finished. As we // must release the lock before calling PR_DestroyCondVar, we use an // extra block here. { AutoLockJSGC lock(mJSRuntime); if (mWatchdogThread) { mWatchdogThread = nsnull; PR_NotifyCondVar(mWatchdogWakeup); PR_WaitCondVar(mWatchdogWakeup, PR_INTERVAL_NO_TIMEOUT); } } PR_DestroyCondVar(mWatchdogWakeup); mWatchdogWakeup = nsnull; } #ifdef XPC_DUMP_AT_SHUTDOWN { // count the total JSContexts in use JSContext* iter = nsnull; int count = 0; while(JS_ContextIterator(mJSRuntime, &iter)) count ++; if(count) printf("deleting XPCJSRuntime with %d live JSContexts\n", count); } #endif // clean up and destroy maps... if(mWrappedJSMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mWrappedJSMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live wrapped JSObject\n", (int)count); #endif mWrappedJSMap->Enumerate(WrappedJSShutdownMarker, mJSRuntime); delete mWrappedJSMap; } if(mWrappedJSClassMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mWrappedJSClassMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live nsXPCWrappedJSClass\n", (int)count); #endif delete mWrappedJSClassMap; } if(mIID2NativeInterfaceMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mIID2NativeInterfaceMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live XPCNativeInterfaces\n", (int)count); #endif delete mIID2NativeInterfaceMap; } if(mClassInfo2NativeSetMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mClassInfo2NativeSetMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live XPCNativeSets\n", (int)count); #endif delete mClassInfo2NativeSetMap; } if(mNativeSetMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mNativeSetMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live XPCNativeSets\n", (int)count); #endif delete mNativeSetMap; } if(mMapLock) XPCAutoLock::DestroyLock(mMapLock); if(mThisTranslatorMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mThisTranslatorMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live ThisTranslator\n", (int)count); #endif delete mThisTranslatorMap; } #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN if(DEBUG_WrappedNativeHashtable) { int LiveWrapperCount = 0; JS_DHashTableEnumerate(DEBUG_WrappedNativeHashtable, DEBUG_WrapperChecker, &LiveWrapperCount); if(LiveWrapperCount) printf("deleting XPCJSRuntime with %d live XPCWrappedNative (found in wrapper check)\n", (int)LiveWrapperCount); JS_DHashTableDestroy(DEBUG_WrappedNativeHashtable); } #endif if(mNativeScriptableSharedMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mNativeScriptableSharedMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live XPCNativeScriptableShared\n", (int)count); #endif delete mNativeScriptableSharedMap; } if(mDyingWrappedNativeProtoMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mDyingWrappedNativeProtoMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live but dying XPCWrappedNativeProto\n", (int)count); #endif delete mDyingWrappedNativeProtoMap; } if(mDetachedWrappedNativeProtoMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mDetachedWrappedNativeProtoMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live detached XPCWrappedNativeProto\n", (int)count); #endif delete mDetachedWrappedNativeProtoMap; } if(mExplicitNativeWrapperMap) { #ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mExplicitNativeWrapperMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live explicit XPCNativeWrapper\n", (int)count); #endif delete mExplicitNativeWrapperMap; } // unwire the readable/JSString sharing magic XPCStringConvert::ShutdownDOMStringFinalizer(); XPCConvert::RemoveXPCOMUCStringFinalizer(); if(mJSHolders.ops) { JS_DHashTableFinish(&mJSHolders); mJSHolders.ops = nsnull; } if(mJSRuntime) { JS_DestroyRuntime(mJSRuntime); JS_ShutDown(); #ifdef DEBUG_shaver_off fprintf(stderr, "nJRSI: destroyed runtime %p\n", (void *)mJSRuntime); #endif } XPCPerThreadData::ShutDown(); }