Commit 580508f8 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

Revert "[wasm] Support partial serialization of modules"

This reverts commit bce81d6b.

Reason for revert: Newly introduced test is flaking, e.g. https://ci.chromium.org/ui/p/v8/builders/ci/V8%20Linux64%20ASAN/41030/overview or https://ci.chromium.org/ui/p/v8/builders/ci/V8%20Linux/43171/overview

Original change's description:
> [wasm] Support partial serialization of modules
>
> At the moment a WebAssembly module can be serialized successfully when
> all functions were compiled with TurboFan. However, for some functions
> it may not be necessary to be compiled with TurboFan, e.g. for functions
> where Liftoff code is as good as TurboFan code.
>
> With this CL we allow WebAssembly modules to get serialized even when
> not all functions are compiled with TurboFan. Missing functions are
> marked as missing in the serlialization. Upon deserialization, missing
> functions either get compiled by Liftoff, or initialized with a
> lazy-compilation stub, depending on the V8 configuration.
>
> Bug: v8:11862
> Change-Id: Ic833a17639bf841c5def6fe3c35173fe0376c246
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2960209
> Commit-Queue: Andreas Haas <ahaas@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#75987}

Bug: v8:11862
Change-Id: I5445c097ec47f407e5f951d4cf6d2168113f80e8
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3060484
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/master@{#75997}
parent 642a4673
...@@ -132,8 +132,7 @@ class V8_EXPORT_PRIVATE CompilationState { ...@@ -132,8 +132,7 @@ class V8_EXPORT_PRIVATE CompilationState {
void AddCallback(callback_t); void AddCallback(callback_t);
void InitializeAfterDeserialization( void InitializeAfterDeserialization();
base::Vector<const int> missing_functions);
// Wait until top tier compilation finished, or compilation failed. // Wait until top tier compilation finished, or compilation failed.
void WaitForTopTierFinished(); void WaitForTopTierFinished();
......
...@@ -553,8 +553,7 @@ class CompilationStateImpl { ...@@ -553,8 +553,7 @@ class CompilationStateImpl {
// Initialize the compilation progress after deserialization. This is needed // Initialize the compilation progress after deserialization. This is needed
// for recompilation (e.g. for tier down) to work later. // for recompilation (e.g. for tier down) to work later.
void InitializeCompilationProgressAfterDeserialization( void InitializeCompilationProgressAfterDeserialization();
base::Vector<const int> missing_functions);
// Initializes compilation units based on the information encoded in the // Initializes compilation units based on the information encoded in the
// {compilation_progress_}. // {compilation_progress_}.
...@@ -661,10 +660,6 @@ class CompilationStateImpl { ...@@ -661,10 +660,6 @@ class CompilationStateImpl {
} }
private: private:
uint8_t SetupCompilationProgressForFunction(
bool lazy_module, const WasmModule* module,
const WasmFeatures& enabled_features, int func_index);
// Returns the potentially-updated {function_progress}. // Returns the potentially-updated {function_progress}.
uint8_t AddCompilationUnitInternal(CompilationUnitBuilder* builder, uint8_t AddCompilationUnitInternal(CompilationUnitBuilder* builder,
int function_index, int function_index,
...@@ -836,10 +831,8 @@ void CompilationState::WaitForTopTierFinished() { ...@@ -836,10 +831,8 @@ void CompilationState::WaitForTopTierFinished() {
void CompilationState::SetHighPriority() { Impl(this)->SetHighPriority(); } void CompilationState::SetHighPriority() { Impl(this)->SetHighPriority(); }
void CompilationState::InitializeAfterDeserialization( void CompilationState::InitializeAfterDeserialization() {
base::Vector<const int> missing_functions) { Impl(this)->InitializeCompilationProgressAfterDeserialization();
Impl(this)->InitializeCompilationProgressAfterDeserialization(
missing_functions);
} }
bool CompilationState::failed() const { return Impl(this)->failed(); } bool CompilationState::failed() const { return Impl(this)->failed(); }
...@@ -2861,38 +2854,6 @@ bool CompilationStateImpl::cancelled() const { ...@@ -2861,38 +2854,6 @@ bool CompilationStateImpl::cancelled() const {
return compile_cancelled_.load(std::memory_order_relaxed); return compile_cancelled_.load(std::memory_order_relaxed);
} }
uint8_t CompilationStateImpl::SetupCompilationProgressForFunction(
bool lazy_module, const WasmModule* module,
const WasmFeatures& enabled_features, int func_index) {
ExecutionTierPair requested_tiers =
GetRequestedExecutionTiers(module, enabled_features, func_index);
CompileStrategy strategy =
GetCompileStrategy(module, enabled_features, func_index, lazy_module);
bool required_for_baseline = strategy == CompileStrategy::kEager;
bool required_for_top_tier = strategy != CompileStrategy::kLazy;
DCHECK_EQ(required_for_top_tier,
strategy == CompileStrategy::kEager ||
strategy == CompileStrategy::kLazyBaselineEagerTopTier);
// Count functions to complete baseline and top tier compilation.
if (required_for_baseline) outstanding_baseline_units_++;
if (required_for_top_tier) outstanding_top_tier_functions_++;
// Initialize function's compilation progress.
ExecutionTier required_baseline_tier = required_for_baseline
? requested_tiers.baseline_tier
: ExecutionTier::kNone;
ExecutionTier required_top_tier =
required_for_top_tier ? requested_tiers.top_tier : ExecutionTier::kNone;
uint8_t function_progress =
ReachedTierField::encode(ExecutionTier::kNone) |
RequiredBaselineTierField::encode(required_baseline_tier) |
RequiredTopTierField::encode(required_top_tier);
return function_progress;
}
void CompilationStateImpl::InitializeCompilationProgress( void CompilationStateImpl::InitializeCompilationProgress(
bool lazy_module, int num_import_wrappers, int num_export_wrappers) { bool lazy_module, int num_import_wrappers, int num_export_wrappers) {
DCHECK(!failed()); DCHECK(!failed());
...@@ -2919,8 +2880,32 @@ void CompilationStateImpl::InitializeCompilationProgress( ...@@ -2919,8 +2880,32 @@ void CompilationStateImpl::InitializeCompilationProgress(
outstanding_top_tier_functions_++; outstanding_top_tier_functions_++;
continue; continue;
} }
uint8_t function_progress = SetupCompilationProgressForFunction( ExecutionTierPair requested_tiers =
lazy_module, module, enabled_features, func_index); GetRequestedExecutionTiers(module, enabled_features, func_index);
CompileStrategy strategy =
GetCompileStrategy(module, enabled_features, func_index, lazy_module);
bool required_for_baseline = strategy == CompileStrategy::kEager;
bool required_for_top_tier = strategy != CompileStrategy::kLazy;
DCHECK_EQ(required_for_top_tier,
strategy == CompileStrategy::kEager ||
strategy == CompileStrategy::kLazyBaselineEagerTopTier);
// Count functions to complete baseline and top tier compilation.
if (required_for_baseline) outstanding_baseline_units_++;
if (required_for_top_tier) outstanding_top_tier_functions_++;
// Initialize function's compilation progress.
ExecutionTier required_baseline_tier = required_for_baseline
? requested_tiers.baseline_tier
: ExecutionTier::kNone;
ExecutionTier required_top_tier =
required_for_top_tier ? requested_tiers.top_tier : ExecutionTier::kNone;
uint8_t function_progress = ReachedTierField::encode(ExecutionTier::kNone);
function_progress = RequiredBaselineTierField::update(
function_progress, required_baseline_tier);
function_progress =
RequiredTopTierField::update(function_progress, required_top_tier);
compilation_progress_.push_back(function_progress); compilation_progress_.push_back(function_progress);
} }
DCHECK_IMPLIES(lazy_module, outstanding_baseline_units_ == 0); DCHECK_IMPLIES(lazy_module, outstanding_baseline_units_ == 0);
...@@ -3030,12 +3015,8 @@ void CompilationStateImpl::AddCompilationUnit(CompilationUnitBuilder* builder, ...@@ -3030,12 +3015,8 @@ void CompilationStateImpl::AddCompilationUnit(CompilationUnitBuilder* builder,
} }
} }
void CompilationStateImpl::InitializeCompilationProgressAfterDeserialization( void CompilationStateImpl::InitializeCompilationProgressAfterDeserialization() {
base::Vector<const int> missing_functions) {
auto* module = native_module_->module(); auto* module = native_module_->module();
auto enabled_features = native_module_->enabled_features();
const bool lazy_module = IsLazyModule(module);
{
base::MutexGuard guard(&callbacks_mutex_); base::MutexGuard guard(&callbacks_mutex_);
DCHECK(compilation_progress_.empty()); DCHECK(compilation_progress_.empty());
constexpr uint8_t kProgressAfterDeserialization = constexpr uint8_t kProgressAfterDeserialization =
...@@ -3047,14 +3028,6 @@ void CompilationStateImpl::InitializeCompilationProgressAfterDeserialization( ...@@ -3047,14 +3028,6 @@ void CompilationStateImpl::InitializeCompilationProgressAfterDeserialization(
finished_events_.Add(CompilationEvent::kFinishedTopTierCompilation); finished_events_.Add(CompilationEvent::kFinishedTopTierCompilation);
compilation_progress_.assign(module->num_declared_functions, compilation_progress_.assign(module->num_declared_functions,
kProgressAfterDeserialization); kProgressAfterDeserialization);
for (auto func_index : missing_functions) {
compilation_progress_[func_index] = SetupCompilationProgressForFunction(
lazy_module, module, enabled_features, func_index);
}
}
auto builder = std::make_unique<CompilationUnitBuilder>(native_module_);
InitializeCompilationUnits(std::move(builder));
WaitForCompilationEvent(CompilationEvent::kFinishedBaselineCompilation);
} }
void CompilationStateImpl::InitializeRecompilation( void CompilationStateImpl::InitializeRecompilation(
......
...@@ -304,7 +304,7 @@ NativeModuleSerializer::NativeModuleSerializer( ...@@ -304,7 +304,7 @@ NativeModuleSerializer::NativeModuleSerializer(
size_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const { size_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const {
if (code == nullptr) return sizeof(bool); if (code == nullptr) return sizeof(bool);
DCHECK_EQ(WasmCode::kFunction, code->kind()); DCHECK_EQ(WasmCode::kFunction, code->kind());
if (code->tier() != ExecutionTier::kTurbofan) { if (FLAG_wasm_lazy_compilation && code->tier() != ExecutionTier::kTurbofan) {
return sizeof(bool); return sizeof(bool);
} }
return kCodeHeaderSize + code->instructions().size() + return kCodeHeaderSize + code->instructions().size() +
...@@ -338,9 +338,12 @@ bool NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) { ...@@ -338,9 +338,12 @@ bool NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
// Only serialize TurboFan code, as Liftoff code can contain breakpoints or // Only serialize TurboFan code, as Liftoff code can contain breakpoints or
// non-relocatable constants. // non-relocatable constants.
if (code->tier() != ExecutionTier::kTurbofan) { if (code->tier() != ExecutionTier::kTurbofan) {
if (FLAG_wasm_lazy_compilation) {
writer->Write(false); writer->Write(false);
return true; return true;
} }
return false;
}
writer->Write(true); writer->Write(true);
// Write the size of the entire code section, followed by the code header. // Write the size of the entire code section, followed by the code header.
writer->Write(code->constant_pool_offset()); writer->Write(code->constant_pool_offset());
...@@ -533,10 +536,6 @@ class V8_EXPORT_PRIVATE NativeModuleDeserializer { ...@@ -533,10 +536,6 @@ class V8_EXPORT_PRIVATE NativeModuleDeserializer {
bool Read(Reader* reader); bool Read(Reader* reader);
base::Vector<const int> missing_functions() {
return base::VectorOf(missing_functions_);
}
private: private:
friend class CopyAndRelocTask; friend class CopyAndRelocTask;
friend class PublishTask; friend class PublishTask;
...@@ -555,7 +554,6 @@ class V8_EXPORT_PRIVATE NativeModuleDeserializer { ...@@ -555,7 +554,6 @@ class V8_EXPORT_PRIVATE NativeModuleDeserializer {
size_t remaining_code_size_ = 0; size_t remaining_code_size_ = 0;
base::Vector<byte> current_code_space_; base::Vector<byte> current_code_space_;
NativeModule::JumpTablesRef current_jump_tables_; NativeModule::JumpTablesRef current_jump_tables_;
std::vector<int> missing_functions_;
}; };
class CopyAndRelocTask : public JobTask { class CopyAndRelocTask : public JobTask {
...@@ -689,7 +687,9 @@ DeserializationUnit NativeModuleDeserializer::ReadCode(int fn_index, ...@@ -689,7 +687,9 @@ DeserializationUnit NativeModuleDeserializer::ReadCode(int fn_index,
Reader* reader) { Reader* reader) {
bool has_code = reader->Read<bool>(); bool has_code = reader->Read<bool>();
if (!has_code) { if (!has_code) {
missing_functions_.push_back(fn_index); DCHECK(FLAG_wasm_lazy_compilation ||
native_module_->enabled_features().has_compilation_hints());
native_module_->UseLazyStub(fn_index);
return {}; return {};
} }
int constant_pool_offset = reader->Read<int>(); int constant_pool_offset = reader->Read<int>();
...@@ -862,14 +862,9 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule( ...@@ -862,14 +862,9 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule(
NativeModuleDeserializer deserializer(shared_native_module.get()); NativeModuleDeserializer deserializer(shared_native_module.get());
Reader reader(data + WasmSerializer::kHeaderSize); Reader reader(data + WasmSerializer::kHeaderSize);
bool error = !deserializer.Read(&reader); bool error = !deserializer.Read(&reader);
if (error) { shared_native_module->compilation_state()->InitializeAfterDeserialization();
wasm_engine->UpdateNativeModuleCache(error, &shared_native_module,
isolate);
return {};
}
shared_native_module->compilation_state()->InitializeAfterDeserialization(
deserializer.missing_functions());
wasm_engine->UpdateNativeModuleCache(error, &shared_native_module, isolate); wasm_engine->UpdateNativeModuleCache(error, &shared_native_module, isolate);
if (error) return {};
} }
Handle<FixedArray> export_wrappers; Handle<FixedArray> export_wrappers;
......
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --liftoff --no-wasm-tier-up --expose-gc
// Compile functions 0 and 2 with Turbofan, the rest with Liftoff:
// Flags: --wasm-tier-mask-for-testing=5
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
const num_functions = 5;
function create_builder() {
const builder = new WasmModuleBuilder();
for (let i = 0; i < num_functions; ++i) {
builder.addFunction('f' + i, kSig_i_v)
.addBody(wasmI32Const(i))
.exportFunc();
}
return builder;
}
function check(instance) {
for (let i = 0; i < num_functions; ++i) {
const expect_liftoff = i != 0 && i != 2;
assertEquals(
expect_liftoff, %IsLiftoffFunction(instance.exports['f' + i]),
'function ' + i);
}
}
const wire_bytes = create_builder().toBuffer();
function testTierTestingFlag() {
print(arguments.callee.name);
const module = new WebAssembly.Module(wire_bytes);
const buff = %SerializeWasmModule(module);
const instance = new WebAssembly.Instance(module);
check(instance);
return buff;
};
const serialized_module = testTierTestingFlag();
// Do some GCs to make sure the first module got collected and removed from the
// module cache.
gc();
gc();
gc();
(function testSerializedModule() {
print(arguments.callee.name);
const module = %DeserializeWasmModule(serialized_module, wire_bytes);
const instance = new WebAssembly.Instance(module);
check(instance);
})();
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