LCOV - code coverage report
Current view: top level - xpcom/base - CycleCollectedJSContext.h (source / functions) Hit Total Coverage
Test: output.info Lines: 39 41 95.1 %
Date: 2017-07-14 16:53:18 Functions: 10 15 66.7 %
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_CycleCollectedJSContext_h
       8             : #define mozilla_CycleCollectedJSContext_h
       9             : 
      10             : #include <queue>
      11             : 
      12             : #include "mozilla/DeferredFinalize.h"
      13             : #include "mozilla/LinkedList.h"
      14             : #include "mozilla/mozalloc.h"
      15             : #include "mozilla/MemoryReporting.h"
      16             : #include "jsapi.h"
      17             : #include "jsfriendapi.h"
      18             : 
      19             : #include "nsCOMPtr.h"
      20             : #include "nsCycleCollectionParticipant.h"
      21             : #include "nsTArray.h"
      22             : 
      23             : class nsCycleCollectionNoteRootCallback;
      24             : class nsIException;
      25             : class nsIRunnable;
      26             : class nsThread;
      27             : class nsWrapperCache;
      28             : 
      29             : namespace mozilla {
      30             : 
      31             : class CycleCollectedJSRuntime;
      32             : 
      33             : // Contains various stats about the cycle collection.
      34             : struct CycleCollectorResults
      35             : {
      36           4 :   CycleCollectorResults()
      37           4 :   {
      38             :     // Initialize here so when we increment mNumSlices the first time we're
      39             :     // not using uninitialized memory.
      40           4 :     Init();
      41           4 :   }
      42             : 
      43           4 :   void Init()
      44             :   {
      45           4 :     mForcedGC = false;
      46           4 :     mMergedZones = false;
      47           4 :     mAnyManual = false;
      48           4 :     mVisitedRefCounted = 0;
      49           4 :     mVisitedGCed = 0;
      50           4 :     mFreedRefCounted = 0;
      51           4 :     mFreedGCed = 0;
      52           4 :     mFreedJSZones = 0;
      53           4 :     mNumSlices = 1;
      54             :     // mNumSlices is initialized to one, because we call Init() after the
      55             :     // per-slice increment of mNumSlices has already occurred.
      56           4 :   }
      57             : 
      58             :   bool mForcedGC;
      59             :   bool mMergedZones;
      60             :   bool mAnyManual; // true if any slice of the CC was manually triggered, or at shutdown.
      61             :   uint32_t mVisitedRefCounted;
      62             :   uint32_t mVisitedGCed;
      63             :   uint32_t mFreedRefCounted;
      64             :   uint32_t mFreedGCed;
      65             :   uint32_t mFreedJSZones;
      66             :   uint32_t mNumSlices;
      67             : };
      68             : 
      69             : class CycleCollectedJSContext
      70             :   : public LinkedListElement<CycleCollectedJSContext>
      71             : {
      72             :   friend class CycleCollectedJSRuntime;
      73             : 
      74             : protected:
      75             :   CycleCollectedJSContext();
      76             :   virtual ~CycleCollectedJSContext();
      77             : 
      78             :   MOZ_IS_CLASS_INIT
      79             :   nsresult Initialize(JSRuntime* aParentRuntime,
      80             :                       uint32_t aMaxBytes,
      81             :                       uint32_t aMaxNurseryBytes);
      82             : 
      83             :   // See explanation in mIsPrimaryContext.
      84             :   MOZ_IS_CLASS_INIT
      85             :   nsresult InitializeNonPrimary(CycleCollectedJSContext* aPrimaryContext);
      86             : 
      87             :   virtual CycleCollectedJSRuntime* CreateRuntime(JSContext* aCx) = 0;
      88             : 
      89             :   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
      90             : 
      91             :   std::queue<nsCOMPtr<nsIRunnable>> mPromiseMicroTaskQueue;
      92             :   std::queue<nsCOMPtr<nsIRunnable>> mDebuggerPromiseMicroTaskQueue;
      93             : 
      94             : private:
      95             :   MOZ_IS_CLASS_INIT
      96             :   void InitializeCommon();
      97             : 
      98             :   static JSObject* GetIncumbentGlobalCallback(JSContext* aCx);
      99             :   static bool EnqueuePromiseJobCallback(JSContext* aCx,
     100             :                                         JS::HandleObject aJob,
     101             :                                         JS::HandleObject aAllocationSite,
     102             :                                         JS::HandleObject aIncumbentGlobal,
     103             :                                         void* aData);
     104             :   static void PromiseRejectionTrackerCallback(JSContext* aCx,
     105             :                                               JS::HandleObject aPromise,
     106             :                                               PromiseRejectionHandlingState state,
     107             :                                               void* aData);
     108             : 
     109             :   void AfterProcessMicrotask(uint32_t aRecursionDepth);
     110             : public:
     111             :   void ProcessStableStateQueue();
     112             : private:
     113             :   void ProcessMetastableStateQueue(uint32_t aRecursionDepth);
     114             : 
     115             : public:
     116             :   enum DeferredFinalizeType {
     117             :     FinalizeIncrementally,
     118             :     FinalizeNow,
     119             :   };
     120             : 
     121       28217 :   CycleCollectedJSRuntime* Runtime() const
     122             :   {
     123       28217 :     MOZ_ASSERT(mRuntime);
     124       28217 :     return mRuntime;
     125             :   }
     126             : 
     127             :   already_AddRefed<nsIException> GetPendingException() const;
     128             :   void SetPendingException(nsIException* aException);
     129             : 
     130             :   std::queue<nsCOMPtr<nsIRunnable>>& GetPromiseMicroTaskQueue();
     131             :   std::queue<nsCOMPtr<nsIRunnable>>& GetDebuggerPromiseMicroTaskQueue();
     132             : 
     133      200062 :   JSContext* Context() const
     134             :   {
     135      200062 :     MOZ_ASSERT(mJSContext);
     136      200062 :     return mJSContext;
     137             :   }
     138             : 
     139         183 :   JS::RootingContext* RootingCx() const
     140             :   {
     141         183 :     MOZ_ASSERT(mJSContext);
     142         183 :     return JS::RootingContext::get(mJSContext);
     143             :   }
     144             : 
     145          31 :   bool MicroTaskCheckpointDisabled() const
     146             :   {
     147          31 :     return mDisableMicroTaskCheckpoint;
     148             :   }
     149             : 
     150          62 :   void DisableMicroTaskCheckpoint(bool aDisable)
     151             :   {
     152          62 :     mDisableMicroTaskCheckpoint = aDisable;
     153          62 :   }
     154             : 
     155             :   class MOZ_RAII AutoDisableMicroTaskCheckpoint
     156             :   {
     157             :     public:
     158          31 :     AutoDisableMicroTaskCheckpoint()
     159          31 :     : mCCJSCX(CycleCollectedJSContext::Get())
     160             :     {
     161          31 :       mOldValue = mCCJSCX->MicroTaskCheckpointDisabled();
     162          31 :       mCCJSCX->DisableMicroTaskCheckpoint(true);
     163          31 :     }
     164             : 
     165          31 :     ~AutoDisableMicroTaskCheckpoint()
     166          31 :     {
     167          31 :       mCCJSCX->DisableMicroTaskCheckpoint(mOldValue);
     168          31 :     }
     169             : 
     170             :     CycleCollectedJSContext* mCCJSCX;
     171             :     bool mOldValue;
     172             :   };
     173             : 
     174             : protected:
     175           0 :   JSContext* MaybeContext() const { return mJSContext; }
     176             : 
     177             : public:
     178             :   // nsThread entrypoints
     179        1265 :   virtual void BeforeProcessTask(bool aMightBlock) { };
     180             :   virtual void AfterProcessTask(uint32_t aRecursionDepth);
     181             : 
     182             :   // microtask processor entry point
     183             :   void AfterProcessMicrotask();
     184             : 
     185             :   uint32_t RecursionDepth();
     186             : 
     187             :   // Run in stable state (call through nsContentUtils)
     188             :   void RunInStableState(already_AddRefed<nsIRunnable>&& aRunnable);
     189             :   // This isn't in the spec at all yet, but this gets the behavior we want for IDB.
     190             :   // Runs after the current microtask completes.
     191             :   void RunInMetastableState(already_AddRefed<nsIRunnable>&& aRunnable);
     192             : 
     193             :   // Get the current thread's CycleCollectedJSContext.  Returns null if there
     194             :   // isn't one.
     195             :   static CycleCollectedJSContext* Get();
     196             : 
     197             :   // Queue an async microtask to the current main or worker thread.
     198             :   virtual void DispatchToMicroTask(already_AddRefed<nsIRunnable> aRunnable);
     199             : 
     200             :   // Storage for watching rejected promises waiting for some client to
     201             :   // consume their rejection.
     202             :   // Promises in this list have been rejected in the last turn of the
     203             :   // event loop without the rejection being handled.
     204             :   // Note that this can contain nullptrs in place of promises removed because
     205             :   // they're consumed before it'd be reported.
     206             :   JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mUncaughtRejections;
     207             : 
     208             :   // Promises in this list have previously been reported as rejected
     209             :   // (because they were in the above list), but the rejection was handled
     210             :   // in the last turn of the event loop.
     211             :   JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mConsumedRejections;
     212             :   nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
     213             : 
     214             : private:
     215             :   // A primary context owns the mRuntime. Non-main-thread contexts should always
     216             :   // be primary. On the main thread, the primary context should be the first one
     217             :   // created and the last one destroyed. Non-primary contexts are used for
     218             :   // cooperatively scheduled threads.
     219             :   bool mIsPrimaryContext;
     220             : 
     221             :   CycleCollectedJSRuntime* mRuntime;
     222             : 
     223             :   JSContext* mJSContext;
     224             : 
     225             :   nsCOMPtr<nsIException> mPendingException;
     226             :   nsThread* mOwningThread; // Manual refcounting to avoid include hell.
     227             : 
     228           0 :   struct RunInMetastableStateData
     229             :   {
     230             :     nsCOMPtr<nsIRunnable> mRunnable;
     231             :     uint32_t mRecursionDepth;
     232             :   };
     233             : 
     234             :   nsTArray<nsCOMPtr<nsIRunnable>> mStableStateEvents;
     235             :   nsTArray<RunInMetastableStateData> mMetastableStateEvents;
     236             :   uint32_t mBaseRecursionDepth;
     237             :   bool mDoingStableStates;
     238             : 
     239             :   bool mDisableMicroTaskCheckpoint;
     240             : };
     241             : 
     242             : } // namespace mozilla
     243             : 
     244             : #endif // mozilla_CycleCollectedJSContext_h

Generated by: LCOV version 1.13