Bug 1329018 - Part 1: Wasm: Add plumbing for compile threads to report validation errors. r=luke

MozReview-Commit-ID: 2cS7skk5tdk

--HG--
extra : rebase_source : 24dd758202e5b15efc9a0bbb5aa7f115cee25683
This commit is contained in:
David Major 2017-01-06 17:15:23 -06:00
parent 839ad41abf
commit ce404f2d14
10 changed files with 44 additions and 17 deletions

View File

@ -1416,11 +1416,12 @@ HelperThread::handleWasmWorkload(AutoLockHelperThreadState& locked)
currentTask.emplace(HelperThreadState().wasmWorklist(locked).popCopy()); currentTask.emplace(HelperThreadState().wasmWorklist(locked).popCopy());
bool success = false; bool success = false;
UniqueChars error;
wasm::CompileTask* task = wasmTask(); wasm::CompileTask* task = wasmTask();
{ {
AutoUnlockHelperThreadState unlock(locked); AutoUnlockHelperThreadState unlock(locked);
success = wasm::CompileFunction(task); success = wasm::CompileFunction(task, &error);
} }
// On success, try to move work to the finished list. // On success, try to move work to the finished list.
@ -1428,8 +1429,10 @@ HelperThread::handleWasmWorkload(AutoLockHelperThreadState& locked)
success = HelperThreadState().wasmFinishedList(locked).append(task); success = HelperThreadState().wasmFinishedList(locked).append(task);
// On failure, note the failure for harvesting by the parent. // On failure, note the failure for harvesting by the parent.
if (!success) if (!success) {
HelperThreadState().noteWasmFailure(locked); HelperThreadState().noteWasmFailure(locked);
HelperThreadState().setWasmError(locked, Move(error));
}
// Notify the main thread in case it's waiting. // Notify the main thread in case it's waiting.
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked); HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);

View File

@ -220,10 +220,17 @@ class GlobalHelperThreadState
numWasmFailedJobs = 0; numWasmFailedJobs = 0;
return n; return n;
} }
UniqueChars harvestWasmError(const AutoLockHelperThreadState&) {
return Move(firstWasmError);
}
void noteWasmFailure(const AutoLockHelperThreadState&) { void noteWasmFailure(const AutoLockHelperThreadState&) {
// Be mindful to signal the main thread after calling this function. // Be mindful to signal the main thread after calling this function.
numWasmFailedJobs++; numWasmFailedJobs++;
} }
void setWasmError(const AutoLockHelperThreadState&, UniqueChars error) {
if (!firstWasmError)
firstWasmError = Move(error);
}
bool wasmFailed(const AutoLockHelperThreadState&) { bool wasmFailed(const AutoLockHelperThreadState&) {
return bool(numWasmFailedJobs); return bool(numWasmFailedJobs);
} }
@ -243,6 +250,11 @@ class GlobalHelperThreadState
* Their parent is logically the main thread, and this number serves for harvesting. * Their parent is logically the main thread, and this number serves for harvesting.
*/ */
uint32_t numWasmFailedJobs; uint32_t numWasmFailedJobs;
/*
* Error string from wasm validation. Arbitrarily choose to keep the first one that gets
* reported. Nondeterministic if multiple threads have errors.
*/
UniqueChars firstWasmError;
public: public:
JSScript* finishScriptParseTask(JSContext* cx, void* token); JSScript* finishScriptParseTask(JSContext* cx, void* token);
@ -404,7 +416,7 @@ namespace wasm {
// Performs MIR optimization and LIR generation on one or several functions. // Performs MIR optimization and LIR generation on one or several functions.
MOZ_MUST_USE bool MOZ_MUST_USE bool
CompileFunction(CompileTask* task); CompileFunction(CompileTask* task, UniqueChars* error);
} }

View File

@ -1724,6 +1724,7 @@ class MOZ_STACK_CLASS ModuleValidator
arrayViews_(cx), arrayViews_(cx),
atomicsPresent_(false), atomicsPresent_(false),
simdPresent_(false), simdPresent_(false),
mg_(nullptr),
errorString_(nullptr), errorString_(nullptr),
errorOffset_(UINT32_MAX), errorOffset_(UINT32_MAX),
errorOverRecursed_(false) errorOverRecursed_(false)

View File

