mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1492011 introduce a separate class to hold main-thread data associated with each Console r=baku
This provides that ConsoleRunnable no longer has a reference to Console, which previously needed to be released through a message to the console thread. Differential Revision: https://phabricator.services.mozilla.com/D67999 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
7a8ede2509
commit
8000fcef11
@ -218,6 +218,35 @@ class ConsoleCallData final {
|
||||
~ConsoleCallData() { AssertIsOnOwningThread(); }
|
||||
};
|
||||
|
||||
// MainThreadConsoleData instances are created on the Console thread and
|
||||
// referenced from both main and Console threads in order to provide the same
|
||||
// object for any ConsoleRunnables relating to the same Console. A Console
|
||||
// owns a MainThreadConsoleData; MainThreadConsoleData does not keep its
|
||||
// Console alive.
|
||||
class MainThreadConsoleData final {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MainThreadConsoleData);
|
||||
|
||||
JSObject* GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal);
|
||||
// This method must receive aCx and aArguments in the same JS::Compartment.
|
||||
void ProcessCallData(JSContext* aCx, ConsoleCallData* aData,
|
||||
const Sequence<JS::Value>& aArguments);
|
||||
|
||||
private:
|
||||
~MainThreadConsoleData() {
|
||||
NS_ReleaseOnMainThreadSystemGroup("MainThreadConsoleData::mStorage",
|
||||
mStorage.forget());
|
||||
NS_ReleaseOnMainThreadSystemGroup("MainThreadConsoleData::mSandbox",
|
||||
mSandbox.forget());
|
||||
}
|
||||
|
||||
// All members, except for mRefCnt, are accessed only on the main thread,
|
||||
// except in MainThreadConsoleData destruction, at which point there are no
|
||||
// other references.
|
||||
nsCOMPtr<nsIConsoleAPIStorage> mStorage;
|
||||
RefPtr<JSObjectHolder> mSandbox;
|
||||
nsTArray<nsString> mGroupStack;
|
||||
};
|
||||
|
||||
// This base class must be extended for Worker and for Worklet.
|
||||
class ConsoleRunnable : public StructuredCloneHolderBase {
|
||||
public:
|
||||
@ -284,7 +313,7 @@ class ConsoleRunnable : public StructuredCloneHolderBase {
|
||||
}
|
||||
|
||||
// Helper method for CallData
|
||||
void ProcessCallData(JSContext* aCx, Console* aConsole,
|
||||
void ProcessCallData(JSContext* aCx, MainThreadConsoleData* aConsoleData,
|
||||
ConsoleCallData* aCallData) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
@ -321,7 +350,7 @@ class ConsoleRunnable : public StructuredCloneHolderBase {
|
||||
|
||||
MOZ_ASSERT(values.Length() == length);
|
||||
|
||||
aConsole->ProcessCallData(aCx, aCallData, values);
|
||||
aConsoleData->ProcessCallData(aCx, aCallData, values);
|
||||
}
|
||||
|
||||
// Generic
|
||||
@ -414,9 +443,10 @@ class ConsoleRunnable : public StructuredCloneHolderBase {
|
||||
class ConsoleWorkletRunnable : public Runnable, public ConsoleRunnable {
|
||||
protected:
|
||||
explicit ConsoleWorkletRunnable(Console* aConsole)
|
||||
: Runnable("dom::console::ConsoleWorkletRunnable"), mConsole(aConsole) {
|
||||
: Runnable("dom::console::ConsoleWorkletRunnable"),
|
||||
mConsoleData(aConsole->GetOrCreateMainThreadData()) {
|
||||
WorkletThread::AssertIsOnWorkletThread();
|
||||
nsCOMPtr<WorkletGlobalScope> global = do_QueryInterface(mConsole->mGlobal);
|
||||
nsCOMPtr<WorkletGlobalScope> global = do_QueryInterface(aConsole->mGlobal);
|
||||
MOZ_ASSERT(global);
|
||||
mWorkletImpl = global->Impl();
|
||||
MOZ_ASSERT(mWorkletImpl);
|
||||
@ -437,7 +467,6 @@ class ConsoleWorkletRunnable : public Runnable, public ConsoleRunnable {
|
||||
WorkletThread::AssertIsOnWorkletThread();
|
||||
|
||||
ReleaseData();
|
||||
mConsole = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -448,8 +477,7 @@ class ConsoleWorkletRunnable : public Runnable, public ConsoleRunnable {
|
||||
// This method is called in the owning thread of the Console object.
|
||||
virtual void ReleaseData() = 0;
|
||||
|
||||
// This must be released on the worker thread.
|
||||
RefPtr<Console> mConsole;
|
||||
RefPtr<MainThreadConsoleData> mConsoleData;
|
||||
|
||||
RefPtr<WorkletImpl> mWorkletImpl;
|
||||
};
|
||||
@ -490,7 +518,7 @@ class ConsoleCallDataWorkletRunnable final : public ConsoleWorkletRunnable {
|
||||
AutoSafeJSContext cx;
|
||||
|
||||
JSObject* sandbox =
|
||||
mConsole->GetOrCreateSandbox(cx, mWorkletImpl->Principal());
|
||||
mConsoleData->GetOrCreateSandbox(cx, mWorkletImpl->Principal());
|
||||
JS::Rooted<JSObject*> global(cx, sandbox);
|
||||
if (NS_WARN_IF(!global)) {
|
||||
return;
|
||||
@ -505,7 +533,7 @@ class ConsoleCallDataWorkletRunnable final : public ConsoleWorkletRunnable {
|
||||
// We don't need to set a parent object in mCallData bacause there are not
|
||||
// DOM objects exposed to worklet.
|
||||
|
||||
ProcessCallData(cx, mConsole, mCallData);
|
||||
ProcessCallData(cx, mConsoleData, mCallData);
|
||||
}
|
||||
|
||||
virtual void ReleaseData() override { mCallData = nullptr; }
|
||||
@ -516,7 +544,8 @@ class ConsoleCallDataWorkletRunnable final : public ConsoleWorkletRunnable {
|
||||
class ConsoleWorkerRunnable : public WorkerProxyToMainThreadRunnable,
|
||||
public ConsoleRunnable {
|
||||
public:
|
||||
explicit ConsoleWorkerRunnable(Console* aConsole) : mConsole(aConsole) {}
|
||||
explicit ConsoleWorkerRunnable(Console* aConsole)
|
||||
: mConsoleData(aConsole->GetOrCreateMainThreadData()) {}
|
||||
|
||||
~ConsoleWorkerRunnable() override = default;
|
||||
|
||||
@ -596,7 +625,7 @@ class ConsoleWorkerRunnable : public WorkerProxyToMainThreadRunnable,
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
JS::Rooted<JSObject*> global(
|
||||
cx, mConsole->GetOrCreateSandbox(cx, wp->GetPrincipal()));
|
||||
cx, mConsoleData->GetOrCreateSandbox(cx, wp->GetPrincipal()));
|
||||
if (NS_WARN_IF(!global)) {
|
||||
return;
|
||||
}
|
||||
@ -619,7 +648,6 @@ class ConsoleWorkerRunnable : public WorkerProxyToMainThreadRunnable,
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
ReleaseData();
|
||||
mConsole = nullptr;
|
||||
}
|
||||
|
||||
// This method is called in the main-thread.
|
||||
@ -633,8 +661,7 @@ class ConsoleWorkerRunnable : public WorkerProxyToMainThreadRunnable,
|
||||
|
||||
bool ForMessaging() const override { return true; }
|
||||
|
||||
// This must be released on the worker thread.
|
||||
RefPtr<Console> mConsole;
|
||||
RefPtr<MainThreadConsoleData> mConsoleData;
|
||||
};
|
||||
|
||||
// This runnable appends a CallData object into the Console queue running on
|
||||
@ -687,7 +714,7 @@ class ConsoleCallDataWorkerRunnable final : public ConsoleWorkerRunnable {
|
||||
|
||||
mClonedData.mGlobal = aGlobal;
|
||||
|
||||
ProcessCallData(aCx, mConsole, mCallData);
|
||||
ProcessCallData(aCx, mConsoleData, mCallData);
|
||||
|
||||
mClonedData.mGlobal = nullptr;
|
||||
}
|
||||
@ -728,7 +755,7 @@ class ConsoleProfileWorkletRunnable final : public ConsoleWorkletRunnable {
|
||||
AutoSafeJSContext cx;
|
||||
|
||||
JSObject* sandbox =
|
||||
mConsole->GetOrCreateSandbox(cx, mWorkletImpl->Principal());
|
||||
mConsoleData->GetOrCreateSandbox(cx, mWorkletImpl->Principal());
|
||||
JS::Rooted<JSObject*> global(cx, sandbox);
|
||||
if (NS_WARN_IF(!global)) {
|
||||
return;
|
||||
@ -783,10 +810,6 @@ class ConsoleProfileWorkerRunnable final : public ConsoleWorkerRunnable {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Console)
|
||||
|
||||
// We don't need to traverse/unlink mStorage and mSandbox because they are not
|
||||
// CCed objects and they are only used on the main thread, even when this
|
||||
// Console object is used on workers.
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Console)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsoleEventNotifier)
|
||||
@ -933,9 +956,6 @@ void Console::Shutdown() {
|
||||
}
|
||||
}
|
||||
|
||||
NS_ReleaseOnMainThreadSystemGroup("Console::mStorage", mStorage.forget());
|
||||
NS_ReleaseOnMainThreadSystemGroup("Console::mSandbox", mSandbox.forget());
|
||||
|
||||
mTimerRegistry.Clear();
|
||||
mCounterRegistry.Clear();
|
||||
|
||||
@ -1437,7 +1457,7 @@ void Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
|
||||
callData->SetIDs(NS_LITERAL_STRING("jsm"), filename);
|
||||
}
|
||||
|
||||
ProcessCallData(aCx, callData, aData);
|
||||
GetOrCreateMainThreadData()->ProcessCallData(aCx, callData, aData);
|
||||
|
||||
// Just because we don't want to expose
|
||||
// retrieveConsoleEvents/setConsoleEventHandler to main-thread, we can
|
||||
@ -1467,6 +1487,16 @@ void Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
|
||||
}
|
||||
}
|
||||
|
||||
MainThreadConsoleData* Console::GetOrCreateMainThreadData() {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (!mMainThreadData) {
|
||||
mMainThreadData = new MainThreadConsoleData();
|
||||
}
|
||||
|
||||
return mMainThreadData;
|
||||
}
|
||||
|
||||
// We store information to lazily compute the stack in the reserved slots of
|
||||
// LazyStackGetter. The first slot always stores a JS object: it's either the
|
||||
// JS wrapper of the nsIStackFrame or the actual reified stack representation.
|
||||
@ -1503,8 +1533,9 @@ bool LazyStackGetter(JSContext* aCx, unsigned aArgc, JS::Value* aVp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Console::ProcessCallData(JSContext* aCx, ConsoleCallData* aData,
|
||||
const Sequence<JS::Value>& aArguments) {
|
||||
void MainThreadConsoleData::ProcessCallData(
|
||||
JSContext* aCx, ConsoleCallData* aData,
|
||||
const Sequence<JS::Value>& aArguments) {
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aData);
|
||||
|
||||
@ -1523,7 +1554,7 @@ void Console::ProcessCallData(JSContext* aCx, ConsoleCallData* aData,
|
||||
|
||||
// aCx and aArguments are in the same compartment.
|
||||
JS::Rooted<JSObject*> targetScope(aCx, xpc::PrivilegedJunkScope());
|
||||
if (NS_WARN_IF(!PopulateConsoleNotificationInTheTargetScope(
|
||||
if (NS_WARN_IF(!Console::PopulateConsoleNotificationInTheTargetScope(
|
||||
aCx, aArguments, targetScope, &eventValue, aData, &mGroupStack))) {
|
||||
return;
|
||||
}
|
||||
@ -1549,7 +1580,7 @@ void Console::ProcessCallData(JSContext* aCx, ConsoleCallData* aData,
|
||||
innerID.AppendInt(aData->mInnerIDNumber);
|
||||
}
|
||||
|
||||
if (aData->mMethodName == MethodClear) {
|
||||
if (aData->mMethodName == Console::MethodClear) {
|
||||
DebugOnly<nsresult> rv = mStorage->ClearEvents(innerID);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "ClearEvents failed");
|
||||
}
|
||||
@ -2360,8 +2391,8 @@ bool Console::ShouldIncludeStackTrace(MethodName aMethodName) {
|
||||
}
|
||||
}
|
||||
|
||||
JSObject* Console::GetOrCreateSandbox(JSContext* aCx,
|
||||
nsIPrincipal* aPrincipal) {
|
||||
JSObject* MainThreadConsoleData::GetOrCreateSandbox(JSContext* aCx,
|
||||
nsIPrincipal* aPrincipal) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (!mSandbox) {
|
||||
|
@ -32,6 +32,7 @@ class ConsoleInstanceDumpCallback;
|
||||
class ConsoleRunnable;
|
||||
class ConsoleCallDataRunnable;
|
||||
class ConsoleProfileRunnable;
|
||||
class MainThreadConsoleData;
|
||||
|
||||
class Console final : public nsIObserver, public nsSupportsWeakReference {
|
||||
public:
|
||||
@ -222,9 +223,7 @@ class Console final : public nsIObserver, public nsSupportsWeakReference {
|
||||
MethodName aMethodName,
|
||||
const nsAString& aMethodString);
|
||||
|
||||
// This method must receive aCx and aArguments in the same JS::Compartment.
|
||||
void ProcessCallData(JSContext* aCx, ConsoleCallData* aData,
|
||||
const Sequence<JS::Value>& aArguments);
|
||||
MainThreadConsoleData* GetOrCreateMainThreadData();
|
||||
|
||||
// Returns true on success; otherwise false.
|
||||
bool StoreCallData(JSContext* aCx, ConsoleCallData* aCallData,
|
||||
@ -350,8 +349,6 @@ class Console final : public nsIObserver, public nsSupportsWeakReference {
|
||||
|
||||
static bool ShouldIncludeStackTrace(MethodName aMethodName);
|
||||
|
||||
JSObject* GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal);
|
||||
|
||||
void AssertIsOnOwningThread() const;
|
||||
|
||||
bool IsShuttingDown() const;
|
||||
@ -401,9 +398,6 @@ class Console final : public nsIObserver, public nsSupportsWeakReference {
|
||||
|
||||
// Owning/CC thread only
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
// These nsCOMPtr are touched on main thread only.
|
||||
nsCOMPtr<nsIConsoleAPIStorage> mStorage;
|
||||
RefPtr<JSObjectHolder> mSandbox;
|
||||
|
||||
// Touched on the owner thread.
|
||||
nsDataHashtable<nsStringHashKey, DOMHighResTimeStamp> mTimerRegistry;
|
||||
@ -419,7 +413,9 @@ class Console final : public nsIObserver, public nsSupportsWeakReference {
|
||||
|
||||
RefPtr<AnyCallback> mConsoleEventNotifier;
|
||||
|
||||
// This is the stack for groupping.
|
||||
RefPtr<MainThreadConsoleData> mMainThreadData;
|
||||
// This is the stack for grouping relating to Console-thread events, when
|
||||
// the Console thread is not the main thread.
|
||||
nsTArray<nsString> mGroupStack;
|
||||
|
||||
uint64_t mOuterID;
|
||||
@ -448,6 +444,7 @@ class Console final : public nsIObserver, public nsSupportsWeakReference {
|
||||
friend class ConsoleRunnable;
|
||||
friend class ConsoleWorkerRunnable;
|
||||
friend class ConsoleWorkletRunnable;
|
||||
friend class MainThreadConsoleData;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
Loading…
Reference in New Issue
Block a user