diff options
Diffstat (limited to 'js/src/vm/HelperThreads.h')
-rw-r--r-- | js/src/vm/HelperThreads.h | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/js/src/vm/HelperThreads.h b/js/src/vm/HelperThreads.h new file mode 100644 index 0000000000..7b44a102ea --- /dev/null +++ b/js/src/vm/HelperThreads.h @@ -0,0 +1,292 @@ +/* -*- 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/. */ + +/* + * API for managing off-thread work. + */ + +#ifndef vm_HelperThreads_h +#define vm_HelperThreads_h + +#include "mozilla/Variant.h" + +#include "js/OffThreadScriptCompilation.h" +#include "js/shadow/Zone.h" +#include "js/Transcoding.h" +#include "js/UniquePtr.h" +#include "threading/LockGuard.h" +#include "threading/Mutex.h" +#include "wasm/WasmConstants.h" + +namespace mozilla { +union Utf8Unit; +} + +namespace JS { +class OffThreadToken {}; +class JS_PUBLIC_API ReadOnlyCompileOptions; +class Zone; + +template <typename UnitT> +class SourceText; +} // namespace JS + +namespace js { + +class AutoLockHelperThreadState; +struct PromiseHelperTask; +class SourceCompressionTask; + +namespace frontend { +struct CompilationStencil; +} + +namespace gc { +class GCRuntime; +} + +namespace jit { +class IonCompileTask; +class IonFreeTask; +} // namespace jit + +namespace wasm { +struct CompileTask; +struct CompileTaskState; +struct Tier2GeneratorTask; +using UniqueTier2GeneratorTask = UniquePtr<Tier2GeneratorTask>; +} // namespace wasm + +/* + * Lock protecting all mutable shared state accessed by helper threads, and used + * by all condition variables. + */ +extern Mutex gHelperThreadLock MOZ_UNANNOTATED; + +class MOZ_RAII AutoLockHelperThreadState : public LockGuard<Mutex> { + using Base = LockGuard<Mutex>; + + public: + explicit AutoLockHelperThreadState() : Base(gHelperThreadLock) {} +}; + +class MOZ_RAII AutoUnlockHelperThreadState : public UnlockGuard<Mutex> { + using Base = UnlockGuard<Mutex>; + + public: + explicit AutoUnlockHelperThreadState(AutoLockHelperThreadState& locked) + : Base(locked) {} +}; + +// Create data structures used by helper threads. +bool CreateHelperThreadsState(); + +// Destroy data structures used by helper threads. +void DestroyHelperThreadsState(); + +// Initialize helper threads unless already initialized. +bool EnsureHelperThreadsInitialized(); + +size_t GetHelperThreadCount(); +size_t GetHelperThreadCPUCount(); +size_t GetMaxWasmCompilationThreads(); + +// This allows the JS shell to override GetCPUCount() when passed the +// --thread-count=N option. +bool SetFakeCPUCount(size_t count); + +// Enqueues a wasm compilation task. +bool StartOffThreadWasmCompile(wasm::CompileTask* task, wasm::CompileMode mode); + +// Remove any pending wasm compilation tasks queued with +// StartOffThreadWasmCompile that match the arguments. Return the number +// removed. +size_t RemovePendingWasmCompileTasks(const wasm::CompileTaskState& taskState, + wasm::CompileMode mode, + const AutoLockHelperThreadState& lock); + +// Enqueues a wasm compilation task. +void StartOffThreadWasmTier2Generator(wasm::UniqueTier2GeneratorTask task); + +// Cancel all background Wasm Tier-2 compilations. +void CancelOffThreadWasmTier2Generator(); + +/* + * If helper threads are available, call execute() then dispatchResolve() on the + * given task in a helper thread. If no helper threads are available, the given + * task is executed and resolved synchronously. + * + * This function takes ownership of task unconditionally; if it fails, task is + * deleted. + */ +bool StartOffThreadPromiseHelperTask(JSContext* cx, + UniquePtr<PromiseHelperTask> task); + +/* + * Like the JSContext-accepting version, but only safe to use when helper + * threads are available, so we can be sure we'll never need to fall back on + * synchronous execution. + * + * This function can be called from any thread, but takes ownership of the task + * only on success. On OOM, it is the caller's responsibility to arrange for the + * task to be cleaned up properly. + */ +bool StartOffThreadPromiseHelperTask(PromiseHelperTask* task); + +/* + * Schedule an off-thread Ion compilation for a script, given a task. + */ +bool StartOffThreadIonCompile(jit::IonCompileTask* task, + const AutoLockHelperThreadState& lock); + +/* + * Schedule deletion of Ion compilation data. + */ +bool StartOffThreadIonFree(jit::IonCompileTask* task, + const AutoLockHelperThreadState& lock); + +void FinishOffThreadIonCompile(jit::IonCompileTask* task, + const AutoLockHelperThreadState& lock); + +struct ZonesInState { + JSRuntime* runtime; + JS::shadow::Zone::GCState state; +}; + +using CompilationSelector = mozilla::Variant<JSScript*, JS::Realm*, JS::Zone*, + ZonesInState, JSRuntime*>; + +/* + * Cancel scheduled or in progress Ion compilations. + */ +void CancelOffThreadIonCompile(const CompilationSelector& selector); + +inline void CancelOffThreadIonCompile(JSScript* script) { + CancelOffThreadIonCompile(CompilationSelector(script)); +} + +inline void CancelOffThreadIonCompile(JS::Realm* realm) { + CancelOffThreadIonCompile(CompilationSelector(realm)); +} + +inline void CancelOffThreadIonCompile(JS::Zone* zone) { + CancelOffThreadIonCompile(CompilationSelector(zone)); +} + +inline void CancelOffThreadIonCompile(JSRuntime* runtime, + JS::shadow::Zone::GCState state) { + CancelOffThreadIonCompile(CompilationSelector(ZonesInState{runtime, state})); +} + +inline void CancelOffThreadIonCompile(JSRuntime* runtime) { + CancelOffThreadIonCompile(CompilationSelector(runtime)); +} + +#ifdef DEBUG +bool HasOffThreadIonCompile(JS::Realm* realm); +#endif + +// True iff the current thread is a ParseTask or a DelazifyTask. +bool CurrentThreadIsParseThread(); + +/* + * Cancel all scheduled, in progress or finished parses for runtime. + * + * Parse tasks which have completed but for which JS::FinishOffThreadScript (or + * equivalent) has not been called are removed from the system. This is only + * safe to do during shutdown, or if you know that the main thread isn't waiting + * for tasks to complete. + */ +void CancelOffThreadParses(JSRuntime* runtime); + +/* + * Cancel all scheduled or in progress eager delazification phases for a + * runtime. + */ +void CancelOffThreadDelazify(JSRuntime* runtime); + +/* + * Wait for all delazification to complete. + */ +void WaitForAllDelazifyTasks(JSRuntime* rt); + +/* + * Start a parse/emit cycle for a stream of source. The characters must stay + * alive until the compilation finishes. + */ + +JS::OffThreadToken* StartOffThreadCompileToStencil( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText<char16_t>& srcBuf, JS::OffThreadCompileCallback callback, + void* callbackData); +JS::OffThreadToken* StartOffThreadCompileToStencil( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText<mozilla::Utf8Unit>& srcBuf, + JS::OffThreadCompileCallback callback, void* callbackData); + +JS::OffThreadToken* StartOffThreadCompileModuleToStencil( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText<char16_t>& srcBuf, JS::OffThreadCompileCallback callback, + void* callbackData); +JS::OffThreadToken* StartOffThreadCompileModuleToStencil( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText<mozilla::Utf8Unit>& srcBuf, + JS::OffThreadCompileCallback callback, void* callbackData); + +JS::OffThreadToken* StartOffThreadDecodeStencil( + JSContext* cx, const JS::DecodeOptions& options, + const JS::TranscodeRange& range, JS::OffThreadCompileCallback callback, + void* callbackData); + +JS::OffThreadToken* StartOffThreadDecodeMultiStencils( + JSContext* cx, const JS::DecodeOptions& options, + JS::TranscodeSources& sources, JS::OffThreadCompileCallback callback, + void* callbackData); + +// Start off-thread delazification task, to race the delazification of inner +// functions. +void StartOffThreadDelazification(JSContext* cx, + const JS::ReadOnlyCompileOptions& options, + const frontend::CompilationStencil& stencil); + +// Drain the task queues and wait for all helper threads to finish running. +// +// Note that helper threads are shared between runtimes and it's possible that +// another runtime could saturate the helper thread system and cause this to +// never return. +void WaitForAllHelperThreads(); +void WaitForAllHelperThreads(AutoLockHelperThreadState& lock); + +// Enqueue a compression job to be processed later. These are started at the +// start of the major GC after the next one. +bool EnqueueOffThreadCompression(JSContext* cx, + UniquePtr<SourceCompressionTask> task); + +// Start handling any compression tasks for this runtime. Called at the start of +// major GC. +void StartHandlingCompressionsOnGC(JSRuntime* rt); + +// Cancel all scheduled, in progress, or finished compression tasks for +// runtime. +void CancelOffThreadCompressions(JSRuntime* runtime); + +void AttachFinishedCompressions(JSRuntime* runtime, + AutoLockHelperThreadState& lock); + +// Sweep pending tasks that are holding onto should-be-dead ScriptSources. +void SweepPendingCompressions(AutoLockHelperThreadState& lock); + +// Run all pending source compression tasks synchronously, for testing purposes +void RunPendingSourceCompressions(JSRuntime* runtime); + +// False if the off-thread source compression mechanism isn't being used. This +// happens on low core count machines where we are concerned about blocking +// main-thread execution. +bool IsOffThreadSourceCompressionEnabled(); + +} // namespace js + +#endif /* vm_HelperThreads_h */ |