LCOV - code coverage report
Current view: top level - xpcom/base - CycleCollectedJSRuntime.h (source / functions) Hit Total Coverage
Test: output.info Lines: 12 41 29.3 %
Date: 2017-07-14 16:53:18 Functions: 7 24 29.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_CycleCollectedJSRuntime_h
       8             : #define mozilla_CycleCollectedJSRuntime_h
       9             : 
      10             : #include <queue>
      11             : 
      12             : #include "mozilla/CycleCollectedJSContext.h"
      13             : #include "mozilla/DeferredFinalize.h"
      14             : #include "mozilla/LinkedList.h"
      15             : #include "mozilla/mozalloc.h"
      16             : #include "mozilla/MemoryReporting.h"
      17             : #include "mozilla/SegmentedVector.h"
      18             : #include "jsapi.h"
      19             : #include "jsfriendapi.h"
      20             : 
      21             : #include "nsCycleCollectionParticipant.h"
      22             : #include "nsDataHashtable.h"
      23             : #include "nsHashKeys.h"
      24             : #include "nsTHashtable.h"
      25             : 
      26             : class nsCycleCollectionNoteRootCallback;
      27             : class nsIException;
      28             : class nsIRunnable;
      29             : class nsWrapperCache;
      30             : 
      31             : namespace js {
      32             : struct Class;
      33             : } // namespace js
      34             : 
      35             : namespace mozilla {
      36             : 
      37           4 : class JSGCThingParticipant: public nsCycleCollectionParticipant
      38             : {
      39             : public:
      40             :   constexpr JSGCThingParticipant()
      41             :     : nsCycleCollectionParticipant(false) {}
      42             : 
      43           0 :   NS_IMETHOD_(void) Root(void*) override
      44             :   {
      45           0 :     MOZ_ASSERT(false, "Don't call Root on GC things");
      46             :   }
      47             : 
      48           0 :   NS_IMETHOD_(void) Unlink(void*) override
      49             :   {
      50           0 :     MOZ_ASSERT(false, "Don't call Unlink on GC things, as they may be dead");
      51             :   }
      52             : 
      53           0 :   NS_IMETHOD_(void) Unroot(void*) override
      54             :   {
      55           0 :     MOZ_ASSERT(false, "Don't call Unroot on GC things, as they may be dead");
      56             :   }
      57             : 
      58           0 :   NS_IMETHOD_(void) DeleteCycleCollectable(void* aPtr) override
      59             :   {
      60           0 :     MOZ_ASSERT(false, "Can't directly delete a cycle collectable GC thing");
      61             :   }
      62             : 
      63             :   NS_IMETHOD TraverseNative(void* aPtr, nsCycleCollectionTraversalCallback& aCb)
      64             :     override;
      65             : 
      66           0 :   NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(JSGCThingParticipant)
      67             : };
      68             : 
      69           4 : class JSZoneParticipant : public nsCycleCollectionParticipant
      70             : {
      71             : public:
      72             :   constexpr JSZoneParticipant(): nsCycleCollectionParticipant(false)
      73             :   {
      74             :   }
      75             : 
      76           0 :   NS_IMETHOD_(void) Root(void*) override
      77             :   {
      78           0 :     MOZ_ASSERT(false, "Don't call Root on GC things");
      79             :   }
      80             : 
      81           0 :   NS_IMETHOD_(void) Unlink(void*) override
      82             :   {
      83           0 :     MOZ_ASSERT(false, "Don't call Unlink on GC things, as they may be dead");
      84             :   }
      85             : 
      86           0 :   NS_IMETHOD_(void) Unroot(void*) override
      87             :   {
      88           0 :     MOZ_ASSERT(false, "Don't call Unroot on GC things, as they may be dead");
      89             :   }
      90             : 
      91           0 :   NS_IMETHOD_(void) DeleteCycleCollectable(void*) override
      92             :   {
      93           0 :     MOZ_ASSERT(false, "Can't directly delete a cycle collectable GC thing");
      94             :   }
      95             : 
      96             :   NS_IMETHOD TraverseNative(void* aPtr, nsCycleCollectionTraversalCallback& aCb)
      97             :     override;
      98             : 
      99           0 :   NS_DECL_CYCLE_COLLECTION_CLASS_NAME_METHOD(JSZoneParticipant)
     100             : };
     101             : 
     102             : class IncrementalFinalizeRunnable;
     103             : 
     104             : struct JSHolderInfo
     105             : {
     106             :   void* mHolder;
     107             :   nsScriptObjectTracer* mTracer;
     108             : };
     109             : 
     110             : class CycleCollectedJSRuntime
     111             : {
     112             :   friend class JSGCThingParticipant;
     113             :   friend class JSZoneParticipant;
     114             :   friend class IncrementalFinalizeRunnable;
     115             :   friend class CycleCollectedJSContext;
     116             : protected:
     117             :   CycleCollectedJSRuntime(JSContext* aMainContext);
     118             :   virtual ~CycleCollectedJSRuntime();
     119             : 
     120             :   virtual void Shutdown(JSContext* cx);
     121             : 
     122             :   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     123             :   void UnmarkSkippableJSHolders();
     124             : 
     125             :   virtual void
     126           0 :   TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& aCb) {}
     127           0 :   virtual void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) {}
     128             : 
     129           0 :   virtual void CustomGCCallback(JSGCStatus aStatus) {}
     130           0 :   virtual void CustomOutOfMemoryCallback() {}
     131             : 
     132           1 :   LinkedList<CycleCollectedJSContext>& Contexts()
     133             :   {
     134           1 :     return mContexts;
     135             :   }
     136             : 
     137             : private:
     138             :   void
     139             :   DescribeGCThing(bool aIsMarked, JS::GCCellPtr aThing,
     140             :                   nsCycleCollectionTraversalCallback& aCb) const;
     141             : 
     142             :   virtual bool
     143           0 :   DescribeCustomObjects(JSObject* aObject, const js::Class* aClasp,
     144             :                         char (&aName)[72]) const
     145             :   {
     146           0 :     return false; // We did nothing.
     147             :   }
     148             : 
     149             :   void
     150             :   NoteGCThingJSChildren(JS::GCCellPtr aThing,
     151             :                         nsCycleCollectionTraversalCallback& aCb) const;
     152             : 
     153             :   void
     154             :   NoteGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj,
     155             :                            nsCycleCollectionTraversalCallback& aCb) const;
     156             : 
     157             :   virtual bool
     158           0 :   NoteCustomGCThingXPCOMChildren(const js::Class* aClasp, JSObject* aObj,
     159             :                                  nsCycleCollectionTraversalCallback& aCb) const
     160             :   {
     161           0 :     return false; // We did nothing.
     162             :   }
     163             : 
     164             :   enum TraverseSelect {
     165             :     TRAVERSE_CPP,
     166             :     TRAVERSE_FULL
     167             :   };
     168             : 
     169             :   void
     170             :   TraverseGCThing(TraverseSelect aTs, JS::GCCellPtr aThing,
     171             :                   nsCycleCollectionTraversalCallback& aCb);
     172             : 
     173             :   void
     174             :   TraverseZone(JS::Zone* aZone, nsCycleCollectionTraversalCallback& aCb);
     175             : 
     176             :   static void
     177             :   TraverseObjectShim(void* aData, JS::GCCellPtr aThing);
     178             : 
     179             :   void TraverseNativeRoots(nsCycleCollectionNoteRootCallback& aCb);
     180             : 
     181             :   static void TraceBlackJS(JSTracer* aTracer, void* aData);
     182             :   static void TraceGrayJS(JSTracer* aTracer, void* aData);
     183             :   static void GCCallback(JSContext* aContext, JSGCStatus aStatus, void* aData);
     184             :   static void GCSliceCallback(JSContext* aContext, JS::GCProgress aProgress,
     185             :                               const JS::GCDescription& aDesc);
     186             :   static void GCNurseryCollectionCallback(JSContext* aContext,
     187             :                                           JS::GCNurseryProgress aProgress,
     188             :                                           JS::gcreason::Reason aReason);
     189             :   static void OutOfMemoryCallback(JSContext* aContext, void* aData);
     190             :   /**
     191             :    * Callback for reporting external string memory.
     192             :    */
     193             :   static size_t SizeofExternalStringCallback(JSString* aStr,
     194             :                                              mozilla::MallocSizeOf aMallocSizeOf);
     195             : 
     196             :   static bool ContextCallback(JSContext* aCx, unsigned aOperation,
     197             :                               void* aData);
     198             : 
     199           0 :   virtual void TraceNativeBlackRoots(JSTracer* aTracer) { };
     200             :   void TraceNativeGrayRoots(JSTracer* aTracer);
     201             : 
     202             : public:
     203             :   void FinalizeDeferredThings(CycleCollectedJSContext::DeferredFinalizeType aType);
     204             : 
     205             :   virtual void PrepareForForgetSkippable() = 0;
     206             :   virtual void BeginCycleCollectionCallback() = 0;
     207             :   virtual void EndCycleCollectionCallback(CycleCollectorResults& aResults) = 0;
     208             :   virtual void DispatchDeferredDeletion(bool aContinuation, bool aPurge = false) = 0;
     209             : 
     210             :   // Two conditions, JSOutOfMemory and JSLargeAllocationFailure, are noted in
     211             :   // crash reports. Here are the values that can appear in the reports:
     212             :   enum class OOMState : uint32_t {
     213             :     // The condition has never happened. No entry appears in the crash report.
     214             :     OK,
     215             : 
     216             :     // We are currently reporting the given condition.
     217             :     //
     218             :     // Suppose a crash report contains "JSLargeAllocationFailure:
     219             :     // Reporting". This means we crashed while executing memory-pressure
     220             :     // observers, trying to shake loose some memory. The large allocation in
     221             :     // question did not return null: it is still on the stack. Had we not
     222             :     // crashed, it would have been retried.
     223             :     Reporting,
     224             : 
     225             :     // The condition has been reported since the last GC.
     226             :     //
     227             :     // If a crash report contains "JSOutOfMemory: Reported", that means a small
     228             :     // allocation failed, and then we crashed, probably due to buggy
     229             :     // error-handling code that ran after allocation returned null.
     230             :     //
     231             :     // This contrasts with "Reporting" which means that no error-handling code
     232             :     // had executed yet.
     233             :     Reported,
     234             : 
     235             :     // The condition has happened, but a GC cycle ended since then.
     236             :     //
     237             :     // GC is taken as a proxy for "we've been banging on the heap a good bit
     238             :     // now and haven't crashed; the OOM was probably handled correctly".
     239             :     Recovered
     240             :   };
     241             : 
     242             :   void SetLargeAllocationFailure(OOMState aNewState);
     243             : 
     244             :   void AnnotateAndSetOutOfMemory(OOMState* aStatePtr, OOMState aNewState);
     245             :   void OnGC(JSContext* aContext, JSGCStatus aStatus);
     246             :   void OnOutOfMemory();
     247             :   void OnLargeAllocationFailure();
     248             : 
     249        1788 :   JSRuntime* Runtime() { return mJSRuntime; }
     250             : 
     251             : public:
     252             :   void AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
     253             :   void RemoveJSHolder(void* aHolder);
     254             : #ifdef DEBUG
     255             :   bool IsJSHolder(void* aHolder);
     256             :   void AssertNoObjectsToTrace(void* aPossibleJSHolder);
     257             : #endif
     258             : 
     259             :   nsCycleCollectionParticipant* GCThingParticipant();
     260             :   nsCycleCollectionParticipant* ZoneParticipant();
     261             : 
     262             :   nsresult TraverseRoots(nsCycleCollectionNoteRootCallback& aCb);
     263             :   virtual bool UsefulToMergeZones() const;
     264             :   void FixWeakMappingGrayBits() const;
     265             :   void CheckGrayBits() const;
     266             :   bool AreGCGrayBitsValid() const;
     267             :   void GarbageCollect(uint32_t aReason) const;
     268             : 
     269             :   // This needs to be an nsWrapperCache, not a JSObject, because we need to know
     270             :   // when our object gets moved.  But we can't trace it (and hence update our
     271             :   // storage), because we do not want to keep it alive.  nsWrapperCache handles
     272             :   // this for us via its "object moved" handling.
     273             :   void NurseryWrapperAdded(nsWrapperCache* aCache);
     274             :   void NurseryWrapperPreserved(JSObject* aWrapper);
     275             :   void JSObjectsTenured();
     276             : 
     277             :   void DeferredFinalize(DeferredFinalizeAppendFunction aAppendFunc,
     278             :                         DeferredFinalizeFunction aFunc,
     279             :                         void* aThing);
     280             :   void DeferredFinalize(nsISupports* aSupports);
     281             : 
     282             :   void DumpJSHeap(FILE* aFile);
     283             : 
     284             :   // Add aZone to the set of zones waiting for a GC.
     285          11 :   void AddZoneWaitingForGC(JS::Zone* aZone)
     286             :   {
     287          11 :     mZonesWaitingForGC.PutEntry(aZone);
     288          11 :   }
     289             : 
     290             :   // Prepare any zones for GC that have been passed to AddZoneWaitingForGC()
     291             :   // since the last GC or since the last call to PrepareWaitingZonesForGC(),
     292             :   // whichever was most recent. If there were no such zones, prepare for a
     293             :   // full GC.
     294             :   void PrepareWaitingZonesForGC();
     295             : 
     296             :   // Get the current thread's CycleCollectedJSRuntime.  Returns null if there
     297             :   // isn't one.
     298             :   static CycleCollectedJSRuntime* Get();
     299             : 
     300             :   void AddContext(CycleCollectedJSContext* aContext);
     301             :   void RemoveContext(CycleCollectedJSContext* aContext);
     302             : 
     303             : private:
     304             :   LinkedList<CycleCollectedJSContext> mContexts;
     305             : 
     306             :   JSGCThingParticipant mGCThingCycleCollectorGlobal;
     307             : 
     308             :   JSZoneParticipant mJSZoneCycleCollectorGlobal;
     309             : 
     310             :   JSRuntime* mJSRuntime;
     311             : 
     312             :   JS::GCSliceCallback mPrevGCSliceCallback;
     313             :   JS::GCNurseryCollectionCallback mPrevGCNurseryCollectionCallback;
     314             : 
     315             :   mozilla::TimeStamp mLatestNurseryCollectionStart;
     316             : 
     317             :   SegmentedVector<JSHolderInfo, 1024, InfallibleAllocPolicy> mJSHolders;
     318             :   nsDataHashtable<nsPtrHashKey<void>, JSHolderInfo*> mJSHolderMap;
     319             : 
     320             :   typedef nsDataHashtable<nsFuncPtrHashKey<DeferredFinalizeFunction>, void*>
     321             :     DeferredFinalizerTable;
     322             :   DeferredFinalizerTable mDeferredFinalizerTable;
     323             : 
     324             :   RefPtr<IncrementalFinalizeRunnable> mFinalizeRunnable;
     325             : 
     326             :   OOMState mOutOfMemoryState;
     327             :   OOMState mLargeAllocationFailureState;
     328             : 
     329             :   static const size_t kSegmentSize = 512;
     330             :   SegmentedVector<nsWrapperCache*, kSegmentSize, InfallibleAllocPolicy>
     331             :     mNurseryObjects;
     332             :   SegmentedVector<JS::PersistentRooted<JSObject*>, kSegmentSize,
     333             :                   InfallibleAllocPolicy>
     334             :     mPreservedNurseryObjects;
     335             : 
     336             :   nsTHashtable<nsPtrHashKey<JS::Zone>> mZonesWaitingForGC;
     337             : 
     338           4 :   struct EnvironmentPreparer : public js::ScriptEnvironmentPreparer {
     339             :     void invoke(JS::HandleObject scope, Closure& closure) override;
     340             :   };
     341             :   EnvironmentPreparer mEnvironmentPreparer;
     342             : };
     343             : 
     344             : void TraceScriptHolder(nsISupports* aHolder, JSTracer* aTracer);
     345             : 
     346             : // Returns true if the JS::TraceKind is one the cycle collector cares about.
     347        2592 : inline bool AddToCCKind(JS::TraceKind aKind)
     348             : {
     349           0 :   return aKind == JS::TraceKind::Object ||
     350           0 :          aKind == JS::TraceKind::Script ||
     351        2592 :          aKind == JS::TraceKind::Scope ||
     352        2592 :          aKind == JS::TraceKind::RegExpShared;
     353             : }
     354             : 
     355             : bool
     356             : GetBuildId(JS::BuildIdCharVector* aBuildID);
     357             : 
     358             : } // namespace mozilla
     359             : 
     360             : #endif // mozilla_CycleCollectedJSRuntime_h

Generated by: LCOV version 1.13