[wasm] Avoid re-validation after deserialization

As we do not ship lazy validation, we can expect that most modules are
fully validated when they are serialized. We should use that information
and not re-validate functions after deserialization.

We do so by writing out a single boolean value that encodes whether all
functions have been validated. This value is expected to be true in all
relevant cases. On deserialization we then mark all functions as
validated if the value is set.

R=ahaas@chromium.org

Bug: v8:13565
Change-Id: I18bdd6b04b607ba4521d36d3ca2fd35b4a6df7dd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4152489
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85244}
This commit is contained in:
Clemens Backes 2023-01-10 20:52:20 +01:00 committed by V8 LUCI CQ
parent 8a646573d9
commit c48cc5bab5
2 changed files with 31 additions and 1 deletions

View File

@ -656,6 +656,15 @@ struct V8_EXPORT_PRIVATE WasmModule {
} }
} }
void set_all_functions_validated() const {
DCHECK_EQ(kWasmOrigin, origin);
DCHECK_NOT_NULL(validated_functions);
size_t num_words = (num_declared_functions + 7) / 8;
for (size_t i = 0; i < num_words; ++i) {
validated_functions[i].store(0xff, std::memory_order_relaxed);
}
}
base::Vector<const WasmFunction> declared_functions() const { base::Vector<const WasmFunction> declared_functions() const {
return base::VectorOf(functions) + num_imported_functions; return base::VectorOf(functions) + num_imported_functions;
} }

View File

@ -187,7 +187,8 @@ uint32_t GetWasmCalleeTag(RelocInfo* rinfo) {
#endif #endif
} }
constexpr size_t kHeaderSize = sizeof(size_t); // total code size constexpr size_t kHeaderSize = sizeof(size_t) + // total code size
sizeof(bool); // all functions validated
constexpr size_t kCodeHeaderSize = sizeof(uint8_t) + // code kind constexpr size_t kCodeHeaderSize = sizeof(uint8_t) + // code kind
sizeof(int) + // offset of constant pool sizeof(int) + // offset of constant pool
@ -331,6 +332,20 @@ void NativeModuleSerializer::WriteHeader(Writer* writer,
// handler was used or not when serializing. // handler was used or not when serializing.
writer->Write(total_code_size); writer->Write(total_code_size);
// We do not ship lazy validation, so in most cases all functions will be
// validated. Thus only write out a single bit instead of serializing the
// information per function.
const bool fully_validated = !v8_flags.wasm_lazy_validation;
writer->Write(fully_validated);
#ifdef DEBUG
if (fully_validated) {
const WasmModule* module = native_module_->module();
for (auto& function : module->declared_functions()) {
DCHECK(module->function_was_validated(function.func_index));
}
}
#endif
} }
void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) { void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
@ -583,6 +598,7 @@ class V8_EXPORT_PRIVATE NativeModuleDeserializer {
// Updated in {ReadCode}. // Updated in {ReadCode}.
size_t remaining_code_size_ = 0; size_t remaining_code_size_ = 0;
bool all_functions_validated_ = false;
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> lazy_functions_; std::vector<int> lazy_functions_;
@ -665,6 +681,10 @@ bool NativeModuleDeserializer::Read(Reader* reader) {
uint32_t total_fns = native_module_->num_functions(); uint32_t total_fns = native_module_->num_functions();
uint32_t first_wasm_fn = native_module_->num_imported_functions(); uint32_t first_wasm_fn = native_module_->num_imported_functions();
if (all_functions_validated_) {
native_module_->module()->set_all_functions_validated();
}
WasmCodeRefScope wasm_code_ref_scope; WasmCodeRefScope wasm_code_ref_scope;
DeserializationQueue reloc_queue; DeserializationQueue reloc_queue;
@ -718,6 +738,7 @@ bool NativeModuleDeserializer::Read(Reader* reader) {
void NativeModuleDeserializer::ReadHeader(Reader* reader) { void NativeModuleDeserializer::ReadHeader(Reader* reader) {
remaining_code_size_ = reader->Read<size_t>(); remaining_code_size_ = reader->Read<size_t>();
all_functions_validated_ = reader->Read<bool>();
} }
DeserializationUnit NativeModuleDeserializer::ReadCode(int fn_index, DeserializationUnit NativeModuleDeserializer::ReadCode(int fn_index,