[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: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80900}
This commit is contained in:
Clemens Backes 2022-06-01 17:03:57 +02:00 committed by V8 LUCI CQ
parent 4b1b7e29ba
commit 85cf4be909

View File

@ -97,15 +97,19 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
if (module_object->module()->start_function_index >= 0) return;
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()
->SyncInstantiate(isolate, &thrower, module_object, {},
{}) // no imports & memory
.ToHandle(&instance)) {
->SyncInstantiate(
isolate, &thrower,
module_ref.is_null() ? module_object : module_ref, {},
{}) // no imports & memory
.ToHandle(&instance_ref)) {
isolate->clear_pending_exception();
thrower.Reset(); // Ignore errors.
return;
@ -114,7 +118,7 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
// Get the "main" exported function. Do nothing if it does not exist.
Handle<WasmExportedFunction> main_function;
if (!testing::GetExportedFunction(isolate, instance, "main")
if (!testing::GetExportedFunction(isolate, instance_ref, "main")
.ToHandle(&main_function)) {
return;
}
@ -122,17 +126,15 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
base::OwnedVector<Handle<Object>> compiled_args =
testing::MakeDefaultArguments(isolate, main_function->sig());
bool exception_ref = false;
bool exception = false;
int32_t result_ref = 0;
int32_t result = 0;
if (module_ref.is_null()) {
// Use the interpreter as reference.
base::OwnedVector<WasmValue> arguments =
testing::MakeDefaultInterpreterArguments(isolate, main_function->sig());
// Now interpret.
testing::WasmInterpretationResult interpreter_result =
testing::InterpretWasmModule(isolate, instance,
testing::InterpretWasmModule(isolate, instance_ref,
main_function->function_index(),
arguments.begin());
if (interpreter_result.failed()) return;
@ -150,35 +152,8 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
DCHECK(interpreter_result.trapped());
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 {
Handle<WasmInstanceObject> instance_ref;
{
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());
}
// Use Liftoff code as reference.
result_ref = testing::CallWasmFunctionForTesting(
isolate, instance_ref, "main", static_cast<int>(compiled_args.size()),
compiled_args.begin(), &exception_ref);
@ -190,7 +165,24 @@ void InterpretAndExecuteModule(i::Isolate* isolate,
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()),
compiled_args.begin(), &exception);