diff options
Diffstat (limited to 'js/src/jsworkers.h')
-rw-r--r-- | js/src/jsworkers.h | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/js/src/jsworkers.h b/js/src/jsworkers.h new file mode 100644 index 0000000..f29aa81 --- /dev/null +++ b/js/src/jsworkers.h @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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/. */ + +/* + * Definitions for managing off-main-thread work using a shared, per runtime + * worklist. Worklist items are engine internal, and are distinct from e.g. + * web workers. + */ + +#ifndef jsworkers_h +#define jsworkers_h + +#include "mozilla/GuardObjects.h" +#include "mozilla/PodOperations.h" + +#include "jscntxt.h" +#include "jslock.h" + +#include "jit/Ion.h" + +namespace js { + +struct AsmJSParallelTask; + +namespace jit { + class IonBuilder; +} + +#if defined(JS_THREADSAFE) && defined(JS_ION) +# define JS_PARALLEL_COMPILATION + +struct WorkerThread; +struct AsmJSParallelTask; + +/* Per-runtime state for off thread work items. */ +class WorkerThreadState +{ + public: + /* Available threads. */ + WorkerThread *threads; + size_t numThreads; + + enum CondVar { + MAIN, + WORKER + }; + + /* Shared worklist for Ion worker threads. */ + js::Vector<jit::IonBuilder*, 0, SystemAllocPolicy> ionWorklist; + + /* Worklist for AsmJS worker threads. */ + js::Vector<AsmJSParallelTask*, 0, SystemAllocPolicy> asmJSWorklist; + + /* + * Finished list for AsmJS worker threads. + * Simultaneous AsmJS compilations all service the same AsmJS module. + * The main thread must pick up finished optimizations and perform codegen. + */ + js::Vector<AsmJSParallelTask*, 0, SystemAllocPolicy> asmJSFinishedList; + + WorkerThreadState() { mozilla::PodZero(this); } + ~WorkerThreadState(); + + bool init(JSRuntime *rt); + + void lock(); + void unlock(); + +# ifdef DEBUG + bool isLocked(); +# endif + + void wait(CondVar which, uint32_t timeoutMillis = 0); + void notify(CondVar which); + void notifyAll(CondVar which); + + bool canStartAsmJSCompile(); + bool canStartIonCompile(); + + uint32_t harvestFailedAsmJSJobs() { + JS_ASSERT(isLocked()); + uint32_t n = numAsmJSFailedJobs; + numAsmJSFailedJobs = 0; + return n; + } + void noteAsmJSFailure(int32_t func) { + // Be mindful to signal the main thread after calling this function. + JS_ASSERT(isLocked()); + if (asmJSFailedFunctionIndex < 0) + asmJSFailedFunctionIndex = func; + numAsmJSFailedJobs++; + } + bool asmJSWorkerFailed() const { + return bool(numAsmJSFailedJobs); + } + void resetAsmJSFailureState() { + numAsmJSFailedJobs = 0; + asmJSFailedFunctionIndex = -1; + } + int32_t maybeGetAsmJSFailedFunctionIndex() const { + return asmJSFailedFunctionIndex; + } + + private: + + /* + * Lock protecting all mutable shared state accessed by helper threads, and + * used by all condition variables. + */ + PRLock *workerLock; + +# ifdef DEBUG + PRThread *lockOwner; +# endif + + /* Condvar to notify the main thread that work has been completed. */ + PRCondVar *mainWakeup; + + /* Condvar to notify helper threads that they may be able to make progress. */ + PRCondVar *helperWakeup; + + /* + * Number of AsmJS workers that encountered failure for the active module. + * Their parent is logically the main thread, and this number serves for harvesting. + */ + uint32_t numAsmJSFailedJobs; + + /* + * Function index |i| in |Module.function(i)| of first failed AsmJS function. + * -1 if no function has failed. + */ + int32_t asmJSFailedFunctionIndex; +}; + +/* Individual helper thread, one allocated per core. */ +struct WorkerThread +{ + JSRuntime *runtime; + + mozilla::Maybe<PerThreadData> threadData; + PRThread *thread; + + /* Indicate to an idle thread that it should finish executing. */ + bool terminate; + + /* Any builder currently being compiled by Ion on this thread. */ + jit::IonBuilder *ionBuilder; + + /* Any AsmJS data currently being optimized by Ion on this thread. */ + AsmJSParallelTask *asmData; + + void destroy(); + + void handleAsmJSWorkload(WorkerThreadState &state); + void handleIonWorkload(WorkerThreadState &state); + + static void ThreadMain(void *arg); + void threadLoop(); +}; + +#endif /* JS_THREADSAFE && JS_ION */ + +inline bool +OffThreadCompilationEnabled(JSContext *cx) +{ +#ifdef JS_PARALLEL_COMPILATION + return jit::js_IonOptions.parallelCompilation + && cx->runtime()->useHelperThreads() + && cx->runtime()->helperThreadCount() != 0; +#else + return false; +#endif +} + +/* Methods for interacting with worker threads. */ + +/* Initialize worker threads unless already initialized. */ +bool +EnsureParallelCompilationInitialized(JSRuntime *rt); + +/* Perform MIR optimization and LIR generation on a single function. */ +bool +StartOffThreadAsmJSCompile(JSContext *cx, AsmJSParallelTask *asmData); + +/* + * Schedule an Ion compilation for a script, given a builder which has been + * generated and read everything needed from the VM state. + */ +bool +StartOffThreadIonCompile(JSContext *cx, jit::IonBuilder *builder); + +/* + * Cancel a scheduled or in progress Ion compilation for script. If script is + * NULL, all compilations for the compartment are cancelled. + */ +void +CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script); + +class AutoLockWorkerThreadState +{ + JSRuntime *rt; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER + + public: + + AutoLockWorkerThreadState(JSRuntime *rt + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : rt(rt) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; +#ifdef JS_PARALLEL_COMPILATION + JS_ASSERT(rt->workerThreadState); + rt->workerThreadState->lock(); +#else + (void)this->rt; +#endif + } + + ~AutoLockWorkerThreadState() + { +#ifdef JS_PARALLEL_COMPILATION + rt->workerThreadState->unlock(); +#endif + } +}; + +class AutoUnlockWorkerThreadState +{ + JSRuntime *rt; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER + + public: + + AutoUnlockWorkerThreadState(JSRuntime *rt + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : rt(rt) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; +#ifdef JS_PARALLEL_COMPILATION + JS_ASSERT(rt->workerThreadState); + rt->workerThreadState->unlock(); +#else + (void)this->rt; +#endif + } + + ~AutoUnlockWorkerThreadState() + { +#ifdef JS_PARALLEL_COMPILATION + rt->workerThreadState->lock(); +#endif + } +}; + +} /* namespace js */ + +#endif /* jsworkers_h */ |