/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
class nsCycleCollectionNoteRootCallback; class nsIRunnable; class nsThread;
namespace mozilla { class AutoSlowOperation;
class CycleCollectedJSContext; class CycleCollectedJSRuntime;
namespace dom { class Exception; class WorkerJSContext; class WorkletJSContext;
} // namespace dom
// Contains various stats about the cycle collection. struct CycleCollectorResults {
CycleCollectorResults() { // Initialize here so when we increment mNumSlices the first time we're // not using uninitialized memory.
Init();
}
void Init() {
mForcedGC = false;
mSuspectedAtCCStart = 0;
mMergedZones = false;
mAnyManual = false;
mVisitedRefCounted = 0;
mVisitedGCed = 0;
mFreedRefCounted = 0;
mFreedGCed = 0;
mFreedJSZones = 0;
mNumSlices = 1; // mNumSlices is initialized to one, because we call Init() after the // per-slice increment of mNumSlices has already occurred.
}
bool mForcedGC; bool mMergedZones; // mAnyManual is true if any slice was manually triggered, and at shutdown. bool mAnyManual;
uint32_t mSuspectedAtCCStart;
uint32_t mVisitedRefCounted;
uint32_t mVisitedGCed;
uint32_t mFreedRefCounted;
uint32_t mFreedGCed;
uint32_t mFreedJSZones;
uint32_t mNumSlices;
};
// Store the suppressed mictotasks in another microtask so that operations // for the microtask queue as a whole keep working. class SuppressedMicroTasks : public MicroTaskRunnable { public: explicit SuppressedMicroTasks(CycleCollectedJSContext* aContext);
MOZ_CAN_RUN_SCRIPT_BOUNDARY void Run(AutoSlowOperation& aAso) final {} virtualbool Suppressed();
// Support for JS FinalizationRegistry objects, which allow a JS callback to be // registered that is called when objects die. // // We keep a vector of functions that call back into the JS engine along // with their associated incumbent globals, one per FinalizationRegistry object // that has pending cleanup work. These are run in their own task. class FinalizationRegistryCleanup { public: explicit FinalizationRegistryCleanup(CycleCollectedJSContext* aContext); void Init(); void Destroy(); void QueueCallback(JSFunction* aDoCleanup, JSObject* aHostDefinedData);
MOZ_CAN_RUN_SCRIPT void DoCleanup();
// This object is part of CycleCollectedJSContext, so it's safe to have a raw // pointer to its containing context here.
CycleCollectedJSContext* mContext;
using CallbackVector = JS::GCVector<Callback, 0, InfallibleAllocPolicy>;
JS::PersistentRooted<CallbackVector> mCallbacks;
};
public: // nsThread entrypoints // // MOZ_CAN_RUN_SCRIPT_BOUNDARY so we don't need to annotate // nsThread::ProcessNextEvent and all its callers MOZ_CAN_RUN_SCRIPT for now. // But we really should!
MOZ_CAN_RUN_SCRIPT_BOUNDARY virtualvoid BeforeProcessTask(bool aMightBlock); // MOZ_CAN_RUN_SCRIPT_BOUNDARY so we don't need to annotate // nsThread::ProcessNextEvent and all its callers MOZ_CAN_RUN_SCRIPT for now. // But we really should!
MOZ_CAN_RUN_SCRIPT_BOUNDARY virtualvoid AfterProcessTask(uint32_t aRecursionDepth);
// Check whether any eager thresholds have been reached, which would mean // an idle GC task (minor or major) would be useful. virtualvoid MaybePokeGC();
uint32_t RecursionDepth() const;
// Run in stable state (call through nsContentUtils) void RunInStableState(already_AddRefed<nsIRunnable>&& aRunnable);
// Get the CycleCollectedJSContext for a JSContext. // Returns null only if Initialize() has not completed on or during // destruction of the CycleCollectedJSContext. static CycleCollectedJSContext* GetFor(JSContext* aCx);
// Get the current thread's CycleCollectedJSContext. Returns null if there // isn't one. static CycleCollectedJSContext* Get();
// Queue an async microtask to the current main or worker thread. virtualvoid DispatchToMicroTask(
already_AddRefed<MicroTaskRunnable> aRunnable);
// Call EnterMicroTask when you're entering JS execution. // Usually the best way to do this is to use nsAutoMicroTask. void EnterMicroTask() { ++mMicroTaskLevel; }
// Storage for watching rejected promises waiting for some client to // consume their rejection. // Promises in this list have been rejected in the last turn of the // event loop without the rejection being handled. // Note that this can contain nullptrs in place of promises removed because // they're consumed before it'd be reported.
JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>>
mUncaughtRejections;
// Promises in this list have previously been reported as rejected // (because they were in the above list), but the rejection was handled // in the last turn of the event loop.
JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>>
mConsumedRejections;
nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */>>
mUncaughtRejectionObservers;
virtualbool IsSystemCaller() const = 0;
// Unused on main thread. Used by AutoJSAPI on Worker and Worklet threads. virtualvoid ReportError(JSErrorReport* aReport,
JS::ConstUTF8CharsZ aToStringResult) {
MOZ_ASSERT_UNREACHABLE("Not supported");
}
// These two functions control a special flag variable which lets us turn // tracing on and off from a thread other than this JSContext's main thread. // This is useful because we want to be able to start tracing many threads // all at once from the Gecko Profiler in Firefox. // // NOTE: the caller must ensure that this CycleCollectedJSContext is not // being destroyed when this is called. At the time of this API being added, // the only consumer is the Gecko Profiler, which guarantees this via a mutex // around unregistering the context, which always occurs before the context // is destroyed. void BeginExecutionTracingAsync(); void EndExecutionTracingAsync();
private: // JS::JobQueue implementation: see js/public/Promise.h. // SpiderMonkey uses some of these methods to enqueue promise resolution jobs. // Others protect the debuggee microtask queue from the debugger's // interruptions; see the comments on JS::AutoDebuggerJobQueueInterruption for // details. bool getHostDefinedData(JSContext* cx,
JS::MutableHandle<JSObject*> aData) const override;
bool enqueuePromiseJob(JSContext* cx, JS::Handle<JSObject*> promise,
JS::Handle<JSObject*> job,
JS::Handle<JSObject*> allocationSite,
JS::Handle<JSObject*> hostDefinedData) override; // MOZ_CAN_RUN_SCRIPT_BOUNDARY for now so we don't have to change SpiderMonkey // headers. The caller presumably knows this can run script (like everything // in SpiderMonkey!) and will deal.
MOZ_CAN_RUN_SCRIPT_BOUNDARY void runJobs(JSContext* cx) override; bool empty() const override; bool isDrainingStopped() const override { returnfalse; } class SavedMicroTaskQueue;
js::UniquePtr<SavedJobQueue> saveJobQueue(JSContext*) override;
private:
CycleCollectedJSRuntime* mRuntime;
JSContext* mJSContext;
nsCOMPtr<dom::Exception> mPendingException;
nsThread* mOwningThread; // Manual refcounting to avoid include hell.
// How many times the debugger has interrupted execution, possibly creating // microtask checkpoints in places that they would not normally occur.
uint32_t mDebuggerRecursionDepth;
// This is for the "outstanding rejected promises weak set" in the spec, // https://html.spec.whatwg.org/multipage/webappapis.html#outstanding-rejected-promises-weak-set // We use different data structure and opposite logic here to achieve the same // effect. Basically this is used for tracking the rejected promise that does // NOT need firing a rejectionhandled event. We will check the table to see if // firing rejectionhandled event is required when a rejected promise is being // handled. // // The rejected promise will be stored in the table if // - it is unhandled, and // - The unhandledrejection is not yet fired. // // And be removed when // - it is handled, or // - A unhandledrejection is fired and it isn't being handled in event // handler. typedef nsRefPtrHashtable<nsUint64HashKey, dom::Promise> PromiseHashtable;
PromiseHashtable mPendingUnhandledRejections;
class NotifyUnhandledRejections final : public CancelableRunnable { public: explicit NotifyUnhandledRejections(PromiseArray&& aPromises)
: CancelableRunnable("NotifyUnhandledRejections"),
mUnhandledRejections(std::move(aPromises)) {}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.