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;
bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
wasm::CompilationEnv* env, const wasm::FunctionBody& func_body,
wasm::WasmFeatures* detected, double* decode_ms, MachineGraph* mcgraph,
NodeOriginTable* node_origins, SourcePositionTable* source_positions,
wasm::WasmError* error_out) {
NodeOriginTable* node_origins, SourcePositionTable* source_positions) {
base::ElapsedTimer decode_timer;
if (FLAG_trace_wasm_decode_time) {
decode_timer.Start();
......@@ -6039,7 +6038,6 @@ bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
<< graph_construction_result.error().message()
<< std::endl;
}
*error_out = graph_construction_result.error();
return false;
}
......@@ -6111,11 +6109,9 @@ wasm::WasmCompilationResult TurbofanWasmCompilationUnit::ExecuteCompilation(
: nullptr;
SourcePositionTable* source_positions =
new (mcgraph->zone()) SourcePositionTable(mcgraph->graph());
wasm::WasmError error;
if (!BuildGraphForWasmFunction(env, func_body, detected, &decode_ms, mcgraph,
node_origins, source_positions, &error)) {
DCHECK(!error.empty());
return wasm::WasmCompilationResult{std::move(error)};
node_origins, source_positions)) {
return wasm::WasmCompilationResult{};
}
if (node_origins) {
......@@ -6161,9 +6157,7 @@ wasm::WasmCompilationResult InterpreterCompilationUnit::ExecuteCompilation(
wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::EmptyInterface> decoder(
&zone, module, env->enabled_features, detected, func_body);
decoder.Decode();
if (decoder.failed()) {
return wasm::WasmCompilationResult{decoder.error()};
}
if (decoder.failed()) return wasm::WasmCompilationResult{};
wasm::WasmCompilationResult result = CompileWasmInterpreterEntry(
wasm_unit_->wasm_engine_, env->enabled_features, wasm_unit_->func_index_,
......
......@@ -55,8 +55,7 @@ class TurbofanWasmCompilationUnit {
wasm::WasmFeatures* detected,
double* decode_ms, MachineGraph* mcgraph,
NodeOriginTable* node_origins,
SourcePositionTable* source_positions,
wasm::WasmError* error_out);
SourcePositionTable* source_positions);
wasm::WasmCompilationResult ExecuteCompilation(wasm::CompilationEnv*,
const wasm::FunctionBody&,
......
......@@ -2004,12 +2004,12 @@ WasmCompilationResult LiftoffCompilationUnit::ExecuteCompilation(
LiftoffCompiler* compiler = &decoder.interface();
if (decoder.failed()) {
compiler->OnFirstError(&decoder);
return WasmCompilationResult{decoder.error()};
return WasmCompilationResult{};
}
if (!compiler->ok()) {
// Liftoff compilation failed.
counters->liftoff_unsupported_functions()->Increment();
return WasmCompilationResult{WasmError{0, "Liftoff bailout"}};
return WasmCompilationResult{};
}
counters->liftoff_compiled_functions()->Increment();
......
......@@ -109,7 +109,7 @@ class CompilationState {
void AbortCompilation();
void SetError(uint32_t func_index, const WasmError& error);
void SetError();
void SetWireBytesStorage(std::shared_ptr<WireBytesStorage>);
......
......@@ -195,8 +195,7 @@ WasmCompilationResult WasmCompilationUnit::ExecuteCompilation(
WasmCode* WasmCompilationUnit::Publish(WasmCompilationResult result,
NativeModule* native_module) {
if (!result.succeeded()) {
native_module->compilation_state()->SetError(func_index_,
std::move(result.error));
native_module->compilation_state()->SetError();
return nullptr;
}
......
......@@ -51,12 +51,7 @@ struct WasmCompilationResult {
public:
MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(WasmCompilationResult);
explicit WasmCompilationResult(WasmError error) : error(std::move(error)) {}
bool succeeded() const {
DCHECK_EQ(code_desc.buffer != nullptr, error.empty());
return error.empty();
}
bool succeeded() const { return code_desc.buffer != nullptr; }
operator bool() const { return succeeded(); }
CodeDesc code_desc;
......@@ -65,8 +60,6 @@ struct WasmCompilationResult {
uint32_t tagged_parameter_slots = 0;
OwnedVector<byte> source_positions;
OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions;
WasmError error;
};
class WasmCompilationUnit final {
......
This diff is collapsed.
......@@ -109,7 +109,8 @@ class AsyncCompileJob {
void FinishCompile();
void AsyncCompileFailed(const WasmError&);
void DecodeFailed(const WasmError&);
void AsyncCompileFailed();
void AsyncCompileSucceeded(Handle<WasmModuleObject> result);
......@@ -154,7 +155,7 @@ class AsyncCompileJob {
// Copy of the module wire bytes, moved into the {native_module_} on its
// creation.
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_}).
ModuleWireBytes wire_bytes_;
Handle<Context> native_context_;
......
......@@ -66,7 +66,7 @@ assertPromiseResult(async function badFunctionInTheMiddle() {
let buffer = builder.toBuffer();
await assertCompileError(
buffer,
'Compiling wasm function \"bad\" failed: ' +
'Compiling function #10:\"bad\" failed: ' +
'expected 1 elements on the stack for fallthru to @1, found 0 @+94');
}());
......
......@@ -55,7 +55,7 @@ function assertConversionError(bytes, imports, msg) {
(function TestValidationError() {
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(
builder().addFunction('f', kSig_i_v).end().toBuffer(),
f_error('function body must end with "end" opcode @+24'));
......@@ -176,7 +176,6 @@ function import_error(index, module, func, msg) {
assertConversionError(buffer, {}, kTrapMsgs[kTrapTypeError]);
})();
(function InternalDebugTrace() {
print(arguments.callee.name);
var builder = new WasmModuleBuilder();
......@@ -192,3 +191,18 @@ function import_error(index, module, func, msg) {
}).exports.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
builder.addFunction('three snowmen: ☃☃☃', kSig_i_v).addBody([]).exportFunc();
assertThrows(
() => builder.instantiate(), WebAssembly.CompileError,
/Compiling wasm function "three snowmen: ☃☃☃" failed: /);
/Compiling function #0:"three snowmen: ☃☃☃" failed: /);
})();
(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