diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/src/gc/ParallelMarking.h | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/gc/ParallelMarking.h')
-rw-r--r-- | js/src/gc/ParallelMarking.h | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/js/src/gc/ParallelMarking.h b/js/src/gc/ParallelMarking.h new file mode 100644 index 0000000000..4c39328de1 --- /dev/null +++ b/js/src/gc/ParallelMarking.h @@ -0,0 +1,125 @@ +/* -*- 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/. */ + +#ifndef gc_ParallelMarking_h +#define gc_ParallelMarking_h + +#include "mozilla/Atomics.h" +#include "mozilla/DoublyLinkedList.h" +#include "mozilla/TimeStamp.h" + +#include "gc/GCMarker.h" +#include "gc/GCParallelTask.h" +#include "js/HeapAPI.h" +#include "js/SliceBudget.h" +#include "threading/ConditionVariable.h" +#include "threading/ProtectedData.h" + +namespace js { + +class AutoLockHelperThreadState; + +namespace gc { + +class ParallelMarkTask; + +// Per-runtime parallel marking state. +// +// This class is used on the main thread and coordinates parallel marking using +// several helper threads running ParallelMarkTasks. +// +// This uses a work-requesting approach. Threads mark until they run out of +// work and then add themselves to a list of waiting tasks and block. Running +// tasks with enough work may donate work to a waiting task and resume it. +class MOZ_STACK_CLASS ParallelMarker { + public: + explicit ParallelMarker(GCRuntime* gc); + + bool mark(SliceBudget& sliceBudget); + + using AtomicCount = mozilla::Atomic<uint32_t, mozilla::Relaxed>; + AtomicCount& waitingTaskCountRef() { return waitingTaskCount; } + bool hasWaitingTasks() { return waitingTaskCount != 0; } + void donateWorkFrom(GCMarker* src); + + private: + bool markOneColor(MarkColor color, SliceBudget& sliceBudget); + + bool hasWork(MarkColor color) const; + + void addTask(ParallelMarkTask* task, const AutoLockHelperThreadState& lock); + + void addTaskToWaitingList(ParallelMarkTask* task, + const AutoLockHelperThreadState& lock); +#ifdef DEBUG + bool isTaskInWaitingList(const ParallelMarkTask* task, + const AutoLockHelperThreadState& lock) const; +#endif + + bool hasActiveTasks(const AutoLockHelperThreadState& lock) const { + return activeTasks; + } + void incActiveTasks(ParallelMarkTask* task, + const AutoLockHelperThreadState& lock); + void decActiveTasks(ParallelMarkTask* task, + const AutoLockHelperThreadState& lock); + + size_t workerCount() const; + + friend class ParallelMarkTask; + + GCRuntime* const gc; + + using ParallelMarkTaskList = mozilla::DoublyLinkedList<ParallelMarkTask>; + HelperThreadLockData<ParallelMarkTaskList> waitingTasks; + AtomicCount waitingTaskCount; + + HelperThreadLockData<size_t> activeTasks; +}; + +// A helper thread task that performs parallel marking. +class alignas(TypicalCacheLineSize) ParallelMarkTask + : public GCParallelTask, + public mozilla::DoublyLinkedListElement<ParallelMarkTask> { + public: + friend class ParallelMarker; + + ParallelMarkTask(ParallelMarker* pm, GCMarker* marker, MarkColor color, + const SliceBudget& budget); + ~ParallelMarkTask(); + + void run(AutoLockHelperThreadState& lock) override; + + void recordDuration() override; + + private: + bool tryMarking(AutoLockHelperThreadState& lock); + bool requestWork(AutoLockHelperThreadState& lock); + + void waitUntilResumed(AutoLockHelperThreadState& lock); + void resume(); + void resumeOnFinish(const AutoLockHelperThreadState& lock); + + bool hasWork() const; + + // The following fields are only accessed by the marker thread: + ParallelMarker* const pm; + GCMarker* const marker; + AutoSetMarkColor color; + SliceBudget budget; + ConditionVariable resumed; + + HelperThreadLockData<bool> isWaiting; + + // Length of time this task spent blocked waiting for work. + MainThreadOrGCTaskData<mozilla::TimeDuration> markTime; + MainThreadOrGCTaskData<mozilla::TimeDuration> waitTime; +}; + +} // namespace gc +} // namespace js + +#endif /* gc_ParallelMarking_h */ |