author | Kyle Huey <khuey@kylehuey.com> |
Sat, 03 Aug 2013 16:55:39 -0700 | |
changeset 153596 | d18e1e6db0dcc133fa155e991347d73ac22eb9df |
parent 153595 | b7dbdc2a38f9679122cc299ee84713fac521a341 |
child 153597 | 688333343bdd7891c53376816ef7ca231d12e65d |
push id | 2859 |
push user | akeybl@mozilla.com |
push date | Mon, 16 Sep 2013 19:14:59 +0000 |
treeherder | mozilla-beta@87d3c51cd2bf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 845545 |
milestone | 25.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -217,16 +217,53 @@ XPCJSRuntime::CustomContextCallback(JSCo if (!callbacks[i](cx, operation)) { return false; } } return true; } +class AsyncFreeSnowWhite : public nsRunnable +{ +public: + NS_IMETHOD Run() + { + TimeStamp start = TimeStamp::Now(); + bool hadSnowWhiteObjects = nsCycleCollector_doDeferredDeletion(); + Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING, + uint32_t((TimeStamp::Now() - start).ToMilliseconds())); + if (hadSnowWhiteObjects && !mContinuation) { + mContinuation = true; + if (NS_FAILED(NS_DispatchToCurrentThread(this))) { + mActive = false; + } + } else { + mActive = false; + } + return NS_OK; + } + + void Dispatch(bool aContinuation = false) + { + if (mContinuation) { + mContinuation = aContinuation; + } + if (!mActive && NS_SUCCEEDED(NS_DispatchToCurrentThread(this))) { + mActive = true; + } + } + + AsyncFreeSnowWhite() : mContinuation(false), mActive(false) {} + +public: + bool mContinuation; + bool mActive; +}; + namespace xpc { CompartmentPrivate::~CompartmentPrivate() { MOZ_COUNT_DTOR(xpc::CompartmentPrivate); } bool CompartmentPrivate::TryParseLocationURI() @@ -562,16 +599,22 @@ XPCJSRuntime::PrepareForCollection() { nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->NotifyObservers(nullptr, "cycle-collector-begin", nullptr); } } void +XPCJSRuntime::DispatchDeferredDeletion(bool aContinuation) +{ + mAsyncSnowWhiteFreer->Dispatch(aContinuation); +} + +void xpc_UnmarkSkippableJSHolders() { if (nsXPConnect::XPConnect()->GetRuntime()) { nsXPConnect::XPConnect()->GetRuntime()->UnmarkSkippableJSHolders(); } } template<class T> static void @@ -2693,16 +2736,17 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* mWrappedJSToReleaseArray(), mNativesToReleaseArray(), mDoingFinalization(false), mVariantRoots(nullptr), mWrappedJSRoots(nullptr), mObjectHolderRoots(nullptr), mWatchdogManager(new WatchdogManager(this)), mJunkScope(nullptr), + mAsyncSnowWhiteFreer(new AsyncFreeSnowWhite()), mExceptionManagerNotAvailable(false) { #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN DEBUG_WrappedNativeHashtable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, sizeof(PLDHashEntryStub), 128); #endif
--- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -602,16 +602,18 @@ enum WatchdogTimestampCategory { TimestampRuntimeStateChange = 0, TimestampWatchdogWakeup, TimestampWatchdogHibernateStart, TimestampWatchdogHibernateStop, TimestampCount }; +class AsyncFreeSnowWhite; + class XPCJSRuntime : public mozilla::CycleCollectedJSRuntime { public: static XPCJSRuntime* newXPCJSRuntime(nsXPConnect* aXPConnect); static XPCJSRuntime* Get() { return nsXPConnect::XPConnect()->GetRuntime(); } // Make this public for now. Ideally we'd hide the JSRuntime inside. JSRuntime* Runtime() const @@ -724,16 +726,17 @@ public: } void TraceNativeBlackRoots(JSTracer* trc); void TraceAdditionalNativeGrayRoots(JSTracer* aTracer); void TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& cb); void UnmarkSkippableJSHolders(); void PrepareForForgetSkippable() MOZ_OVERRIDE; void PrepareForCollection() MOZ_OVERRIDE; + void DispatchDeferredDeletion(bool continuation) MOZ_OVERRIDE; void CustomGCCallback(JSGCStatus status) MOZ_OVERRIDE; bool CustomContextCallback(JSContext *cx, unsigned operation) MOZ_OVERRIDE; static void GCSliceCallback(JSRuntime *rt, JS::GCProgress progress, const JS::GCDescription &desc); static void FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, JSBool isCompartmentGC); @@ -866,16 +869,17 @@ private: XPCRootSetElem *mVariantRoots; XPCRootSetElem *mWrappedJSRoots; XPCRootSetElem *mObjectHolderRoots; nsTArray<xpcGCCallback> extraGCCallbacks; nsTArray<xpcContextCallback> extraContextCallbacks; nsRefPtr<WatchdogManager> mWatchdogManager; JS::GCSliceCallback mPrevGCSliceCallback; JSObject* mJunkScope; + nsRefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer; nsCOMPtr<nsIException> mPendingException; nsCOMPtr<nsIExceptionManager> mExceptionManager; bool mExceptionManagerNotAvailable; #define XPCCCX_STRING_CACHE_SIZE 2 // String wrapper entry, holds a string, and a boolean that tells
--- a/xpcom/base/CycleCollectedJSRuntime.h +++ b/xpcom/base/CycleCollectedJSRuntime.h @@ -199,16 +199,18 @@ public: virtual void PrepareForCollection() {} void DeferredFinalize(DeferredFinalizeAppendFunction aAppendFunc, DeferredFinalizeFunction aFunc, void* aThing); void DeferredFinalize(nsISupports* aSupports); void DumpJSHeap(FILE* aFile); + + virtual void DispatchDeferredDeletion(bool aContinuation) = 0; private: JSGCThingParticipant mGCThingCycleCollectorGlobal; JSZoneParticipant mJSZoneCycleCollectorGlobal; JSRuntime* mJSRuntime;
--- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -996,18 +996,16 @@ class nsCycleCollector // Strong reference nsCycleCollectorRunner *mRunner; PRThread* mThread; public: nsCycleCollectorParams mParams; private: - nsRefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer; - nsTArray<PtrInfo*> *mWhiteNodes; uint32_t mWhiteNodeCount; // mVisitedRefCounted and mVisitedGCed are only used for telemetry uint32_t mVisitedRefCounted; uint32_t mVisitedGCed; CC_BeforeUnlinkCallback mBeforeUnlinkCB; @@ -1075,28 +1073,18 @@ public: void FixGrayBits(bool aForceGC); bool ShouldMergeZones(ccType aCCType); void CleanupAfterCollection(); // Start and finish an individual collection. bool BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener); bool FinishCollection(nsICycleCollectorListener *aListener); - AsyncFreeSnowWhite* AsyncSnowWhiteFreer() - { - return mAsyncSnowWhiteFreer; - } - bool FreeSnowWhite(bool aUntilNoSWInPurpleBuffer); - // If there is a cycle collector available in the current thread, - // this calls FreeSnowWhite(false). Returns true if some - // snow-white objects were found. - static bool TryToFreeSnowWhite(); - uint32_t SuspectedCount(); void Shutdown(); void ClearGraph() { mGraph.mNodes.Clear(); mGraph.mEdges.Clear(); mGraph.mWeakMaps.Clear(); @@ -2178,54 +2166,16 @@ ChildFinder::NoteJSChild(void *child) static bool MayHaveChild(void *o, nsCycleCollectionParticipant* cp) { ChildFinder cf; cp->Traverse(o, cf); return cf.MayHaveChild(); } -class AsyncFreeSnowWhite : public nsRunnable -{ -public: - NS_IMETHOD Run() - { - TimeStamp start = TimeStamp::Now(); - bool hadSnowWhiteObjects = nsCycleCollector::TryToFreeSnowWhite(); - Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING, - uint32_t((TimeStamp::Now() - start).ToMilliseconds())); - if (hadSnowWhiteObjects && !mContinuation) { - mContinuation = true; - if (NS_FAILED(NS_DispatchToCurrentThread(this))) { - mActive = false; - } - } else { - mActive = false; - } - return NS_OK; - } - - static void Dispatch(nsCycleCollector* aCollector, bool aContinuation = false) - { - AsyncFreeSnowWhite* swf = aCollector->AsyncSnowWhiteFreer(); - if (swf->mContinuation) { - swf->mContinuation = aContinuation; - } - if (!swf->mActive && NS_SUCCEEDED(NS_DispatchToCurrentThread(swf))) { - swf->mActive = true; - } - } - - AsyncFreeSnowWhite() : mContinuation(false), mActive(false) {} - -public: - bool mContinuation; - bool mActive; -}; - struct SnowWhiteObject { void* mPointer; nsCycleCollectionParticipant* mParticipant; nsCycleCollectingAutoRefCnt* mRefCnt; }; class SnowWhiteKiller @@ -2297,30 +2247,30 @@ public: { // Note, we must call the callback before SnowWhiteKiller calls // DeleteCycleCollectable! if (mCallback) { mCallback(); } if (HasSnowWhiteObjects()) { // Effectively a continuation. - AsyncFreeSnowWhite::Dispatch(mCollector, true); + nsCycleCollector_dispatchDeferredDeletion(true); } } void Visit(nsPurpleBuffer &aBuffer, nsPurpleBufferEntry *aEntry) { MOZ_ASSERT(aEntry->mObject, "null mObject in purple buffer"); if (!aEntry->mRefCnt->get()) { if (!mAsyncSnowWhiteFreeing) { SnowWhiteKiller::Visit(aBuffer, aEntry); } else if (!mDispatchedDeferredDeletion) { mDispatchedDeferredDeletion = true; - nsCycleCollector_dispatchDeferredDeletion(); + nsCycleCollector_dispatchDeferredDeletion(false); } return; } void *o = aEntry->mObject; nsCycleCollectionParticipant *cp = aEntry->mParticipant; CanonicalizeParticipant(&o, &cp); if (aEntry->mRefCnt->IsPurple() && !cp->CanSkip(o, false) && (!mRemoveChildlessNodes || MayHaveChild(o, cp))) { @@ -2359,25 +2309,16 @@ nsCycleCollector::FreeSnowWhite(bool aUn visitor.HasSnowWhiteObjects(); if (!visitor.HasSnowWhiteObjects()) { break; } } while (aUntilNoSWInPurpleBuffer); return hadSnowWhiteObjects; } -/* static */ bool -nsCycleCollector::TryToFreeSnowWhite() -{ - CollectorData* data = sCollectorData.get(); - return data->mCollector ? - data->mCollector->FreeSnowWhite(false) : - false; -} - void nsCycleCollector::SelectPurple(GCGraphBuilder &builder) { mPurpleBuf.SelectPointers(builder); } void nsCycleCollector::ForgetSkippable(bool aRemoveChildlessNodes, @@ -2644,17 +2585,17 @@ nsCycleCollector::CollectWhite(nsICycleC for (uint32_t i = 0; i < count; ++i) { PtrInfo *pinfo = mWhiteNodes->ElementAt(i); rv = pinfo->mParticipant->Unroot(pinfo->mPointer); if (NS_FAILED(rv)) Fault("Failed unroot call while unlinking", pinfo); } timeLog.Checkpoint("CollectWhite::Unroot"); - nsCycleCollector_dispatchDeferredDeletion(); + nsCycleCollector_dispatchDeferredDeletion(false); return count > 0; } //////////////////////// // Memory reporter //////////////////////// @@ -2735,17 +2676,16 @@ NS_IMPL_ISUPPORTS1(CycleCollectorMultiRe nsCycleCollector::nsCycleCollector(CCThreadingModel aModel) : mCollectionInProgress(false), mScanInProgress(false), mResults(nullptr), mJSRuntime(nullptr), mRunner(nullptr), mThread(PR_GetCurrentThread()), - mAsyncSnowWhiteFreer(new AsyncFreeSnowWhite()), mWhiteNodes(nullptr), mWhiteNodeCount(0), mVisitedRefCounted(0), mVisitedGCed(0), mBeforeUnlinkCB(nullptr), mForgetSkippableCB(nullptr), mReporter(nullptr), mUnmergedNeeded(0), @@ -3374,22 +3314,38 @@ nsCycleCollector_forgetSkippable(bool aR PROFILER_LABEL("CC", "nsCycleCollector_forgetSkippable"); TimeLog timeLog; data->mCollector->ForgetSkippable(aRemoveChildlessNodes, aAsyncSnowWhiteFreeing); timeLog.Checkpoint("ForgetSkippable()"); } void -nsCycleCollector_dispatchDeferredDeletion() +nsCycleCollector_dispatchDeferredDeletion(bool aContinuation) { - CollectorData* data = sCollectorData.get(); - if (data && data->mCollector) { - AsyncFreeSnowWhite::Dispatch(data->mCollector); + CollectorData *data = sCollectorData.get(); + + if (!data || !data->mRuntime) { + return; } + + data->mRuntime->DispatchDeferredDeletion(aContinuation); +} + +bool +nsCycleCollector_doDeferredDeletion() +{ + CollectorData *data = sCollectorData.get(); + + // We should have started the cycle collector by now. + MOZ_ASSERT(data); + MOZ_ASSERT(data->mCollector); + MOZ_ASSERT(data->mRuntime); + + return data->mCollector->FreeSnowWhite(false); } void nsCycleCollector_collect(bool aManuallyTriggered, nsCycleCollectorResults *aResults, nsICycleCollectorListener *aListener) { CollectorData *data = sCollectorData.get();
--- a/xpcom/base/nsCycleCollector.h +++ b/xpcom/base/nsCycleCollector.h @@ -52,17 +52,18 @@ typedef void (*CC_BeforeUnlinkCallback)( void nsCycleCollector_setBeforeUnlinkCallback(CC_BeforeUnlinkCallback aCB); typedef void (*CC_ForgetSkippableCallback)(void); void nsCycleCollector_setForgetSkippableCallback(CC_ForgetSkippableCallback aCB); void nsCycleCollector_forgetSkippable(bool aRemoveChildlessNodes = false, bool aAsyncSnowWhiteFreeing = false); -void nsCycleCollector_dispatchDeferredDeletion(); +void nsCycleCollector_dispatchDeferredDeletion(bool aContinuation = false); +bool nsCycleCollector_doDeferredDeletion(); void nsCycleCollector_collect(bool aManuallyTriggered, nsCycleCollectorResults *aResults, nsICycleCollectorListener *aListener); uint32_t nsCycleCollector_suspectedCount(); void nsCycleCollector_shutdownThreads(); void nsCycleCollector_shutdown();