mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
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:
parent
839ad41abf
commit
ce404f2d14
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user