mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 922096 - OdinMonkey: prevent multiple concurrent parallel asm.js compilations (r=sstangl)
This commit is contained in:
parent
548b3fc608
commit
5530c7cf8e
26
js/src/jit-test/tests/asm.js/testParallelCompile.js
Normal file
26
js/src/jit-test/tests/asm.js/testParallelCompile.js
Normal file
@ -0,0 +1,26 @@
|
||||
load(libdir + "asm.js");
|
||||
|
||||
if (!isAsmJSCompilationAvailable())
|
||||
quit();
|
||||
|
||||
var module = "'use asm';\n";
|
||||
for (var i = 0; i < 100; i++) {
|
||||
module += "function f" + i + "(i) {\n";
|
||||
module += " i=i|0; var j=0; j=(i+1)|0; i=(j-4)|0; i=(i+j)|0; return i|0\n";
|
||||
module += "}\n";
|
||||
}
|
||||
module += "return f0";
|
||||
var script = "(function() {\n" + module + "})";
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
try {
|
||||
offThreadCompileScript(script);
|
||||
var f = new Function(module);
|
||||
var g = runOffThreadScript();
|
||||
assertEq(isAsmJSModule(f), true);
|
||||
assertEq(isAsmJSModule(g), true);
|
||||
} catch (e) {
|
||||
// ignore spurious error when offThreadCompileScript can't run in
|
||||
// parallel
|
||||
}
|
||||
}
|
@ -5074,6 +5074,29 @@ CheckFunctionsSequential(ModuleCompiler &m)
|
||||
|
||||
#ifdef JS_WORKER_THREADS
|
||||
|
||||
// Currently, only one asm.js parallel compilation is allowed at a time.
|
||||
// This RAII class attempts to claim this parallel compilation using atomic ops
|
||||
// on rt->workerThreadState->asmJSCompilationInProgress.
|
||||
class ParallelCompilationGuard
|
||||
{
|
||||
WorkerThreadState *parallelState_;
|
||||
public:
|
||||
ParallelCompilationGuard() : parallelState_(NULL) {}
|
||||
~ParallelCompilationGuard() {
|
||||
if (parallelState_) {
|
||||
JS_ASSERT(parallelState_->asmJSCompilationInProgress == true);
|
||||
parallelState_->asmJSCompilationInProgress = false;
|
||||
}
|
||||
}
|
||||
bool claim(WorkerThreadState *state) {
|
||||
JS_ASSERT(!parallelState_);
|
||||
if (!state->asmJSCompilationInProgress.compareExchange(false, true))
|
||||
return false;
|
||||
parallelState_ = state;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static bool
|
||||
ParallelCompilationEnabled(ExclusiveContext *cx)
|
||||
{
|
||||
@ -5254,6 +5277,15 @@ static const size_t LIFO_ALLOC_PARALLEL_CHUNK_SIZE = 1 << 12;
|
||||
static bool
|
||||
CheckFunctionsParallel(ModuleCompiler &m)
|
||||
{
|
||||
// If parallel compilation isn't enabled (not enough cores, disabled by
|
||||
// pref, etc) or another thread is currently compiling asm.js in parallel,
|
||||
// fall back to sequential compilation. (We could lift the latter
|
||||
// constraint by hoisting asmJS* state out of WorkerThreadState so multiple
|
||||
// concurrent asm.js parallel compilations don't race.)
|
||||
ParallelCompilationGuard g;
|
||||
if (!ParallelCompilationEnabled(m.cx()) || !g.claim(m.cx()->workerThreadState()))
|
||||
return CheckFunctionsSequential(m);
|
||||
|
||||
// Saturate all worker threads plus the main thread.
|
||||
WorkerThreadState &state = *m.cx()->workerThreadState();
|
||||
size_t numParallelJobs = state.numThreads + 1;
|
||||
@ -6393,13 +6425,8 @@ CheckModule(ExclusiveContext *cx, AsmJSParser &parser, ParseNode *stmtList,
|
||||
return false;
|
||||
|
||||
#ifdef JS_WORKER_THREADS
|
||||
if (ParallelCompilationEnabled(cx)) {
|
||||
if (!CheckFunctionsParallel(m))
|
||||
return false;
|
||||
} else {
|
||||
if (!CheckFunctionsSequential(m))
|
||||
return false;
|
||||
}
|
||||
if (!CheckFunctionsParallel(m))
|
||||
return false;
|
||||
#else
|
||||
if (!CheckFunctionsSequential(m))
|
||||
return false;
|
||||
|
@ -71,6 +71,12 @@ class WorkerThreadState
|
||||
*/
|
||||
Vector<AsmJSParallelTask*, 0, SystemAllocPolicy> asmJSFinishedList;
|
||||
|
||||
/*
|
||||
* For now, only allow a single parallel asm.js compilation to happen at a
|
||||
* time. This avoids race conditions on asmJSWorklist/asmJSFinishedList/etc.
|
||||
*/
|
||||
mozilla::Atomic<uint32_t> asmJSCompilationInProgress;
|
||||
|
||||
/* Shared worklist for parsing/emitting scripts on worker threads. */
|
||||
Vector<ParseTask*, 0, SystemAllocPolicy> parseWorklist, parseFinishedList;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user