Commit 85cf4be9 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[wasm][fuzzer] Refactor second instantiation

The fuzzer instantiates the module twice: Once for reference
interpretation / execution, and once for the actual execution of
Liftoff/TurboFan code.
For some reason, the two code paths for interpretation and Liftoff
reference execution used different patterns: Interpretation was using
the first instance, and then creating a second instance for actual
execution, whereas the Liftoff path used a second instance for the
reference execution and used the first one for the actual execution.

This CL refactors this to always create a "reference instance" first,
use that for either the interpreter or Liftoff, and then create a second
instance for the actual execution.

R=thibaudm@chromium.org

Bug: v8:12425
Change-Id: I19754264240d8570f00161abb7aecba1cc2b2ae0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3683323
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80900}
parent 4b1b7e29
...@@ -97,15 +97,19 @@ void InterpretAndExecuteModule(i::Isolate* isolate, ...@@ -97,15 +97,19 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
if (module_object->module()->start_function_index >= 0) return; if (module_object->module()->start_function_index >= 0) return;
HandleScope handle_scope(isolate); // Avoid leaking handles. HandleScope handle_scope(isolate); // Avoid leaking handles.
Handle<WasmInstanceObject> instance; Handle<WasmInstanceObject> instance_ref;
// Try to instantiate, return if it fails. // Try to instantiate the reference instance, return if it fails. Use
// {module_ref} if provided (for "Liftoff as reference"), {module_object}
// otherwise (for "interpreter as reference").
{ {
ErrorThrower thrower(isolate, "WebAssembly Instantiation"); ErrorThrower thrower(isolate, "InterpretAndExecuteModule");
if (!GetWasmEngine() if (!GetWasmEngine()
->SyncInstantiate(isolate, &thrower, module_object, {}, ->SyncInstantiate(
{}) // no imports & memory isolate, &thrower,
.ToHandle(&instance)) { module_ref.is_null() ? module_object : module_ref, {},
{}) // no imports & memory
.ToHandle(&instance_ref)) {
isolate->clear_pending_exception(); isolate->clear_pending_exception();
thrower.Reset(); // Ignore errors. thrower.Reset(); // Ignore errors.
return; return;
...@@ -114,7 +118,7 @@ void InterpretAndExecuteModule(i::Isolate* isolate, ...@@ -114,7 +118,7 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
// Get the "main" exported function. Do nothing if it does not exist. // Get the "main" exported function. Do nothing if it does not exist.
Handle<WasmExportedFunction> main_function; Handle<WasmExportedFunction> main_function;
if (!testing::GetExportedFunction(isolate, instance, "main") if (!testing::GetExportedFunction(isolate, instance_ref, "main")
.ToHandle(&main_function)) { .ToHandle(&main_function)) {
return; return;
} }
...@@ -122,17 +126,15 @@ void InterpretAndExecuteModule(i::Isolate* isolate, ...@@ -122,17 +126,15 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
base::OwnedVector<Handle<Object>> compiled_args = base::OwnedVector<Handle<Object>> compiled_args =
testing::MakeDefaultArguments(isolate, main_function->sig()); testing::MakeDefaultArguments(isolate, main_function->sig());
bool exception_ref = false; bool exception_ref = false;
bool exception = false;
int32_t result_ref = 0; int32_t result_ref = 0;
int32_t result = 0;
if (module_ref.is_null()) { if (module_ref.is_null()) {
// Use the interpreter as reference.
base::OwnedVector<WasmValue> arguments = base::OwnedVector<WasmValue> arguments =
testing::MakeDefaultInterpreterArguments(isolate, main_function->sig()); testing::MakeDefaultInterpreterArguments(isolate, main_function->sig());
// Now interpret.
testing::WasmInterpretationResult interpreter_result = testing::WasmInterpretationResult interpreter_result =
testing::InterpretWasmModule(isolate, instance, testing::InterpretWasmModule(isolate, instance_ref,
main_function->function_index(), main_function->function_index(),
arguments.begin()); arguments.begin());
if (interpreter_result.failed()) return; if (interpreter_result.failed()) return;
...@@ -150,35 +152,8 @@ void InterpretAndExecuteModule(i::Isolate* isolate, ...@@ -150,35 +152,8 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
DCHECK(interpreter_result.trapped()); DCHECK(interpreter_result.trapped());
exception_ref = true; exception_ref = true;
} }
// Reset the instance before the test run.
{
ErrorThrower thrower(isolate, "Second Instantiation");
// We instantiated before, so the second instantiation must also succeed.
if (!GetWasmEngine()
->SyncInstantiate(isolate, &thrower, module_object, {},
{}) // no imports & memory
.ToHandle(&instance)) {
DCHECK(thrower.error());
FATAL("Second instantiation failed unexpectedly: %s",
thrower.error_msg());
}
DCHECK(!thrower.error());
}
} else { } else {
Handle<WasmInstanceObject> instance_ref; // Use Liftoff code as reference.
{
ErrorThrower thrower(isolate, "WebAssembly Instantiation");
// We instantiated before, so the second instantiation must also succeed.
if (!GetWasmEngine()
->SyncInstantiate(isolate, &thrower, module_ref, {},
{}) // no imports & memory
.ToHandle(&instance_ref)) {
DCHECK(thrower.error());
FATAL("Second instantiation failed unexpectedly: %s",
thrower.error_msg());
}
DCHECK(!thrower.error());
}
result_ref = testing::CallWasmFunctionForTesting( result_ref = testing::CallWasmFunctionForTesting(
isolate, instance_ref, "main", static_cast<int>(compiled_args.size()), isolate, instance_ref, "main", static_cast<int>(compiled_args.size()),
compiled_args.begin(), &exception_ref); compiled_args.begin(), &exception_ref);
...@@ -190,7 +165,24 @@ void InterpretAndExecuteModule(i::Isolate* isolate, ...@@ -190,7 +165,24 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
if (*nondeterminism != 0) return; if (*nondeterminism != 0) return;
} }
result = testing::CallWasmFunctionForTesting( // Instantiate a fresh instance for the actual (non-ref) execution.
Handle<WasmInstanceObject> instance;
{
ErrorThrower thrower(isolate, "InterpretAndExecuteModule (second)");
// We instantiated before, so the second instantiation must also succeed.
if (!GetWasmEngine()
->SyncInstantiate(isolate, &thrower, module_object, {},
{}) // no imports & memory
.ToHandle(&instance)) {
DCHECK(thrower.error());
FATAL("Second instantiation failed unexpectedly: %s",
thrower.error_msg());
}
DCHECK(!thrower.error());
}
bool exception = false;
int32_t result = testing::CallWasmFunctionForTesting(
isolate, instance, "main", static_cast<int>(compiled_args.size()), isolate, instance, "main", static_cast<int>(compiled_args.size()),
compiled_args.begin(), &exception); compiled_args.begin(), &exception);
......
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