diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index d1b4ec436280..ba31bdccbbaa 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -1416,11 +1416,12 @@ HelperThread::handleWasmWorkload(AutoLockHelperThreadState& locked) currentTask.emplace(HelperThreadState().wasmWorklist(locked).popCopy()); bool success = false; + UniqueChars error; wasm::CompileTask* task = wasmTask(); { AutoUnlockHelperThreadState unlock(locked); - success = wasm::CompileFunction(task); + success = wasm::CompileFunction(task, &error); } // On success, try to move work to the finished list. @@ -1428,8 +1429,10 @@ HelperThread::handleWasmWorkload(AutoLockHelperThreadState& locked) success = HelperThreadState().wasmFinishedList(locked).append(task); // On failure, note the failure for harvesting by the parent. - if (!success) + if (!success) { HelperThreadState().noteWasmFailure(locked); + HelperThreadState().setWasmError(locked, Move(error)); + } // Notify the main thread in case it's waiting. HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked); diff --git a/js/src/vm/HelperThreads.h b/js/src/vm/HelperThreads.h index c5f196e8647f..e5ec1aa3ab7a 100644 --- a/js/src/vm/HelperThreads.h +++ b/js/src/vm/HelperThreads.h @@ -220,10 +220,17 @@ class GlobalHelperThreadState numWasmFailedJobs = 0; return n; } + UniqueChars harvestWasmError(const AutoLockHelperThreadState&) { + return Move(firstWasmError); + } void noteWasmFailure(const AutoLockHelperThreadState&) { // Be mindful to signal the main thread after calling this function. numWasmFailedJobs++; } + void setWasmError(const AutoLockHelperThreadState&, UniqueChars error) { + if (!firstWasmError) + firstWasmError = Move(error); + } bool wasmFailed(const AutoLockHelperThreadState&) { return bool(numWasmFailedJobs); } @@ -243,6 +250,11 @@ class GlobalHelperThreadState * Their parent is logically the main thread, and this number serves for harvesting. */ 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: JSScript* finishScriptParseTask(JSContext* cx, void* token); @@ -404,7 +416,7 @@ namespace wasm { // Performs MIR optimization and LIR generation on one or several functions. MOZ_MUST_USE bool -CompileFunction(CompileTask* task); +CompileFunction(CompileTask* task, UniqueChars* error); } diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index 0f0860889bbc..315945784a19 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -1724,6 +1724,7 @@ class MOZ_STACK_CLASS ModuleValidator arrayViews_(cx), atomicsPresent_(false), simdPresent_(false), + mg_(nullptr), errorString_(nullptr), errorOffset_(UINT32_MAX), errorOverRecursed_(false) diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index 90ca84eccae3..b868ecda85bc 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -7894,13 +7894,13 @@ js::wasm::BaselineCanCompile(const FunctionGenerator* fg) } bool -js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit) +js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error) { MOZ_ASSERT(unit->mode() == CompileMode::Baseline); const FuncBytes& func = unit->func(); - Decoder d(func.bytes()); + Decoder d(func.bytes(), error); // Build the local types vector. diff --git a/js/src/wasm/WasmBaselineCompile.h b/js/src/wasm/WasmBaselineCompile.h index 3fc43ba9606a..7d0ac0d13ef4 100644 --- a/js/src/wasm/WasmBaselineCompile.h +++ b/js/src/wasm/WasmBaselineCompile.h @@ -19,6 +19,8 @@ #ifndef asmjs_wasm_baseline_compile_h #define asmjs_wasm_baseline_compile_h +#include "wasm/WasmTypes.h" + namespace js { namespace wasm { @@ -40,7 +42,7 @@ BaselineCanCompile(const FunctionGenerator* fg); // Generate adequate code quickly. bool -BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit); +BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error); } // namespace wasm } // namespace js diff --git a/js/src/wasm/WasmCompile.cpp b/js/src/wasm/WasmCompile.cpp index 73a385db1c8e..4eefedf69681 100644 --- a/js/src/wasm/WasmCompile.cpp +++ b/js/src/wasm/WasmCompile.cpp @@ -117,7 +117,7 @@ wasm::Compile(const ShareableBytes& bytecode, const CompileArgs& args, UniqueCha if (!DecodeModuleEnvironment(d, env.get())) return nullptr; - ModuleGenerator mg; + ModuleGenerator mg(error); if (!mg.init(Move(env), args)) return nullptr; diff --git a/js/src/wasm/WasmGenerator.cpp b/js/src/wasm/WasmGenerator.cpp index a89f9aa4a29e..ded277b8368b 100644 --- a/js/src/wasm/WasmGenerator.cpp +++ b/js/src/wasm/WasmGenerator.cpp @@ -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 uint32_t BAD_CODE_RANGE = UINT32_MAX; -ModuleGenerator::ModuleGenerator() +ModuleGenerator::ModuleGenerator(UniqueChars* error) : alwaysBaseline_(false), + error_(error), numSigs_(0), numTables_(0), lifo_(GENERATOR_LIFO_DEFAULT_CHUNK_SIZE), @@ -242,8 +243,13 @@ ModuleGenerator::finishOutstandingTask() while (true) { 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; + } if (!HelperThreadState().wasmFinishedList(lock).empty()) { outstanding_--; @@ -917,7 +923,7 @@ ModuleGenerator::launchBatchCompile() return false; outstanding_++; } else { - if (!CompileFunction(currentTask_)) + if (!CompileFunction(currentTask_, error_)) return false; if (!finishTask(currentTask_)) return false; @@ -1165,7 +1171,7 @@ ModuleGenerator::finish(const ShareableBytes& bytecode) } bool -wasm::CompileFunction(CompileTask* task) +wasm::CompileFunction(CompileTask* task, UniqueChars* error) { TraceLoggerThread* logger = TraceLoggerForCurrentThread(); AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation); @@ -1173,11 +1179,11 @@ wasm::CompileFunction(CompileTask* task) for (FuncCompileUnit& unit : task->units()) { switch (unit.mode()) { case CompileMode::Ion: - if (!IonCompileFunction(task, &unit)) + if (!IonCompileFunction(task, &unit, error)) return false; break; case CompileMode::Baseline: - if (!BaselineCompileFunction(task, &unit)) + if (!BaselineCompileFunction(task, &unit, error)) return false; break; } diff --git a/js/src/wasm/WasmGenerator.h b/js/src/wasm/WasmGenerator.h index daa98a005434..f70d5e63e5f9 100644 --- a/js/src/wasm/WasmGenerator.h +++ b/js/src/wasm/WasmGenerator.h @@ -206,6 +206,7 @@ class MOZ_STACK_CLASS ModuleGenerator // Constant parameters bool alwaysBaseline_; + UniqueChars* error_; // Data that is moved into the result of finish() Assumptions assumptions_; @@ -260,7 +261,7 @@ class MOZ_STACK_CLASS ModuleGenerator MOZ_MUST_USE bool initWasm(); public: - explicit ModuleGenerator(); + explicit ModuleGenerator(UniqueChars* error); ~ModuleGenerator(); MOZ_MUST_USE bool init(UniqueModuleEnvironment env, const CompileArgs& args, diff --git a/js/src/wasm/WasmIonCompile.cpp b/js/src/wasm/WasmIonCompile.cpp index aae314c5d952..d8345d3ee15d 100644 --- a/js/src/wasm/WasmIonCompile.cpp +++ b/js/src/wasm/WasmIonCompile.cpp @@ -3655,14 +3655,14 @@ EmitExpr(FunctionCompiler& f) } bool -wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit) +wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error) { MOZ_ASSERT(unit->mode() == CompileMode::Ion); const FuncBytes& func = unit->func(); const ModuleEnvironment& env = task->env(); - Decoder d(func.bytes()); + Decoder d(func.bytes(), error); // Build the local types vector. diff --git a/js/src/wasm/WasmIonCompile.h b/js/src/wasm/WasmIonCompile.h index a228dbde871d..f2165d9be83f 100644 --- a/js/src/wasm/WasmIonCompile.h +++ b/js/src/wasm/WasmIonCompile.h @@ -21,6 +21,8 @@ #include "mozilla/Attributes.h" +#include "wasm/WasmTypes.h" + namespace js { namespace wasm { @@ -29,7 +31,7 @@ class FuncCompileUnit; // Generates very fast code at the expense of compilation time. MOZ_MUST_USE bool -IonCompileFunction(CompileTask* task, FuncCompileUnit* unit); +IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error); } // namespace wasm } // namespace js