Commit b777c1f9 authored by Vicky Kontoura's avatar Vicky Kontoura Committed by Commit Bot

[wasm] [cleanup] Refactor cctest

This CL just refactors the `test-run-wasm-wrappers.cc` cctest.

Bug: v8:10982
Change-Id: Ib8881c97c0cf395766d9b27a68ee440850df5d59
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2534819Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Vicky Kontoura <vkont@google.com>
Cr-Commit-Position: refs/heads/master@{#71222}
parent f8794dca
......@@ -19,6 +19,40 @@ using testing::CompileAndInstantiateForTesting;
#ifdef V8_TARGET_ARCH_X64
namespace {
Handle<WasmInstanceObject> CompileModule(Zone* zone, Isolate* isolate,
WasmModuleBuilder* builder) {
ZoneBuffer buffer(zone);
builder->WriteTo(&buffer);
testing::SetupIsolateForWasmModule(isolate);
ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
MaybeHandle<WasmInstanceObject> maybe_instance =
CompileAndInstantiateForTesting(
isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
return maybe_instance.ToHandleChecked();
}
bool IsGeneric(Code wrapper) {
return wrapper.is_builtin() &&
wrapper.builtin_index() == Builtins::kGenericJSToWasmWrapper;
}
bool IsSpecific(Code wrapper) {
return wrapper.kind() == CodeKind::JS_TO_WASM_FUNCTION;
}
Handle<Object> SmiHandle(Isolate* isolate, int value) {
return Handle<Object>(Smi::FromInt(value), isolate);
}
void SmiCall(Isolate* isolate, Handle<WasmExportedFunction> exported_function,
int argc, Handle<Object>* argv, int expected_result) {
Handle<Object> receiver = isolate->factory()->undefined_value();
Handle<Object> result =
Execution::Call(isolate, exported_function, receiver, argc, argv)
.ToHandleChecked();
CHECK(result->IsSmi() && Smi::ToInt(*result) == expected_result);
}
void Cleanup() {
// By sending a low memory notifications, we will try hard to collect all
// garbage and will therefore also invoke all weak callbacks of actually
......@@ -34,55 +68,43 @@ TEST(WrapperBudget) {
// This test assumes use of the generic wrapper.
FlagScope<bool> use_wasm_generic_wrapper(&FLAG_wasm_generic_wrapper, true);
TestSignatures sigs;
// Initialize the environment and create a module builder.
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
WasmModuleBuilder* builder = zone.New<WasmModuleBuilder>(&zone);
// Define the Wasm function.
WasmModuleBuilder* builder = zone.New<WasmModuleBuilder>(&zone);
TestSignatures sigs;
WasmFunctionBuilder* f = builder->AddFunction(sigs.i_ii());
f->builder()->AddExport(CStrVector("main"), f);
byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)),
WASM_END};
f->EmitCode(code, sizeof(code));
// Compile module.
ZoneBuffer buffer(&zone);
builder->WriteTo(&buffer);
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
testing::SetupIsolateForWasmModule(isolate);
ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
MaybeHandle<WasmInstanceObject> instance = CompileAndInstantiateForTesting(
isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
// Compile the module.
Handle<WasmInstanceObject> instance =
CompileModule(&zone, isolate, builder);
MaybeHandle<WasmExportedFunction> maybe_export =
testing::GetExportedFunction(isolate, instance.ToHandleChecked(),
"main");
Handle<WasmExportedFunction> main_export = maybe_export.ToHandleChecked();
// Get the exported function and the function data.
Handle<WasmExportedFunction> main_export =
testing::GetExportedFunction(isolate, instance, "main")
.ToHandleChecked();
Handle<WasmExportedFunctionData> main_function_data =
handle(main_export->shared().wasm_exported_function_data(), isolate);
// Check that the generic-wrapper budget has initially a value of
// kGenericWrapperBudget.
CHECK_EQ(
main_export->shared().wasm_exported_function_data().wrapper_budget(),
kGenericWrapperBudget);
CHECK_EQ(main_function_data->wrapper_budget(), kGenericWrapperBudget);
CHECK_GT(kGenericWrapperBudget, 0);
// Call the exported Wasm function and get the result.
Handle<Object> params[2] = {Handle<Object>(Smi::FromInt(6), isolate),
Handle<Object>(Smi::FromInt(7), isolate)};
static const int32_t kExpectedValue = 42;
Handle<Object> receiver = isolate->factory()->undefined_value();
MaybeHandle<Object> maybe_result =
Execution::Call(isolate, main_export, receiver, 2, params);
Handle<Object> result = maybe_result.ToHandleChecked();
// Call the exported Wasm function.
Handle<Object> params[2] = {SmiHandle(isolate, 6), SmiHandle(isolate, 7)};
SmiCall(isolate, main_export, 2, params, 42);
// Check that the budget has now a value of (kGenericWrapperBudget - 1).
CHECK_EQ(
main_export->shared().wasm_exported_function_data().wrapper_budget(),
kGenericWrapperBudget - 1);
CHECK(result->IsSmi() && Smi::ToInt(*result) == kExpectedValue);
CHECK_EQ(main_function_data->wrapper_budget(), kGenericWrapperBudget - 1);
}
Cleanup();
}
......@@ -92,95 +114,66 @@ TEST(WrapperReplacement) {
// This test assumes use of the generic wrapper.
FlagScope<bool> use_wasm_generic_wrapper(&FLAG_wasm_generic_wrapper, true);
TestSignatures sigs;
// Initialize the environment and create a module builder.
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
WasmModuleBuilder* builder = zone.New<WasmModuleBuilder>(&zone);
// Define the Wasm function.
WasmModuleBuilder* builder = zone.New<WasmModuleBuilder>(&zone);
TestSignatures sigs;
WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i());
f->builder()->AddExport(CStrVector("main"), f);
byte code[] = {WASM_RETURN1(WASM_GET_LOCAL(0)), WASM_END};
byte code[] = {WASM_GET_LOCAL(0), WASM_END};
f->EmitCode(code, sizeof(code));
// Compile module.
ZoneBuffer buffer(&zone);
builder->WriteTo(&buffer);
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
testing::SetupIsolateForWasmModule(isolate);
ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
MaybeHandle<WasmInstanceObject> instance = CompileAndInstantiateForTesting(
isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
// Compile the module.
Handle<WasmInstanceObject> instance =
CompileModule(&zone, isolate, builder);
// Get the exported function.
MaybeHandle<WasmExportedFunction> maybe_export =
testing::GetExportedFunction(isolate, instance.ToHandleChecked(),
"main");
Handle<WasmExportedFunction> main_export = maybe_export.ToHandleChecked();
// Get the exported function and the function data.
Handle<WasmExportedFunction> main_export =
testing::GetExportedFunction(isolate, instance, "main")
.ToHandleChecked();
Handle<WasmExportedFunctionData> main_function_data =
handle(main_export->shared().wasm_exported_function_data(), isolate);
// Check that the generic-wrapper budget has initially a value of
// kGenericWrapperBudget.
CHECK_EQ(
main_export->shared().wasm_exported_function_data().wrapper_budget(),
kGenericWrapperBudget);
CHECK_EQ(main_function_data->wrapper_budget(), kGenericWrapperBudget);
CHECK_GT(kGenericWrapperBudget, 0);
// Set the generic-wrapper budget to a value that allows for a few
// more calls through the generic wrapper.
const int remaining_budget =
std::min(static_cast<int>(kGenericWrapperBudget), 2);
main_function_data->set_wrapper_budget(remaining_budget);
// Call the exported Wasm function as many times as required to almost
// exhaust the budget for using the generic wrapper.
const int budget = static_cast<int>(kGenericWrapperBudget);
for (int i = budget; i > 1; --i) {
// Verify that the wrapper to be used is still the generic one.
Code wrapper =
main_export->shared().wasm_exported_function_data().wrapper_code();
CHECK(wrapper.is_builtin() &&
wrapper.builtin_index() == Builtins::kGenericJSToWasmWrapper);
// exhaust the remaining budget for using the generic wrapper.
Handle<Code> wrapper_before_call;
for (int i = remaining_budget; i > 0; --i) {
// Verify that the wrapper to be used is the generic one.
wrapper_before_call =
Handle<Code>(main_function_data->wrapper_code(), isolate);
CHECK(IsGeneric(*wrapper_before_call));
// Call the function.
int32_t expected_value = i;
Handle<Object> params[1] = {
Handle<Object>(Smi::FromInt(expected_value), isolate)};
Handle<Object> receiver = isolate->factory()->undefined_value();
MaybeHandle<Object> maybe_result =
Execution::Call(isolate, main_export, receiver, 1, params);
Handle<Object> result = maybe_result.ToHandleChecked();
// Verify that the budget has now a value of (i - 1) and the return value
// is correct.
CHECK_EQ(
main_export->shared().wasm_exported_function_data().wrapper_budget(),
i - 1);
CHECK(result->IsSmi() && Smi::ToInt(*result) == expected_value);
Handle<Object> params[1] = {SmiHandle(isolate, i)};
SmiCall(isolate, main_export, 1, params, i);
// Verify that the budget has now a value of (i - 1).
CHECK_EQ(main_function_data->wrapper_budget(), i - 1);
}
// Get the wrapper-code object before making the call that will kick off the
// wrapper replacement.
Code wrapper_before_call =
main_export->shared().wasm_exported_function_data().wrapper_code();
// Verify that the wrapper before the call is the generic wrapper.
CHECK(wrapper_before_call.is_builtin() &&
wrapper_before_call.builtin_index() ==
Builtins::kGenericJSToWasmWrapper);
// Call the exported Wasm function one more time to kick off the wrapper
// replacement.
int32_t expected_value = 42;
Handle<Object> params[1] = {
Handle<Object>(Smi::FromInt(expected_value), isolate)};
Handle<Object> receiver = isolate->factory()->undefined_value();
MaybeHandle<Object> maybe_result =
Execution::Call(isolate, main_export, receiver, 1, params);
Handle<Object> result = maybe_result.ToHandleChecked();
// Check that the budget has been exhausted and the result is correct.
CHECK_EQ(
main_export->shared().wasm_exported_function_data().wrapper_budget(),
0);
CHECK(result->IsSmi() && Smi::ToInt(*result) == expected_value);
// Verify that the wrapper-code object has changed.
Code wrapper_after_call =
main_export->shared().wasm_exported_function_data().wrapper_code();
CHECK_NE(wrapper_after_call, wrapper_before_call);
// Verify that the wrapper is now a specific one.
CHECK(wrapper_after_call.kind() == CodeKind::JS_TO_WASM_FUNCTION);
// Get the wrapper-code object after the wrapper replacement.
Code wrapper_after_call = main_function_data->wrapper_code();
// Verify that the budget has been exhausted.
CHECK_EQ(main_function_data->wrapper_budget(), 0);
// Verify that the wrapper-code object has changed and the wrapper is now a
// specific one.
CHECK_NE(wrapper_after_call, *wrapper_before_call);
CHECK(IsSpecific(wrapper_after_call));
}
Cleanup();
}
......@@ -190,14 +183,17 @@ TEST(EagerWrapperReplacement) {
// This test assumes use of the generic wrapper.
FlagScope<bool> use_wasm_generic_wrapper(&FLAG_wasm_generic_wrapper, true);
TestSignatures sigs;
// Initialize the environment and create a module builder.
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
WasmModuleBuilder* builder = zone.New<WasmModuleBuilder>(&zone);
// Define three Wasm functions.
// Two of these functions (add and mult) will share the same signature,
// while the other one (id) won't.
WasmModuleBuilder* builder = zone.New<WasmModuleBuilder>(&zone);
TestSignatures sigs;
WasmFunctionBuilder* add = builder->AddFunction(sigs.i_ii());
add->builder()->AddExport(CStrVector("add"), add);
byte add_code[] = {WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)),
......@@ -213,17 +209,9 @@ TEST(EagerWrapperReplacement) {
byte id_code[] = {WASM_GET_LOCAL(0), WASM_END};
id->EmitCode(id_code, sizeof(id_code));
// Compile module.
ZoneBuffer buffer(&zone);
builder->WriteTo(&buffer);
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
testing::SetupIsolateForWasmModule(isolate);
ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
MaybeHandle<WasmInstanceObject> maybe_instance =
CompileAndInstantiateForTesting(
isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
Handle<WasmInstanceObject> instance = maybe_instance.ToHandleChecked();
// Compile the module.
Handle<WasmInstanceObject> instance =
CompileModule(&zone, isolate, builder);
// Get the exported functions.
Handle<WasmExportedFunction> add_export =
......@@ -236,89 +224,60 @@ TEST(EagerWrapperReplacement) {
testing::GetExportedFunction(isolate, instance, "id").ToHandleChecked();
// Get the function data for all exported functions.
WasmExportedFunctionData add_function_data =
add_export->shared().wasm_exported_function_data();
WasmExportedFunctionData mult_function_data =
mult_export->shared().wasm_exported_function_data();
WasmExportedFunctionData id_function_data =
id_export->shared().wasm_exported_function_data();
Handle<WasmExportedFunctionData> add_function_data =
handle(add_export->shared().wasm_exported_function_data(), isolate);
Handle<WasmExportedFunctionData> mult_function_data =
handle(mult_export->shared().wasm_exported_function_data(), isolate);
Handle<WasmExportedFunctionData> id_function_data =
handle(id_export->shared().wasm_exported_function_data(), isolate);
// Set the remaining generic-wrapper budget for add to 1,
// so that the next call to it will cause the function to tier up.
add_function_data.set_wrapper_budget(1);
add_function_data->set_wrapper_budget(1);
// Verify that the generic-wrapper budgets for all functions are correct.
CHECK_EQ(add_function_data.wrapper_budget(), 1);
CHECK_EQ(mult_function_data.wrapper_budget(), kGenericWrapperBudget);
CHECK_EQ(id_function_data.wrapper_budget(), kGenericWrapperBudget);
CHECK_EQ(add_function_data->wrapper_budget(), 1);
CHECK_EQ(mult_function_data->wrapper_budget(), kGenericWrapperBudget);
CHECK_EQ(id_function_data->wrapper_budget(), kGenericWrapperBudget);
// Verify that all functions are set to use the generic wrapper.
CHECK(add_function_data.wrapper_code().is_builtin() &&
add_function_data.wrapper_code().builtin_index() ==
Builtins::kGenericJSToWasmWrapper);
CHECK(mult_function_data.wrapper_code().is_builtin() &&
mult_function_data.wrapper_code().builtin_index() ==
Builtins::kGenericJSToWasmWrapper);
CHECK(id_function_data.wrapper_code().is_builtin() &&
id_function_data.wrapper_code().builtin_index() ==
Builtins::kGenericJSToWasmWrapper);
CHECK(IsGeneric(add_function_data->wrapper_code()));
CHECK(IsGeneric(mult_function_data->wrapper_code()));
CHECK(IsGeneric(id_function_data->wrapper_code()));
// Call the add function to trigger the tier up.
{
int32_t expected_value = 21;
Handle<Object> params[2] = {Handle<Object>(Smi::FromInt(10), isolate),
Handle<Object>(Smi::FromInt(11), isolate)};
Handle<Object> receiver = isolate->factory()->undefined_value();
MaybeHandle<Object> maybe_result =
Execution::Call(isolate, add_export, receiver, 2, params);
Handle<Object> result = maybe_result.ToHandleChecked();
CHECK(result->IsSmi() && Smi::ToInt(*result) == expected_value);
}
Handle<Object> params[2] = {SmiHandle(isolate, 10),
SmiHandle(isolate, 11)};
SmiCall(isolate, add_export, 2, params, 21);
// Verify that the generic-wrapper budgets for all functions are correct.
CHECK_EQ(add_function_data.wrapper_budget(), 0);
CHECK_EQ(mult_function_data.wrapper_budget(), kGenericWrapperBudget);
CHECK_EQ(id_function_data.wrapper_budget(), kGenericWrapperBudget);
// Verify that the tier up of the add function replaced the wrapper
CHECK_EQ(add_function_data->wrapper_budget(), 0);
CHECK_EQ(mult_function_data->wrapper_budget(), kGenericWrapperBudget);
CHECK_EQ(id_function_data->wrapper_budget(), kGenericWrapperBudget);
// Verify that the tier-up of the add function replaced the wrapper
// for both the add and the mult functions, but not the id function.
CHECK(add_function_data.wrapper_code().kind() ==
CodeKind::JS_TO_WASM_FUNCTION);
CHECK(mult_function_data.wrapper_code().kind() ==
CodeKind::JS_TO_WASM_FUNCTION);
CHECK(id_function_data.wrapper_code().is_builtin() &&
id_function_data.wrapper_code().builtin_index() ==
Builtins::kGenericJSToWasmWrapper);
CHECK(IsSpecific(add_function_data->wrapper_code()));
CHECK(IsSpecific(mult_function_data->wrapper_code()));
CHECK(IsGeneric(id_function_data->wrapper_code()));
}
// Call the mult function to verify that the compiled wrapper is used.
{
int32_t expected_value = 42;
Handle<Object> params[2] = {Handle<Object>(Smi::FromInt(7), isolate),
Handle<Object>(Smi::FromInt(6), isolate)};
Handle<Object> receiver = isolate->factory()->undefined_value();
MaybeHandle<Object> maybe_result =
Execution::Call(isolate, mult_export, receiver, 2, params);
Handle<Object> result = maybe_result.ToHandleChecked();
CHECK(result->IsSmi() && Smi::ToInt(*result) == expected_value);
}
Handle<Object> params[2] = {SmiHandle(isolate, 6), SmiHandle(isolate, 7)};
SmiCall(isolate, mult_export, 2, params, 42);
// Verify that mult's budget is still intact, which means that the call
// didn't go through the generic wrapper.
CHECK_EQ(mult_function_data.wrapper_budget(), kGenericWrapperBudget);
CHECK_EQ(mult_function_data->wrapper_budget(), kGenericWrapperBudget);
}
// Call the id function to verify that the generic wrapper is used.
{
int32_t expected_value = 12;
Handle<Object> params[1] = {
Handle<Object>(Smi::FromInt(expected_value), isolate)};
Handle<Object> receiver = isolate->factory()->undefined_value();
MaybeHandle<Object> maybe_result =
Execution::Call(isolate, id_export, receiver, 1, params);
Handle<Object> result = maybe_result.ToHandleChecked();
CHECK(result->IsSmi() && Smi::ToInt(*result) == expected_value);
}
Handle<Object> params[1] = {SmiHandle(isolate, 6)};
SmiCall(isolate, id_export, 1, params, 6);
// Verify that id's budget decreased by 1, which means that the call
// used the generic wrapper.
CHECK_EQ(id_function_data.wrapper_budget(), kGenericWrapperBudget - 1);
CHECK_EQ(id_function_data->wrapper_budget(), kGenericWrapperBudget - 1);
}
}
Cleanup();
}
......
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