Commit eb1d2d70 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Make error messages deterministic

Compilation only stores whether an error has been found, but not the
exact error or it's location. This is generated by running a validation
pass once all wire bytes have been received.
This unifies error messages by removing one more location where we
generate compilation error messages, and makes it deterministic because
a) we always report the error in the first failing function, and
b) if names are present, the error message will always contain the
   function name.

R=titzer@chromium.org

Bug: chromium:926311, v8:8814
Change-Id: I79551b8bb73dcee503484de343a3ada60a6add4f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1521112
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60242}
parent e3aad1c8
...@@ -6020,8 +6020,7 @@ TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default; ...@@ -6020,8 +6020,7 @@ TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default;
bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction( bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
wasm::CompilationEnv* env, const wasm::FunctionBody& func_body, wasm::CompilationEnv* env, const wasm::FunctionBody& func_body,
wasm::WasmFeatures* detected, double* decode_ms, MachineGraph* mcgraph, wasm::WasmFeatures* detected, double* decode_ms, MachineGraph* mcgraph,
NodeOriginTable* node_origins, SourcePositionTable* source_positions, NodeOriginTable* node_origins, SourcePositionTable* source_positions) {
wasm::WasmError* error_out) {
base::ElapsedTimer decode_timer; base::ElapsedTimer decode_timer;
if (FLAG_trace_wasm_decode_time) { if (FLAG_trace_wasm_decode_time) {
decode_timer.Start(); decode_timer.Start();
...@@ -6039,7 +6038,6 @@ bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction( ...@@ -6039,7 +6038,6 @@ bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
<< graph_construction_result.error().message() << graph_construction_result.error().message()
<< std::endl; << std::endl;
} }
*error_out = graph_construction_result.error();
return false; return false;
} }
...@@ -6111,11 +6109,9 @@ wasm::WasmCompilationResult TurbofanWasmCompilationUnit::ExecuteCompilation( ...@@ -6111,11 +6109,9 @@ wasm::WasmCompilationResult TurbofanWasmCompilationUnit::ExecuteCompilation(
: nullptr; : nullptr;
SourcePositionTable* source_positions = SourcePositionTable* source_positions =
new (mcgraph->zone()) SourcePositionTable(mcgraph->graph()); new (mcgraph->zone()) SourcePositionTable(mcgraph->graph());
wasm::WasmError error;
if (!BuildGraphForWasmFunction(env, func_body, detected, &decode_ms, mcgraph, if (!BuildGraphForWasmFunction(env, func_body, detected, &decode_ms, mcgraph,
node_origins, source_positions, &error)) { node_origins, source_positions)) {
DCHECK(!error.empty()); return wasm::WasmCompilationResult{};
return wasm::WasmCompilationResult{std::move(error)};
} }
if (node_origins) { if (node_origins) {
...@@ -6161,9 +6157,7 @@ wasm::WasmCompilationResult InterpreterCompilationUnit::ExecuteCompilation( ...@@ -6161,9 +6157,7 @@ wasm::WasmCompilationResult InterpreterCompilationUnit::ExecuteCompilation(
wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::EmptyInterface> decoder( wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::EmptyInterface> decoder(
&zone, module, env->enabled_features, detected, func_body); &zone, module, env->enabled_features, detected, func_body);
decoder.Decode(); decoder.Decode();
if (decoder.failed()) { if (decoder.failed()) return wasm::WasmCompilationResult{};
return wasm::WasmCompilationResult{decoder.error()};
}
wasm::WasmCompilationResult result = CompileWasmInterpreterEntry( wasm::WasmCompilationResult result = CompileWasmInterpreterEntry(
wasm_unit_->wasm_engine_, env->enabled_features, wasm_unit_->func_index_, wasm_unit_->wasm_engine_, env->enabled_features, wasm_unit_->func_index_,
......
...@@ -55,8 +55,7 @@ class TurbofanWasmCompilationUnit { ...@@ -55,8 +55,7 @@ class TurbofanWasmCompilationUnit {
wasm::WasmFeatures* detected, wasm::WasmFeatures* detected,
double* decode_ms, MachineGraph* mcgraph, double* decode_ms, MachineGraph* mcgraph,
NodeOriginTable* node_origins, NodeOriginTable* node_origins,
SourcePositionTable* source_positions, SourcePositionTable* source_positions);
wasm::WasmError* error_out);
wasm::WasmCompilationResult ExecuteCompilation(wasm::CompilationEnv*, wasm::WasmCompilationResult ExecuteCompilation(wasm::CompilationEnv*,
const wasm::FunctionBody&, const wasm::FunctionBody&,
......
...@@ -2004,12 +2004,12 @@ WasmCompilationResult LiftoffCompilationUnit::ExecuteCompilation( ...@@ -2004,12 +2004,12 @@ WasmCompilationResult LiftoffCompilationUnit::ExecuteCompilation(
LiftoffCompiler* compiler = &decoder.interface(); LiftoffCompiler* compiler = &decoder.interface();
if (decoder.failed()) { if (decoder.failed()) {
compiler->OnFirstError(&decoder); compiler->OnFirstError(&decoder);
return WasmCompilationResult{decoder.error()}; return WasmCompilationResult{};
} }
if (!compiler->ok()) { if (!compiler->ok()) {
// Liftoff compilation failed. // Liftoff compilation failed.
counters->liftoff_unsupported_functions()->Increment(); counters->liftoff_unsupported_functions()->Increment();
return WasmCompilationResult{WasmError{0, "Liftoff bailout"}}; return WasmCompilationResult{};
} }
counters->liftoff_compiled_functions()->Increment(); counters->liftoff_compiled_functions()->Increment();
......
...@@ -109,7 +109,7 @@ class CompilationState { ...@@ -109,7 +109,7 @@ class CompilationState {
void AbortCompilation(); void AbortCompilation();
void SetError(uint32_t func_index, const WasmError& error); void SetError();
void SetWireBytesStorage(std::shared_ptr<WireBytesStorage>); void SetWireBytesStorage(std::shared_ptr<WireBytesStorage>);
......
...@@ -195,8 +195,7 @@ WasmCompilationResult WasmCompilationUnit::ExecuteCompilation( ...@@ -195,8 +195,7 @@ WasmCompilationResult WasmCompilationUnit::ExecuteCompilation(
WasmCode* WasmCompilationUnit::Publish(WasmCompilationResult result, WasmCode* WasmCompilationUnit::Publish(WasmCompilationResult result,
NativeModule* native_module) { NativeModule* native_module) {
if (!result.succeeded()) { if (!result.succeeded()) {
native_module->compilation_state()->SetError(func_index_, native_module->compilation_state()->SetError();
std::move(result.error));
return nullptr; return nullptr;
} }
......
...@@ -51,12 +51,7 @@ struct WasmCompilationResult { ...@@ -51,12 +51,7 @@ struct WasmCompilationResult {
public: public:
MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(WasmCompilationResult); MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(WasmCompilationResult);
explicit WasmCompilationResult(WasmError error) : error(std::move(error)) {} bool succeeded() const { return code_desc.buffer != nullptr; }
bool succeeded() const {
DCHECK_EQ(code_desc.buffer != nullptr, error.empty());
return error.empty();
}
operator bool() const { return succeeded(); } operator bool() const { return succeeded(); }
CodeDesc code_desc; CodeDesc code_desc;
...@@ -65,8 +60,6 @@ struct WasmCompilationResult { ...@@ -65,8 +60,6 @@ struct WasmCompilationResult {
uint32_t tagged_parameter_slots = 0; uint32_t tagged_parameter_slots = 0;
OwnedVector<byte> source_positions; OwnedVector<byte> source_positions;
OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions; OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions;
WasmError error;
}; };
class WasmCompilationUnit final { class WasmCompilationUnit final {
......
This diff is collapsed.
...@@ -109,7 +109,8 @@ class AsyncCompileJob { ...@@ -109,7 +109,8 @@ class AsyncCompileJob {
void FinishCompile(); void FinishCompile();
void AsyncCompileFailed(const WasmError&); void DecodeFailed(const WasmError&);
void AsyncCompileFailed();
void AsyncCompileSucceeded(Handle<WasmModuleObject> result); void AsyncCompileSucceeded(Handle<WasmModuleObject> result);
...@@ -154,7 +155,7 @@ class AsyncCompileJob { ...@@ -154,7 +155,7 @@ class AsyncCompileJob {
// Copy of the module wire bytes, moved into the {native_module_} on its // Copy of the module wire bytes, moved into the {native_module_} on its
// creation. // creation.
std::unique_ptr<byte[]> bytes_copy_; std::unique_ptr<byte[]> bytes_copy_;
// Reference to the wire bytes (hold in {bytes_copy_} or as part of // Reference to the wire bytes (held in {bytes_copy_} or as part of
// {native_module_}). // {native_module_}).
ModuleWireBytes wire_bytes_; ModuleWireBytes wire_bytes_;
Handle<Context> native_context_; Handle<Context> native_context_;
......
...@@ -66,7 +66,7 @@ assertPromiseResult(async function badFunctionInTheMiddle() { ...@@ -66,7 +66,7 @@ assertPromiseResult(async function badFunctionInTheMiddle() {
let buffer = builder.toBuffer(); let buffer = builder.toBuffer();
await assertCompileError( await assertCompileError(
buffer, buffer,
'Compiling wasm function \"bad\" failed: ' + 'Compiling function #10:\"bad\" failed: ' +
'expected 1 elements on the stack for fallthru to @1, found 0 @+94'); 'expected 1 elements on the stack for fallthru to @1, found 0 @+94');
}()); }());
......
...@@ -55,7 +55,7 @@ function assertConversionError(bytes, imports, msg) { ...@@ -55,7 +55,7 @@ function assertConversionError(bytes, imports, msg) {
(function TestValidationError() { (function TestValidationError() {
print(arguments.callee.name); print(arguments.callee.name);
let f_error = msg => 'Compiling wasm function "f" failed: ' + msg; let f_error = msg => 'Compiling function #0:"f" failed: ' + msg;
assertCompileError( assertCompileError(
builder().addFunction('f', kSig_i_v).end().toBuffer(), builder().addFunction('f', kSig_i_v).end().toBuffer(),
f_error('function body must end with "end" opcode @+24')); f_error('function body must end with "end" opcode @+24'));
...@@ -176,7 +176,6 @@ function import_error(index, module, func, msg) { ...@@ -176,7 +176,6 @@ function import_error(index, module, func, msg) {
assertConversionError(buffer, {}, kTrapMsgs[kTrapTypeError]); assertConversionError(buffer, {}, kTrapMsgs[kTrapTypeError]);
})(); })();
(function InternalDebugTrace() { (function InternalDebugTrace() {
print(arguments.callee.name); print(arguments.callee.name);
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
...@@ -192,3 +191,18 @@ function import_error(index, module, func, msg) { ...@@ -192,3 +191,18 @@ function import_error(index, module, func, msg) {
}).exports.main; }).exports.main;
main(); main();
})(); })();
(function TestMultipleCorruptFunctions() {
print(arguments.callee.name);
// Generate a module with multiple corrupt functions. The error message must
// be deterministic.
var builder = new WasmModuleBuilder();
var sig = builder.addType(kSig_v_v);
for (let i = 0; i < 10; ++i) {
builder.addFunction('f' + i, sig).addBody([kExprEnd]);
}
assertCompileError(
builder.toBuffer(),
'Compiling function #0:"f0" failed: ' +
'trailing code after function end @+33');
})();
...@@ -51,7 +51,7 @@ checkExports('☺☺mul☺☺', '☺☺mul☺☺', '☺☺add☺☺', '☺☺add ...@@ -51,7 +51,7 @@ checkExports('☺☺mul☺☺', '☺☺mul☺☺', '☺☺add☺☺', '☺☺add
builder.addFunction('three snowmen: ☃☃☃', kSig_i_v).addBody([]).exportFunc(); builder.addFunction('three snowmen: ☃☃☃', kSig_i_v).addBody([]).exportFunc();
assertThrows( assertThrows(
() => builder.instantiate(), WebAssembly.CompileError, () => builder.instantiate(), WebAssembly.CompileError,
/Compiling wasm function "three snowmen: ☃☃☃" failed: /); /Compiling function #0:"three snowmen: ☃☃☃" failed: /);
})(); })();
(function errorMessageUnicodeInImportModuleName() { (function errorMessageUnicodeInImportModuleName() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment