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

[wasm] Enable dynamic tiering in serialization tests

Some tests disabled dynamic tiering in order to actually serialize
TurboFan code. This makes the tests a bit simpler, but does not reflect
real-world usage.
This CL enables dynamic tiering in those tests and when needed executes
the code until tier-up was observed.

R=ahaas@chromium.org

Bug: v8:12899
Change-Id: I34cb8cedbc5908d9e6ca09d56c51609d0c8b2d6a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3660262
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80849}
parent b5ccb0ef
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "include/libplatform/libplatform.h" #include "include/libplatform/libplatform.h"
#include "src/api/api-inl.h" #include "src/api/api-inl.h"
#include "src/base/vector.h" #include "src/base/vector.h"
#include "src/handles/global-handles-inl.h"
#include "src/init/v8.h" #include "src/init/v8.h"
#include "src/objects/managed.h" #include "src/objects/managed.h"
#include "src/objects/objects-inl.h" #include "src/objects/objects-inl.h"
...@@ -23,9 +24,7 @@ ...@@ -23,9 +24,7 @@
#include "test/common/wasm/wasm-macro-gen.h" #include "test/common/wasm/wasm-macro-gen.h"
#include "test/common/wasm/wasm-module-runner.h" #include "test/common/wasm/wasm-module-runner.h"
namespace v8 { namespace v8::internal::wasm {
namespace internal {
namespace wasm {
class MockPlatform final : public TestPlatform { class MockPlatform final : public TestPlatform {
public: public:
...@@ -153,17 +152,15 @@ class TestResolver : public CompilationResultResolver { ...@@ -153,17 +152,15 @@ class TestResolver : public CompilationResultResolver {
public: public:
TestResolver(i::Isolate* isolate, CompilationState* state, TestResolver(i::Isolate* isolate, CompilationState* state,
std::string* error_message, std::string* error_message,
std::shared_ptr<NativeModule>* native_module) Handle<WasmModuleObject>* module_object)
: isolate_(isolate), : isolate_(isolate),
state_(state), state_(state),
error_message_(error_message), error_message_(error_message),
native_module_(native_module) {} module_object_(module_object) {}
void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> module) override { void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> module) override {
*state_ = CompilationState::kFinished; *state_ = CompilationState::kFinished;
if (!module.is_null()) { *module_object_ = isolate_->global_handles()->Create(*module);
*native_module_ = module->shared_native_module();
}
} }
void OnCompilationFailed(i::Handle<i::Object> error_reason) override { void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
...@@ -177,14 +174,13 @@ class TestResolver : public CompilationResultResolver { ...@@ -177,14 +174,13 @@ class TestResolver : public CompilationResultResolver {
i::Isolate* isolate_; i::Isolate* isolate_;
CompilationState* const state_; CompilationState* const state_;
std::string* const error_message_; std::string* const error_message_;
std::shared_ptr<NativeModule>* const native_module_; Handle<WasmModuleObject>* const module_object_;
}; };
class StreamTester { class StreamTester {
public: public:
explicit StreamTester(v8::Isolate* isolate) explicit StreamTester(v8::Isolate* isolate)
: zone_(&allocator_, "StreamTester"), : zone_(&allocator_, "StreamTester") {
internal_scope_(reinterpret_cast<i::Isolate*>(isolate)) {
Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext(); v8::Local<v8::Context> context = isolate->GetCurrentContext();
...@@ -192,13 +188,24 @@ class StreamTester { ...@@ -192,13 +188,24 @@ class StreamTester {
i_isolate, WasmFeatures::All(), v8::Utils::OpenHandle(*context), i_isolate, WasmFeatures::All(), v8::Utils::OpenHandle(*context),
"WebAssembly.compileStreaming()", "WebAssembly.compileStreaming()",
std::make_shared<TestResolver>(i_isolate, &state_, &error_message_, std::make_shared<TestResolver>(i_isolate, &state_, &error_message_,
&native_module_)); &module_object_));
} }
std::shared_ptr<StreamingDecoder> stream() { return stream_; } std::shared_ptr<StreamingDecoder> stream() const { return stream_; }
// Compiled module object, valid after successful compile.
Handle<WasmModuleObject> module_object() const {
CHECK(!module_object_.is_null());
return module_object_;
}
// Compiled native module, valid after successful compile. // Compiled native module, valid after successful compile.
std::shared_ptr<NativeModule> native_module() { return native_module_; } NativeModule* native_module() const {
return module_object()->native_module();
}
std::shared_ptr<NativeModule> shared_native_module() const {
return module_object()->shared_native_module();
}
// Run all compiler tasks, both foreground and background tasks. // Run all compiler tasks, both foreground and background tasks.
void RunCompilerTasks() { void RunCompilerTasks() {
...@@ -228,10 +235,9 @@ class StreamTester { ...@@ -228,10 +235,9 @@ class StreamTester {
private: private:
AccountingAllocator allocator_; AccountingAllocator allocator_;
Zone zone_; Zone zone_;
i::HandleScope internal_scope_;
CompilationState state_ = CompilationState::kPending; CompilationState state_ = CompilationState::kPending;
std::string error_message_; std::string error_message_;
std::shared_ptr<NativeModule> native_module_; Handle<WasmModuleObject> module_object_;
std::shared_ptr<StreamingDecoder> stream_; std::shared_ptr<StreamingDecoder> stream_;
}; };
} // namespace } // namespace
...@@ -241,6 +247,8 @@ class StreamTester { ...@@ -241,6 +247,8 @@ class StreamTester {
v8::HandleScope handle_scope(isolate); \ v8::HandleScope handle_scope(isolate); \
v8::Local<v8::Context> context = v8::Context::New(isolate); \ v8::Local<v8::Context> context = v8::Context::New(isolate); \
v8::Context::Scope context_scope(context); \ v8::Context::Scope context_scope(context); \
/* Reduce tiering budget so we do not need to execute too long. */ \
i::FlagScope<int> reduced_tiering_budget(&i::FLAG_wasm_tiering_budget, 10); \
RunStream_##name(&platform, isolate); RunStream_##name(&platform, isolate);
#define STREAM_TEST(name) \ #define STREAM_TEST(name) \
...@@ -253,25 +261,20 @@ class StreamTester { ...@@ -253,25 +261,20 @@ class StreamTester {
} \ } \
void RunStream_##name(MockPlatform* platform, v8::Isolate* isolate) void RunStream_##name(MockPlatform* platform, v8::Isolate* isolate)
constexpr const char* kExportNames[] = {"a", "b", "c"};
// Create a valid module with 3 functions. // Create a valid module with 3 functions.
ZoneBuffer GetValidModuleBytes(Zone* zone) { ZoneBuffer GetValidModuleBytes(Zone* zone) {
ZoneBuffer buffer(zone); ZoneBuffer buffer(zone);
TestSignatures sigs; TestSignatures sigs;
WasmModuleBuilder builder(zone); WasmModuleBuilder builder(zone);
{ uint8_t i = 0;
WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); for (const char* export_name : kExportNames) {
uint8_t code[] = {kExprLocalGet, 0, kExprEnd};
f->EmitCode(code, arraysize(code));
}
{
WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
uint8_t code[] = {kExprLocalGet, 1, kExprEnd};
f->EmitCode(code, arraysize(code));
}
{
WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
uint8_t code[] = {kExprLocalGet, 2, kExprEnd}; uint8_t code[] = {kExprLocalGet, i, kExprEnd};
f->EmitCode(code, arraysize(code)); f->EmitCode(code, arraysize(code));
CHECK_GE(3, ++i);
builder.AddExport(base::CStrVector(export_name), f);
} }
builder.WriteTo(&buffer); builder.WriteTo(&buffer);
return buffer; return buffer;
...@@ -287,11 +290,47 @@ ZoneBuffer GetValidCompiledModuleBytes(v8::Isolate* isolate, Zone* zone, ...@@ -287,11 +290,47 @@ ZoneBuffer GetValidCompiledModuleBytes(v8::Isolate* isolate, Zone* zone,
tester.FinishStream(); tester.FinishStream();
tester.RunCompilerTasks(); tester.RunCompilerTasks();
CHECK(tester.IsPromiseFulfilled()); CHECK(tester.IsPromiseFulfilled());
NativeModule* native_module = tester.native_module();
CHECK_NOT_NULL(native_module);
auto* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
ErrorThrower thrower{i_isolate, "GetValidCompiledModuleBytes"};
Handle<WasmInstanceObject> instance =
GetWasmEngine()
->SyncInstantiate(i_isolate, &thrower, tester.module_object(), {}, {})
.ToHandleChecked();
CHECK(!thrower.error());
// Call the exported functions repeatedly until they are all tiered up.
std::vector<Handle<WasmExportedFunction>> exported_functions;
for (const char* export_name : kExportNames) {
exported_functions.push_back(
testing::GetExportedFunction(i_isolate, instance, export_name)
.ToHandleChecked());
}
while (true) {
WasmCodeRefScope code_ref_scope;
std::vector<WasmCode*> all_code = native_module->SnapshotCodeTable();
if (std::all_of(all_code.begin(), all_code.end(), [](const WasmCode* code) {
return code->tier() == ExecutionTier::kTurbofan;
})) {
break;
}
for (Handle<WasmExportedFunction> exported_function : exported_functions) {
Handle<Object> return_value =
Execution::Call(i_isolate, exported_function,
ReadOnlyRoots{i_isolate}.undefined_value_handle(), 0,
nullptr)
.ToHandleChecked();
CHECK(return_value->IsSmi());
CHECK_EQ(0, Smi::cast(*return_value).value());
}
tester.RunCompilerTasks();
}
// Serialize the NativeModule. // Serialize the NativeModule.
std::shared_ptr<NativeModule> native_module = tester.native_module(); i::wasm::WasmSerializer serializer(native_module);
CHECK(native_module);
native_module->compilation_state()->WaitForTopTierFinished();
i::wasm::WasmSerializer serializer(native_module.get());
size_t size = serializer.GetSerializedNativeModuleSize(); size_t size = serializer.GetSerializedNativeModuleSize();
std::vector<byte> buffer(size); std::vector<byte> buffer(size);
CHECK(serializer.SerializeNativeModule(base::VectorOf(buffer))); CHECK(serializer.SerializeNativeModule(base::VectorOf(buffer)));
...@@ -1101,7 +1140,6 @@ STREAM_TEST(TestModuleWithImportedFunction) { ...@@ -1101,7 +1140,6 @@ STREAM_TEST(TestModuleWithImportedFunction) {
} }
STREAM_TEST(TestIncrementalCaching) { STREAM_TEST(TestIncrementalCaching) {
FLAG_VALUE_SCOPE(wasm_dynamic_tiering, true);
FLAG_VALUE_SCOPE(wasm_tier_up, false); FLAG_VALUE_SCOPE(wasm_tier_up, false);
constexpr int threshold = 10; constexpr int threshold = 10;
FlagScope<int> caching_treshold(&FLAG_wasm_caching_threshold, threshold); FlagScope<int> caching_treshold(&FLAG_wasm_caching_threshold, threshold);
...@@ -1149,10 +1187,10 @@ STREAM_TEST(TestIncrementalCaching) { ...@@ -1149,10 +1187,10 @@ STREAM_TEST(TestIncrementalCaching) {
constexpr base::Vector<const char> kNoSourceUrl{"", 0}; constexpr base::Vector<const char> kNoSourceUrl{"", 0};
Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Handle<Script> script = GetWasmEngine()->GetOrCreateScript( Handle<Script> script = GetWasmEngine()->GetOrCreateScript(
i_isolate, tester.native_module(), kNoSourceUrl); i_isolate, tester.shared_native_module(), kNoSourceUrl);
Handle<FixedArray> export_wrappers = i_isolate->factory()->NewFixedArray(3); Handle<FixedArray> export_wrappers = i_isolate->factory()->NewFixedArray(3);
Handle<WasmModuleObject> module_object = WasmModuleObject::New( Handle<WasmModuleObject> module_object = WasmModuleObject::New(
i_isolate, tester.native_module(), script, export_wrappers); i_isolate, tester.shared_native_module(), script, export_wrappers);
ErrorThrower thrower(i_isolate, "Instantiation"); ErrorThrower thrower(i_isolate, "Instantiation");
// We instantiated before, so the second instantiation must also succeed: // We instantiated before, so the second instantiation must also succeed:
Handle<WasmInstanceObject> instance = Handle<WasmInstanceObject> instance =
...@@ -1175,7 +1213,7 @@ STREAM_TEST(TestIncrementalCaching) { ...@@ -1175,7 +1213,7 @@ STREAM_TEST(TestIncrementalCaching) {
CHECK_EQ(1, call_cache_counter); CHECK_EQ(1, call_cache_counter);
size_t serialized_size; size_t serialized_size;
{ {
i::wasm::WasmSerializer serializer(tester.native_module().get()); i::wasm::WasmSerializer serializer(tester.native_module());
serialized_size = serializer.GetSerializedNativeModuleSize(); serialized_size = serializer.GetSerializedNativeModuleSize();
} }
i::wasm::TriggerTierUp(*instance, 1); i::wasm::TriggerTierUp(*instance, 1);
...@@ -1185,7 +1223,7 @@ STREAM_TEST(TestIncrementalCaching) { ...@@ -1185,7 +1223,7 @@ STREAM_TEST(TestIncrementalCaching) {
CHECK(tester.native_module()->GetCode(2)->is_liftoff()); CHECK(tester.native_module()->GetCode(2)->is_liftoff());
CHECK_EQ(2, call_cache_counter); CHECK_EQ(2, call_cache_counter);
{ {
i::wasm::WasmSerializer serializer(tester.native_module().get()); i::wasm::WasmSerializer serializer(tester.native_module());
CHECK_LT(serialized_size, serializer.GetSerializedNativeModuleSize()); CHECK_LT(serialized_size, serializer.GetSerializedNativeModuleSize());
} }
} }
...@@ -1226,7 +1264,6 @@ STREAM_TEST(TestModuleWithErrorAfterDataSection) { ...@@ -1226,7 +1264,6 @@ STREAM_TEST(TestModuleWithErrorAfterDataSection) {
// Test that cached bytes work. // Test that cached bytes work.
STREAM_TEST(TestDeserializationBypassesCompilation) { STREAM_TEST(TestDeserializationBypassesCompilation) {
FlagScope<bool> no_wasm_dynamic_tiering(&FLAG_wasm_dynamic_tiering, false);
StreamTester tester(isolate); StreamTester tester(isolate);
ZoneBuffer wire_bytes = GetValidModuleBytes(tester.zone()); ZoneBuffer wire_bytes = GetValidModuleBytes(tester.zone());
ZoneBuffer module_bytes = ZoneBuffer module_bytes =
...@@ -1242,7 +1279,6 @@ STREAM_TEST(TestDeserializationBypassesCompilation) { ...@@ -1242,7 +1279,6 @@ STREAM_TEST(TestDeserializationBypassesCompilation) {
// Test that bad cached bytes don't cause compilation of wire bytes to fail. // Test that bad cached bytes don't cause compilation of wire bytes to fail.
STREAM_TEST(TestDeserializationFails) { STREAM_TEST(TestDeserializationFails) {
FlagScope<bool> no_wasm_dynamic_tiering(&FLAG_wasm_dynamic_tiering, false);
StreamTester tester(isolate); StreamTester tester(isolate);
ZoneBuffer wire_bytes = GetValidModuleBytes(tester.zone()); ZoneBuffer wire_bytes = GetValidModuleBytes(tester.zone());
ZoneBuffer module_bytes = ZoneBuffer module_bytes =
...@@ -1286,7 +1322,9 @@ STREAM_TEST(TestFunctionSectionWithoutCodeSection) { ...@@ -1286,7 +1322,9 @@ STREAM_TEST(TestFunctionSectionWithoutCodeSection) {
} }
STREAM_TEST(TestSetModuleCompiledCallback) { STREAM_TEST(TestSetModuleCompiledCallback) {
FlagScope<bool> no_wasm_dynamic_tiering(&FLAG_wasm_dynamic_tiering, false); // Reduce the caching threshold so that our three small functions trigger
// caching.
FlagScope<int> caching_treshold(&FLAG_wasm_caching_threshold, 10);
StreamTester tester(isolate); StreamTester tester(isolate);
bool callback_called = false; bool callback_called = false;
tester.stream()->SetModuleCompiledCallback( tester.stream()->SetModuleCompiledCallback(
...@@ -1295,23 +1333,21 @@ STREAM_TEST(TestSetModuleCompiledCallback) { ...@@ -1295,23 +1333,21 @@ STREAM_TEST(TestSetModuleCompiledCallback) {
}); });
uint8_t code[] = { uint8_t code[] = {
U32V_1(4), // body size ADD_COUNT(U32V_1(0), // locals count
U32V_1(0), // locals count kExprLocalGet, 0, kExprEnd) // body
kExprLocalGet, 0, kExprEnd // body
}; };
const uint8_t bytes[] = { const uint8_t bytes[] = {
WASM_MODULE_HEADER, // module header WASM_MODULE_HEADER, // module header
kTypeSectionCode, // section code SECTION(Type,
U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size ENTRY_COUNT(1), // type count
U32V_1(1), // type count SIG_ENTRY_x_x(kI32Code, kI32Code)), // signature entry
SIG_ENTRY_x_x(kI32Code, kI32Code), // signature entry SECTION(Function, ENTRY_COUNT(3), SIG_INDEX(0), SIG_INDEX(0),
kFunctionSectionCode, // section code SIG_INDEX(0)),
U32V_1(1 + 3), // section size SECTION(Export, ENTRY_COUNT(3), // 3 exports
U32V_1(3), // functions count ADD_COUNT('a'), kExternalFunction, FUNC_INDEX(0), // "a" (0)
0, // signature index ADD_COUNT('b'), kExternalFunction, FUNC_INDEX(1), // "b" (1)
0, // signature index ADD_COUNT('c'), kExternalFunction, FUNC_INDEX(2)), // "c" (2)
0, // signature index
kCodeSectionCode, // section code kCodeSectionCode, // section code
U32V_1(1 + arraysize(code) * 3), // section size U32V_1(1 + arraysize(code) * 3), // section size
U32V_1(3), // functions count U32V_1(3), // functions count
...@@ -1321,10 +1357,38 @@ STREAM_TEST(TestSetModuleCompiledCallback) { ...@@ -1321,10 +1357,38 @@ STREAM_TEST(TestSetModuleCompiledCallback) {
tester.OnBytesReceived(code, arraysize(code)); tester.OnBytesReceived(code, arraysize(code));
tester.OnBytesReceived(code, arraysize(code)); tester.OnBytesReceived(code, arraysize(code));
tester.OnBytesReceived(code, arraysize(code)); tester.OnBytesReceived(code, arraysize(code));
tester.FinishStream(); tester.FinishStream();
tester.RunCompilerTasks(); tester.RunCompilerTasks();
CHECK(tester.IsPromiseFulfilled()); CHECK(tester.IsPromiseFulfilled());
CHECK(callback_called);
// Continue executing functions (eventually triggering tier-up) until the
// callback is called at least once.
auto* i_isolate = CcTest::i_isolate();
ErrorThrower thrower{i_isolate, "TestSetModuleCompiledCallback"};
Handle<WasmInstanceObject> instance =
GetWasmEngine()
->SyncInstantiate(i_isolate, &thrower, tester.module_object(), {}, {})
.ToHandleChecked();
CHECK(!thrower.error());
Handle<WasmExportedFunction> exported_functions[]{
testing::GetExportedFunction(i_isolate, instance, "a").ToHandleChecked(),
testing::GetExportedFunction(i_isolate, instance, "b").ToHandleChecked(),
testing::GetExportedFunction(i_isolate, instance, "c").ToHandleChecked()};
// If Liftoff is enabled, then the callback should only be called after
// tiering up.
CHECK_IMPLIES(FLAG_liftoff, !callback_called);
while (!callback_called) {
for (Handle<WasmExportedFunction> exported_function : exported_functions) {
Execution::Call(i_isolate, exported_function,
ReadOnlyRoots{i_isolate}.undefined_value_handle(), 0,
nullptr)
.Check();
}
tester.RunCompilerTasks();
}
} }
// Test that a compile error contains the name of the function, even if the name // Test that a compile error contains the name of the function, even if the name
...@@ -1481,6 +1545,4 @@ STREAM_TEST(TierDownWithError) { ...@@ -1481,6 +1545,4 @@ STREAM_TEST(TierDownWithError) {
#undef STREAM_TEST #undef STREAM_TEST
} // namespace wasm } // namespace v8::internal::wasm
} // namespace internal
} // namespace v8
...@@ -23,21 +23,18 @@ ...@@ -23,21 +23,18 @@
#include "test/common/wasm/wasm-macro-gen.h" #include "test/common/wasm/wasm-macro-gen.h"
#include "test/common/wasm/wasm-module-runner.h" #include "test/common/wasm/wasm-module-runner.h"
namespace v8 { namespace v8::internal::wasm {
namespace internal {
namespace wasm {
namespace test_wasm_serialization {
// Approximate gtest TEST_F style, in case we adopt gtest. // Approximate gtest TEST_F style, in case we adopt gtest.
class WasmSerializationTest { class WasmSerializationTest {
public: public:
WasmSerializationTest() WasmSerializationTest() : zone_(&allocator_, ZONE_NAME) {
: zone_(&allocator_, ZONE_NAME),
no_wasm_dynamic_tiering_(&FLAG_wasm_dynamic_tiering, false) {
// Don't call here if we move to gtest. // Don't call here if we move to gtest.
SetUp(); SetUp();
} }
static constexpr const char* kFunctionName = "increment";
static void BuildWireBytes(Zone* zone, ZoneBuffer* buffer) { static void BuildWireBytes(Zone* zone, ZoneBuffer* buffer) {
WasmModuleBuilder* builder = zone->New<WasmModuleBuilder>(zone); WasmModuleBuilder* builder = zone->New<WasmModuleBuilder>(zone);
TestSignatures sigs; TestSignatures sigs;
...@@ -50,7 +47,7 @@ class WasmSerializationTest { ...@@ -50,7 +47,7 @@ class WasmSerializationTest {
builder->WriteTo(buffer); builder->WriteTo(buffer);
} }
void ClearSerializedData() { serialized_bytes_ = {nullptr, 0}; } void ClearSerializedData() { serialized_bytes_ = {}; }
void InvalidateVersion() { void InvalidateVersion() {
uint32_t* slot = reinterpret_cast<uint32_t*>( uint32_t* slot = reinterpret_cast<uint32_t*>(
...@@ -104,8 +101,6 @@ class WasmSerializationTest { ...@@ -104,8 +101,6 @@ class WasmSerializationTest {
} }
private: private:
static const char* kFunctionName;
Zone* zone() { return &zone_; } Zone* zone() { return &zone_; }
void SetUp() { void SetUp() {
...@@ -141,10 +136,6 @@ class WasmSerializationTest { ...@@ -141,10 +136,6 @@ class WasmSerializationTest {
// Check that the native module exists at this point. // Check that the native module exists at this point.
CHECK(weak_native_module.lock()); CHECK(weak_native_module.lock());
auto* native_module = module_object->native_module();
native_module->compilation_state()->WaitForTopTierFinished();
DCHECK(!native_module->compilation_state()->failed());
v8::Local<v8::Object> v8_module_obj = v8::Local<v8::Object> v8_module_obj =
v8::Utils::ToLocal(Handle<JSObject>::cast(module_object)); v8::Utils::ToLocal(Handle<JSObject>::cast(module_object));
CHECK(v8_module_obj->IsWasmModuleObject()); CHECK(v8_module_obj->IsWasmModuleObject());
...@@ -158,8 +149,19 @@ class WasmSerializationTest { ...@@ -158,8 +149,19 @@ class WasmSerializationTest {
uint8_t* bytes_copy = zone()->NewArray<uint8_t>(uncompiled_bytes.size()); uint8_t* bytes_copy = zone()->NewArray<uint8_t>(uncompiled_bytes.size());
memcpy(bytes_copy, uncompiled_bytes.data(), uncompiled_bytes.size()); memcpy(bytes_copy, uncompiled_bytes.data(), uncompiled_bytes.size());
wire_bytes_ = {bytes_copy, uncompiled_bytes.size()}; wire_bytes_ = {bytes_copy, uncompiled_bytes.size()};
// keep alive data_ until the end
// Run the code until tier-up (of the single function) was observed.
Handle<WasmInstanceObject> instance =
GetWasmEngine()
->SyncInstantiate(serialization_isolate, &thrower, module_object,
{}, {})
.ToHandleChecked();
CHECK_EQ(0, data_.size);
while (data_.size == 0) {
testing::CallWasmFunctionForTesting(serialization_isolate, instance,
kFunctionName, 0, nullptr);
data_ = compiled_module.Serialize(); data_ = compiled_module.Serialize();
}
CHECK_LT(0, data_.size); CHECK_LT(0, data_.size);
} }
// Dispose of serialization isolate to destroy the reference to the // Dispose of serialization isolate to destroy the reference to the
...@@ -186,11 +188,8 @@ class WasmSerializationTest { ...@@ -186,11 +188,8 @@ class WasmSerializationTest {
v8::OwnedBuffer data_; v8::OwnedBuffer data_;
v8::MemorySpan<const uint8_t> wire_bytes_ = {nullptr, 0}; v8::MemorySpan<const uint8_t> wire_bytes_ = {nullptr, 0};
v8::MemorySpan<const uint8_t> serialized_bytes_ = {nullptr, 0}; v8::MemorySpan<const uint8_t> serialized_bytes_ = {nullptr, 0};
FlagScope<bool> no_wasm_dynamic_tiering_;
}; };
const char* WasmSerializationTest::kFunctionName = "increment";
TEST(DeserializeValidModule) { TEST(DeserializeValidModule) {
WasmSerializationTest test; WasmSerializationTest test;
{ {
...@@ -323,6 +322,8 @@ TEST(TierDownAfterDeserialization) { ...@@ -323,6 +322,8 @@ TEST(TierDownAfterDeserialization) {
auto* native_module = module_object->native_module(); auto* native_module = module_object->native_module();
CHECK_EQ(1, native_module->module()->functions.size()); CHECK_EQ(1, native_module->module()->functions.size());
WasmCodeRefScope code_ref_scope; WasmCodeRefScope code_ref_scope;
// The deserialized code must be TurboFan (we wait for tier-up before
// serializing).
auto* turbofan_code = native_module->GetCode(0); auto* turbofan_code = native_module->GetCode(0);
CHECK_NOT_NULL(turbofan_code); CHECK_NOT_NULL(turbofan_code);
CHECK_EQ(ExecutionTier::kTurbofan, turbofan_code->tier()); CHECK_EQ(ExecutionTier::kTurbofan, turbofan_code->tier());
...@@ -363,7 +364,4 @@ TEST(SerializeLiftoffModuleFails) { ...@@ -363,7 +364,4 @@ TEST(SerializeLiftoffModuleFails) {
CHECK(!wasm_serializer.SerializeNativeModule({buffer.get(), buffer_size})); CHECK(!wasm_serializer.SerializeNativeModule({buffer.get(), buffer_size}));
} }
} // namespace test_wasm_serialization } // namespace v8::internal::wasm
} // namespace wasm
} // namespace internal
} // namespace v8
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