Once WorkerPrivate::ResetWorkerPrivateInWorkerThread() is called, the connection between the WorkerPrivate and the WorkerThread is decoupled. This means the WorkerPrivate is not valid anymore for any WorkerThreadRunnables. So, before decoupling the WorkerPrivate and WorkerThread, we should ensure all pending WorkerThreadRunnables are executed, and the Worker should be in the "Dead" status.
It means the logic in the WorkerPrivate::RunLoopNeverRan() except WorkerPrivate::ScheduleDeletion() should be executed before WorkerPrivate::ResetWorkerPrivateInWorkerThread(). However, currently, these logic are executed after ResetWorkerPrivateInWorkerThread().
Differential Revision: https://phabricator.services.mozilla.com/D210775
Sensible defaults are very different for the browser and the shell so I added
separate constants. I think the JS testing functions can get called from the
browser and so may pick the wrong default but it's not too serious.
Differential Revision: https://phabricator.services.mozilla.com/D210058
Atomics.wait prevent WorkerDebuggerRunnable's from running by blocking the event loop.
While dispatching these runnables, also spawn a short timer which would interrupt the worker
and tentatively try to drain the debugger queue and resume any debugger runnable which may be blocked.
Differential Revision: https://phabricator.services.mozilla.com/D194081
In bug 1769913, we remove the WorkerThreadRunnable's raw pointer to the corresponding WorkerPrivate and expect the corresponding WorkerPrivate to be obtained by GetCurrentThreadWorkerPrivate() when WorkerThreadRunnable::Run executing.
In general, the assumption is correct. However, it could be violated in the following two situations.
1. WorkerJSContext initialization fails.
2. WorkerThreadRunnable dispatching after CycleCollector shutdown.
In both cases, there is no corresponding WorkerJSContext to get its mWorkerPrivate by GetCurrentThreadWorkerPrivate(), which causes WorkerThreadRunnable to have no WorkerPrivate for executing.
For case 1, the WorkerThreadRunnables are all from WorkerPrivate::mPreStartRunnables. These runnables need a WorkerPrivate to execute WorkerRun(). To cleanup the resources through WorkerRun() if Worker initialization fails or shutdown before DoRunLoop() starts, WorkerThreadRunnable saves a CheckedUnsafePtr<WorkerPrivate> when the runnable is dispacthed to WorkerPrivate::mPreStartRunnables.
For case 2, the solution could be much easier since the WorkerThreadRunnable is not really a WorkerThreadRunnable. Because the Worker is in the "Dead" state, the WorkerThreadRunnable could not be dispatched normally, which means by WorkerThreadRunnable::Dispatch(WorkerPrivate). So it must be from NS_DispatchToCurrentThread(), WorkerThread::Dispatch(), or other ways which treat WorkerThread as nsIThread/nsISerialEventTarget, where the runnable is wrapped as a WorkerThreadRunnable and call nsThread::Dispatch() directly. In this case, the runnable does not need to be WorkerThreadRunnable, so we should be able to call the runnable's Run() directly.
Differential Revision: https://phabricator.services.mozilla.com/D208259
WorkerRunnable no longer keeps a raw pointer(mWorkerPrivate) for the associated WorkerPrivate in this patch.
Removing the WorkerRunnable::mWorkerPrivate needs to fix the following problems.
1. Thread assertions in WorkerRunnable::Dispatch()
To fix this problem, the associated WorkerPrivate is as a parameter and passed to WorkerRunnable::Dispatch() for the dispatching thread assertions. This associated WorkerPrivate is also propagated to PreDispatch() and PostDispatch() for the children classes of WorkerRunnable()
2. Get the associated WorkerPrivate in WorkerRunnable::Run() for environment setup(GlobabObject, JSContext setting for the runnable)
- For WorkerThreadRunnable
Since WorkerThreadRunnable is supposed to run on the worker thread, it does not need to keep a raw pointer to WorkerPrivate as its class member. GetCurrentThreadWorkerPrivate() should always get the correct WorkerPrivate for WorkerThreadRunnable.
- For WorkerParentThreadRunnable
WorkerParentRef is introduced to keep a RefPtr<WorkerPrivate> for WorkerParentThreadRunnable instead of using a raw pointer.
Checking the associated WorkerPrivate existence by WorkerParentRef at the beginning of WorkerParentThreadRunnable::Run(). If the Worker has already shut down, WorkerParentThreadRunnable cannot do anything with the associated WorkerPrivate, so WorkerParentThreadRunnable::Run() will return NS_OK directly but with a warning.
The associated WorkerPrivate is also passed into WorkerRun(), PreRun(), and PostRun(), so the majority of implementations of child classes of WorkerRunnable do not need to be changed.
If there are any cases in which the child classes of WorkerThreadRunnable/WorkerParentThreadRunnable want to keep the associated WorkerPrivate, they should use WorkerRefs instead of raw pointers.
Depends on D205679
Differential Revision: https://phabricator.services.mozilla.com/D207039
In this patch, WorkerParentThreadRunnable is extracted from WorkerThreadRunnable for runnable on the parent thread.
WorkerParentControlRunnable and WorkerParentDebuggeeRunnable are also created for control runnable and debuggee runnable on the parent thread.
Instead of using WorkerRunnable::Target to indicate the thread target, inheriting WorkerThreadRunnable or WorkerParentThreadRunnable to point out that this runnable should run on the worker thread or on the parent thread. So WorkerRunnable::Target is removed in this patch.
This patch also move the dispatching logic into WorkerPrivate to simplify WorkerRunnable::DispatchInternal()'s implementation.
Depends on D205178
Differential Revision: https://phabricator.services.mozilla.com/D205679
This is the first step in splitting the parent thread runnable out of WorkerRunnable.
To reuse the runnable dispatching codes in Worker, we still need a base class for runnable on the worker thread and the parent thread.
In this patch, we rename the original WorkerRunnable to WorkerThreadRunnable and make WorkerRunnable to be WorkerThreadRunnable's parent class.
In the second patch, we will create WorkerParentThreadRunnable and its sub-classes, split from WorkerThreadRunnable for runnable on the Worker's parent thread.
And in the third patch, we will re-structure the content of WorkerParentThreadRunnable to remove unnecessary members.
Differential Revision: https://phabricator.services.mozilla.com/D205178
Sorry for the massive patch but I found it hard to split without
introducing a bunch of copies around...
This mostly makes necko and DOM agree on which strings to use, which
should result on less copies and conversions.
Differential Revision: https://phabricator.services.mozilla.com/D205601
There is two situatoins cause pending events in the worker thread after Worker status changes to "Dead."
1. The WorkerPrivate::DoRunLoop is never executed.
This is the case where the worker initialization on the worker thread fails. And then WorkerPrivate::RunLoopNeverRan() would be called for handling these fail cases. However, WorkerPrivate::mPreStartRunnables had already dispatched when WorkerPrivate::SetWorkerPrivateInWorkerThread() is called, so when the moment executing WorkerPrivate::RunLoopNeverRan(), mPreStartRunnables must in the worker thread already. CompileScriptRunnable is one of these runnable.
2. Worker enters into DoRunLoop(). The WorkerThread can be held as nsIThread or nsIEventTarget by
nsCOMPtr<nsIThread> thread = NS_GetCurrentThread()
thread->Dispatch(myRunnable);
We don't block these runnable dispatchings after the worker's status changes to "Dead" because some objects, such as cycle_collector, need to complete their shutdown after the worker's shutdown. So ExternalWrappedRunnables(wrapped here) shows up in the dispatching stack when we hit the assertion. The original runnable is from everywhere and is related to Worker.
To fix case 1, the patch wants to handle the pending events in WorkerPrivate::RunLoopNevenRan() correctly. So, call ProcessPendingEvents if needed.
To fix case 2, we process the pending events before setting WorkerThread::mWorkerPrivate as nullptr. I think this is a correct time point because I think any other shutdown jobs should be finished before we detach the WorkerPrivate from the Worker thread.
Differential Revision: https://phabricator.services.mozilla.com/D203551
mLocale is currently initialized in IndexedDatabaseManager::Init which is
called from IndexedDatabaseManager::GetOrCreate if the manager doesn't exist.
This can be a problem when IndexedDatabaseManager::GetOrCreate is called very
early,for example in nsLayoutStatics::Initialize in the parent process.
This is a preparation for moving IndexedDatabaseManager::GetOrCreate from
FactoryOp::Open to InitializeQuotaManager.
Differential Revision: https://phabricator.services.mozilla.com/D189891
Atomics.wait prevent WorkerDebuggerRunnable's from running by blocking the event loop.
While dispatching these runnables, also spawn a short timer which would interrupt the worker
and tentatively try to drain the debugger queue and resume any debugger runnable which may be blocked.
Differential Revision: https://phabricator.services.mozilla.com/D194081
Glean-based Use Counter metrics are cheaper and work as well,
so let's use them instead.
Though we do have metric name strings available in a string table in GleanJSMetrics.cpp,
access is through metric_entry_t which has information not available to usecounters.py.
So for now we return char* literals from the use counter increment fns.
Differential Revision: https://phabricator.services.mozilla.com/D199933
Glean-based Use Counter metrics are cheaper and work as well,
so let's use them instead.
Though we do have metric name strings available in a string table in GleanJSMetrics.cpp,
access is through metric_entry_t which has information not available to usecounters.py.
So for now we return char* literals from the use counter increment fns.
Differential Revision: https://phabricator.services.mozilla.com/D199933
Glean-based Use Counter metrics are cheaper and work as well,
so let's use them instead.
Though we do have metric name strings available in a string table in GleanJSMetrics.cpp,
access is through metric_entry_t which has information not available to usecounters.py.
So for now we return char* literals from the use counter increment fns.
Differential Revision: https://phabricator.services.mozilla.com/D199933
In DEBUG mode, add a settable string to WorkerRefs. Record what we're doing in
the XHR request worker, and log the status if we seem to be hanging (see
WorkerPrivate::DumpCrashInformation).
Differential Revision: https://phabricator.services.mozilla.com/D190054
After this patch, the Worker can be GCed while it is idle for events.
I want to point out the difference from the BusyCount implementation.
Compared to the BusyCount implementation, BusyCount implementation allows the Worker to be GCed during WorkerRunnable execution iff the WorkeRunnable does not modify BusyCount.
Differential Revision: https://phabricator.services.mozilla.com/D194333