@ -7894,13 +7894,13 @@ js::wasm::BaselineCanCompile(const FunctionGenerator* fg)
} }
bool bool
js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit) js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error)
{ {
MOZ_ASSERT(unit->mode() == CompileMode::Baseline); MOZ_ASSERT(unit->mode() == CompileMode::Baseline);
const FuncBytes& func = unit->func(); const FuncBytes& func = unit->func();
Decoder d(func.bytes()); Decoder d(func.bytes(), error);
// Build the local types vector. // Build the local types vector.

View File

@ -19,6 +19,8 @@
#ifndef asmjs_wasm_baseline_compile_h #ifndef asmjs_wasm_baseline_compile_h
#define asmjs_wasm_baseline_compile_h #define asmjs_wasm_baseline_compile_h
#include "wasm/WasmTypes.h"
namespace js { namespace js {
namespace wasm { namespace wasm {
@ -40,7 +42,7 @@ BaselineCanCompile(const FunctionGenerator* fg);
// Generate adequate code quickly. // Generate adequate code quickly.
bool bool
BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit); BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error);
} // namespace wasm } // namespace wasm
} // namespace js } // namespace js

View File

@ -117,7 +117,7 @@ wasm::Compile(const ShareableBytes& bytecode, const CompileArgs& args, UniqueCha
if (!DecodeModuleEnvironment(d, env.get())) if (!DecodeModuleEnvironment(d, env.get()))
return nullptr; return nullptr;
ModuleGenerator mg; ModuleGenerator mg(error);
if (!mg.init(Move(env), args)) if (!mg.init(Move(env), args))
return nullptr; return nullptr;

View File

@ -44,8 +44,9 @@ static const unsigned GENERATOR_LIFO_DEFAULT_CHUNK_SIZE = 4 * 1024;
static const unsigned COMPILATION_LIFO_DEFAULT_CHUNK_SIZE = 64 * 1024; static const unsigned COMPILATION_LIFO_DEFAULT_CHUNK_SIZE = 64 * 1024;
static const uint32_t BAD_CODE_RANGE = UINT32_MAX; static const uint32_t BAD_CODE_RANGE = UINT32_MAX;
ModuleGenerator::ModuleGenerator() ModuleGenerator::ModuleGenerator(UniqueChars* error)
: alwaysBaseline_(false), : alwaysBaseline_(false),
error_(error),
numSigs_(0), numSigs_(0),
numTables_(0), numTables_(0),
lifo_(GENERATOR_LIFO_DEFAULT_CHUNK_SIZE), lifo_(GENERATOR_LIFO_DEFAULT_CHUNK_SIZE),
@ -242,8 +243,13 @@ ModuleGenerator::finishOutstandingTask()
while (true) { while (true) {
MOZ_ASSERT(outstanding_ > 0); MOZ_ASSERT(outstanding_ > 0);
if (HelperThreadState().wasmFailed(lock)) if (HelperThreadState().wasmFailed(lock)) {
if (error_) {
MOZ_ASSERT(!*error_, "Should have stopped earlier");
*error_ = Move(HelperThreadState().harvestWasmError(lock));
}
return false; return false;
}
if (!HelperThreadState().wasmFinishedList(lock).empty()) { if (!HelperThreadState().wasmFinishedList(lock).empty()) {
outstanding_--; outstanding_--;
@ -917,7 +923,7 @@ ModuleGenerator::launchBatchCompile()
return false; return false;
outstanding_++; outstanding_++;
} else { } else {
if (!CompileFunction(currentTask_)) if (!CompileFunction(currentTask_, error_))
return false; return false;
if (!finishTask(currentTask_)) if (!finishTask(currentTask_))
return false; return false;
@ -1165,7 +1171,7 @@ ModuleGenerator::finish(const ShareableBytes& bytecode)
} }
bool bool
wasm::CompileFunction(CompileTask* task) wasm::CompileFunction(CompileTask* task, UniqueChars* error)
{ {
TraceLoggerThread* logger = TraceLoggerForCurrentThread(); TraceLoggerThread* logger = TraceLoggerForCurrentThread();
AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation); AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation);
@ -1173,11 +1179,11 @@ wasm::CompileFunction(CompileTask* task)
for (FuncCompileUnit& unit : task->units()) { for (FuncCompileUnit& unit : task->units()) {
switch (unit.mode()) { switch (unit.mode()) {
case CompileMode::Ion: case CompileMode::Ion:
if (!IonCompileFunction(task, &unit)) if (!IonCompileFunction(task, &unit, error))
return false; return false;
break; break;
case CompileMode::Baseline: case CompileMode::Baseline:
if (!BaselineCompileFunction(task, &unit)) if (!BaselineCompileFunction(task, &unit, error))
return false; return false;
break; break;
} }

View File

@ -206,6 +206,7 @@ class MOZ_STACK_CLASS ModuleGenerator
// Constant parameters // Constant parameters
bool alwaysBaseline_; bool alwaysBaseline_;
UniqueChars* error_;
// Data that is moved into the result of finish() // Data that is moved into the result of finish()
Assumptions assumptions_; Assumptions assumptions_;
@ -260,7 +261,7 @@ class MOZ_STACK_CLASS ModuleGenerator
MOZ_MUST_USE bool initWasm(); MOZ_MUST_USE bool initWasm();
public: public:
explicit ModuleGenerator(); explicit ModuleGenerator(UniqueChars* error);
~ModuleGenerator(); ~ModuleGenerator();
MOZ_MUST_USE bool init(UniqueModuleEnvironment env, const CompileArgs& args, MOZ_MUST_USE bool init(UniqueModuleEnvironment env, const CompileArgs& args,

View File

@ -3655,14 +3655,14 @@ EmitExpr(FunctionCompiler& f)
} }
bool bool
wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit) wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error)
{ {
MOZ_ASSERT(unit->mode() == CompileMode::Ion); MOZ_ASSERT(unit->mode() == CompileMode::Ion);
const FuncBytes& func = unit->func(); const FuncBytes& func = unit->func();
const ModuleEnvironment& env = task->env(); const ModuleEnvironment& env = task->env();
Decoder d(func.bytes()); Decoder d(func.bytes(), error);
// Build the local types vector. // Build the local types vector.

View File

@ -21,6 +21,8 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "wasm/WasmTypes.h"
namespace js { namespace js {
namespace wasm { namespace wasm {
@ -29,7 +31,7 @@ class FuncCompileUnit;
// Generates very fast code at the expense of compilation time. // Generates very fast code at the expense of compilation time.
MOZ_MUST_USE bool MOZ_MUST_USE bool
IonCompileFunction(CompileTask* task, FuncCompileUnit* unit); IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error);
} // namespace wasm } // namespace wasm
} // namespace js } // namespace js