michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_CycleCollectedJSRuntime_h__ michael@0: #define mozilla_CycleCollectedJSRuntime_h__ michael@0: michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "jsapi.h" michael@0: michael@0: #include "nsCycleCollector.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "nsDataHashtable.h" michael@0: #include "nsHashKeys.h" michael@0: #include "nsTArray.h" michael@0: michael@0: class nsCycleCollectionNoteRootCallback; michael@0: class nsIException; michael@0: michael@0: namespace js { michael@0: class Class; michael@0: } michael@0: michael@0: namespace mozilla { michael@0: michael@0: class JSGCThingParticipant: public nsCycleCollectionParticipant michael@0: { michael@0: public: michael@0: NS_IMETHOD_(void) Root(void *n) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD_(void) Unlink(void *n) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD_(void) Unroot(void *n) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD_(void) DeleteCycleCollectable(void *n) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD Traverse(void *n, nsCycleCollectionTraversalCallback &cb); michael@0: }; michael@0: michael@0: class JSZoneParticipant : public nsCycleCollectionParticipant michael@0: { michael@0: public: michael@0: MOZ_CONSTEXPR JSZoneParticipant(): nsCycleCollectionParticipant() {} michael@0: michael@0: NS_IMETHOD_(void) Root(void *p) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD_(void) Unlink(void *p) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD_(void) Unroot(void *p) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD_(void) DeleteCycleCollectable(void *n) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb); michael@0: }; michael@0: michael@0: class IncrementalFinalizeRunnable; michael@0: michael@0: // Contains various stats about the cycle collection. michael@0: struct CycleCollectorResults michael@0: { michael@0: void Init() michael@0: { michael@0: mForcedGC = false; michael@0: mMergedZones = false; michael@0: mVisitedRefCounted = 0; michael@0: mVisitedGCed = 0; michael@0: mFreedRefCounted = 0; michael@0: mFreedGCed = 0; michael@0: } michael@0: michael@0: bool mForcedGC; michael@0: bool mMergedZones; michael@0: uint32_t mVisitedRefCounted; michael@0: uint32_t mVisitedGCed; michael@0: uint32_t mFreedRefCounted; michael@0: uint32_t mFreedGCed; michael@0: }; michael@0: michael@0: class CycleCollectedJSRuntime michael@0: { michael@0: friend class JSGCThingParticipant; michael@0: friend class JSZoneParticipant; michael@0: friend class IncrementalFinalizeRunnable; michael@0: protected: michael@0: CycleCollectedJSRuntime(JSRuntime* aParentRuntime, michael@0: uint32_t aMaxbytes, michael@0: JSUseHelperThreads aUseHelperThreads); michael@0: virtual ~CycleCollectedJSRuntime(); michael@0: michael@0: size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; michael@0: void UnmarkSkippableJSHolders(); michael@0: michael@0: virtual void TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& aCb) {} michael@0: virtual void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) {} michael@0: michael@0: virtual void CustomGCCallback(JSGCStatus aStatus) {} michael@0: virtual bool CustomContextCallback(JSContext* aCx, unsigned aOperation) michael@0: { michael@0: return true; // Don't block context creation. michael@0: } michael@0: michael@0: private: michael@0: michael@0: void michael@0: DescribeGCThing(bool aIsMarked, void* aThing, JSGCTraceKind aTraceKind, michael@0: nsCycleCollectionTraversalCallback& aCb) const; michael@0: michael@0: virtual bool michael@0: DescribeCustomObjects(JSObject* aObject, const js::Class* aClasp, michael@0: char (&aName)[72]) const michael@0: { michael@0: return false; // We did nothing. michael@0: } michael@0: michael@0: void michael@0: NoteGCThingJSChildren(void* aThing, JSGCTraceKind aTraceKind, michael@0: nsCycleCollectionTraversalCallback& aCb) const; michael@0: michael@0: void michael@0: NoteGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj, michael@0: nsCycleCollectionTraversalCallback& aCb) const; michael@0: michael@0: virtual bool michael@0: NoteCustomGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj, michael@0: nsCycleCollectionTraversalCallback& aCb) const michael@0: { michael@0: return false; // We did nothing. michael@0: } michael@0: michael@0: enum TraverseSelect { michael@0: TRAVERSE_CPP, michael@0: TRAVERSE_FULL michael@0: }; michael@0: michael@0: void michael@0: TraverseGCThing(TraverseSelect aTs, void* aThing, michael@0: JSGCTraceKind aTraceKind, michael@0: nsCycleCollectionTraversalCallback& aCb); michael@0: michael@0: void michael@0: TraverseZone(JS::Zone* aZone, nsCycleCollectionTraversalCallback& aCb); michael@0: michael@0: static void michael@0: TraverseObjectShim(void* aData, void* aThing); michael@0: michael@0: void TraverseNativeRoots(nsCycleCollectionNoteRootCallback& aCb); michael@0: michael@0: static void TraceBlackJS(JSTracer* aTracer, void* aData); michael@0: static void TraceGrayJS(JSTracer* aTracer, void* aData); michael@0: static void GCCallback(JSRuntime* aRuntime, JSGCStatus aStatus, void* aData); michael@0: static bool ContextCallback(JSContext* aCx, unsigned aOperation, michael@0: void* aData); michael@0: michael@0: virtual void TraceNativeBlackRoots(JSTracer* aTracer) { }; michael@0: void TraceNativeGrayRoots(JSTracer* aTracer); michael@0: michael@0: enum DeferredFinalizeType { michael@0: FinalizeIncrementally, michael@0: FinalizeNow, michael@0: }; michael@0: michael@0: void FinalizeDeferredThings(DeferredFinalizeType aType); michael@0: michael@0: void OnGC(JSGCStatus aStatus); michael@0: michael@0: public: michael@0: void AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer); michael@0: void RemoveJSHolder(void* aHolder); michael@0: #ifdef DEBUG michael@0: bool IsJSHolder(void* aHolder); michael@0: void AssertNoObjectsToTrace(void* aPossibleJSHolder); michael@0: #endif michael@0: michael@0: already_AddRefed GetPendingException() const; michael@0: void SetPendingException(nsIException* aException); michael@0: michael@0: nsCycleCollectionParticipant* GCThingParticipant(); michael@0: nsCycleCollectionParticipant* ZoneParticipant(); michael@0: michael@0: nsresult TraverseRoots(nsCycleCollectionNoteRootCallback &aCb); michael@0: bool UsefulToMergeZones() const; michael@0: void FixWeakMappingGrayBits() const; michael@0: bool NeedCollect() const; michael@0: void Collect(uint32_t reason) const; michael@0: michael@0: void DeferredFinalize(DeferredFinalizeAppendFunction aAppendFunc, michael@0: DeferredFinalizeFunction aFunc, michael@0: void* aThing); michael@0: void DeferredFinalize(nsISupports* aSupports); michael@0: michael@0: void DumpJSHeap(FILE* aFile); michael@0: michael@0: virtual void PrepareForForgetSkippable() = 0; michael@0: virtual void BeginCycleCollectionCallback() = 0; michael@0: virtual void EndCycleCollectionCallback(CycleCollectorResults &aResults) = 0; michael@0: virtual void DispatchDeferredDeletion(bool aContinuation) = 0; michael@0: michael@0: JSRuntime* Runtime() const michael@0: { michael@0: MOZ_ASSERT(mJSRuntime); michael@0: return mJSRuntime; michael@0: } michael@0: michael@0: // Get the current thread's CycleCollectedJSRuntime. Returns null if there michael@0: // isn't one. michael@0: static CycleCollectedJSRuntime* Get(); michael@0: michael@0: private: michael@0: JSGCThingParticipant mGCThingCycleCollectorGlobal; michael@0: michael@0: JSZoneParticipant mJSZoneCycleCollectorGlobal; michael@0: michael@0: JSRuntime* mJSRuntime; michael@0: michael@0: nsDataHashtable, nsScriptObjectTracer*> mJSHolders; michael@0: michael@0: nsTArray mDeferredSupports; michael@0: typedef nsDataHashtable, void*> michael@0: DeferredFinalizerTable; michael@0: DeferredFinalizerTable mDeferredFinalizerTable; michael@0: michael@0: nsRefPtr mFinalizeRunnable; michael@0: michael@0: nsCOMPtr mPendingException; michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_CycleCollectedJSRuntime_h__