diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index fb5fd5f018f6..ef50da616753 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -2302,6 +2302,13 @@ GlobalHelperThreadState::trace(JSTracer* trc) parseTask->trace(trc); } +/* static */ void +HelperThread::WakeupAll() +{ + AutoLockHelperThreadState lock; + HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER, lock); +} + void JSContext::setHelperThread(HelperThread* thread) { @@ -2395,6 +2402,19 @@ HelperThread::threadLoop() const TaskSpec* task = findHighestPriorityTask(lock); if (!task) { + if (mozilla::recordreplay::IsRecordingOrReplaying()) { + // Unlock the helper thread state lock before potentially + // blocking while the main thread waits for all threads to + // become idle. Otherwise we would need to see if we need to + // block at every point where a helper thread acquires the + // helper thread state lock. + { + AutoUnlockHelperThreadState unlock(lock); + mozilla::recordreplay::MaybeWaitForCheckpointSave(); + } + mozilla::recordreplay::NotifyUnrecordedWait(WakeupAll); + } + HelperThreadState().wait(lock, GlobalHelperThreadState::PRODUCER); continue; } diff --git a/js/src/vm/HelperThreads.h b/js/src/vm/HelperThreads.h index df19fd399fee..426ee2cbd3a3 100644 --- a/js/src/vm/HelperThreads.h +++ b/js/src/vm/HelperThreads.h @@ -414,6 +414,8 @@ struct HelperThread static void ThreadMain(void* arg); void threadLoop(); + static void WakeupAll(); + void ensureRegisteredWithProfiler(); void unregisterWithProfilerIfNeeded();