diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index 041e4325e4..d0cabeabe5 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -5211,21 +5211,21 @@ TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit( TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default; bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction( - wasm::CompilationEnv* env, wasm::WasmFeatures* detected, double* decode_ms, - MachineGraph* mcgraph, NodeOriginTable* node_origins, - SourcePositionTable* source_positions) { + wasm::CompilationEnv* env, const wasm::FunctionBody& func_body, + wasm::WasmFeatures* detected, double* decode_ms, MachineGraph* mcgraph, + NodeOriginTable* node_origins, SourcePositionTable* source_positions) { base::ElapsedTimer decode_timer; if (FLAG_trace_wasm_decode_time) { decode_timer.Start(); } // Create a TF graph during decoding. - WasmGraphBuilder builder(env, mcgraph->zone(), mcgraph, - wasm_unit_->func_body_.sig, source_positions); + WasmGraphBuilder builder(env, mcgraph->zone(), mcgraph, func_body.sig, + source_positions); wasm::VoidResult graph_construction_result = wasm::BuildTFGraph( wasm_unit_->wasm_engine_->allocator(), wasm_unit_->native_module_->enabled_features(), env->module, &builder, - detected, wasm_unit_->func_body_, node_origins); + detected, func_body, node_origins); if (graph_construction_result.failed()) { if (FLAG_trace_wasm_compiler) { StdoutStream{} << "Compilation failed: " @@ -5240,16 +5240,15 @@ bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction( if (builder.has_simd() && (!CpuFeatures::SupportsWasmSimd128() || env->lower_simd)) { - SimdScalarLowering( - mcgraph, - CreateMachineSignature(mcgraph->zone(), wasm_unit_->func_body_.sig)) + SimdScalarLowering(mcgraph, + CreateMachineSignature(mcgraph->zone(), func_body.sig)) .LowerGraph(); } if (wasm_unit_->func_index_ >= FLAG_trace_wasm_ast_start && wasm_unit_->func_index_ < FLAG_trace_wasm_ast_end) { - PrintRawWasmCode(wasm_unit_->wasm_engine_->allocator(), - wasm_unit_->func_body_, env->module, wasm::kPrintLocals); + PrintRawWasmCode(wasm_unit_->wasm_engine_->allocator(), func_body, + env->module, wasm::kPrintLocals); } if (FLAG_trace_wasm_decode_time) { *decode_ms = decode_timer.Elapsed().InMillisecondsF(); @@ -5273,8 +5272,8 @@ Vector GetDebugName(Zone* zone, int index) { } // namespace void TurbofanWasmCompilationUnit::ExecuteCompilation( - wasm::CompilationEnv* env, Counters* counters, - wasm::WasmFeatures* detected) { + wasm::CompilationEnv* env, const wasm::FunctionBody& func_body, + Counters* counters, wasm::WasmFeatures* detected) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "ExecuteTurbofanCompilation"); double decode_ms = 0; @@ -5305,7 +5304,7 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation( : nullptr; SourcePositionTable* source_positions = new (mcgraph->zone()) SourcePositionTable(mcgraph->graph()); - if (!BuildGraphForWasmFunction(env, detected, &decode_ms, mcgraph, + if (!BuildGraphForWasmFunction(env, func_body, detected, &decode_ms, mcgraph, node_origins, source_positions)) { // Compilation failed. return; @@ -5322,16 +5321,15 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation( } // Run the compiler pipeline to generate machine code. - auto call_descriptor = - GetWasmCallDescriptor(&zone, wasm_unit_->func_body_.sig); + auto call_descriptor = GetWasmCallDescriptor(&zone, func_body.sig); if (mcgraph->machine()->Is32()) { call_descriptor = GetI32WasmCallDescriptor(&zone, call_descriptor); } std::unique_ptr job(Pipeline::NewWasmCompilationJob( &info, wasm_unit_->wasm_engine_, mcgraph, call_descriptor, - source_positions, node_origins, wasm_unit_->func_body_, - wasm_unit_->native_module_, wasm_unit_->func_index_)); + source_positions, node_origins, func_body, wasm_unit_->native_module_, + wasm_unit_->func_index_)); if (job->ExecuteJob() == CompilationJob::SUCCEEDED) { wasm_unit_->SetResult(info.wasm_code(), counters); } @@ -5340,9 +5338,8 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation( PrintF( "wasm-compilation phase 1 ok: %u bytes, %0.3f ms decode, %zu nodes, " "%0.3f ms pipeline\n", - static_cast(wasm_unit_->func_body_.end - - wasm_unit_->func_body_.start), - decode_ms, node_count, pipeline_ms); + static_cast(func_body.end - func_body.start), decode_ms, + node_count, pipeline_ms); } // TODO(bradnelson): Improve histogram handling of size_t. counters->wasm_compile_function_peak_memory_bytes()->AddSample( diff --git a/src/compiler/wasm-compiler.h b/src/compiler/wasm-compiler.h index 1c5ba6a184..348c1ccd7b 100644 --- a/src/compiler/wasm-compiler.h +++ b/src/compiler/wasm-compiler.h @@ -51,13 +51,14 @@ class TurbofanWasmCompilationUnit { ~TurbofanWasmCompilationUnit(); bool BuildGraphForWasmFunction(wasm::CompilationEnv* env, + const wasm::FunctionBody& func_body, wasm::WasmFeatures* detected, double* decode_ms, MachineGraph* mcgraph, NodeOriginTable* node_origins, SourcePositionTable* source_positions); - void ExecuteCompilation(wasm::CompilationEnv*, Counters*, - wasm::WasmFeatures* detected); + void ExecuteCompilation(wasm::CompilationEnv*, const wasm::FunctionBody&, + Counters*, wasm::WasmFeatures* detected); private: wasm::WasmCompilationUnit* const wasm_unit_; diff --git a/src/wasm/baseline/liftoff-compiler.cc b/src/wasm/baseline/liftoff-compiler.cc index e054f1978a..168c22b2b7 100644 --- a/src/wasm/baseline/liftoff-compiler.cc +++ b/src/wasm/baseline/liftoff-compiler.cc @@ -1875,6 +1875,7 @@ class LiftoffCompiler { } // namespace bool LiftoffCompilationUnit::ExecuteCompilation(CompilationEnv* env, + const FunctionBody& func_body, Counters* counters, WasmFeatures* detected) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), @@ -1886,13 +1887,12 @@ bool LiftoffCompilationUnit::ExecuteCompilation(CompilationEnv* env, Zone zone(wasm_unit_->wasm_engine_->allocator(), "LiftoffCompilationZone"); const WasmModule* module = env ? env->module : nullptr; - auto call_descriptor = - compiler::GetWasmCallDescriptor(&zone, wasm_unit_->func_body_.sig); + auto call_descriptor = compiler::GetWasmCallDescriptor(&zone, func_body.sig); base::Optional liftoff_compile_time_scope( base::in_place, counters->liftoff_compile_time()); WasmFullDecoder decoder( &zone, module, wasm_unit_->native_module_->enabled_features(), detected, - wasm_unit_->func_body_, call_descriptor, env, &zone); + func_body, call_descriptor, env, &zone); decoder.Decode(); liftoff_compile_time_scope.reset(); LiftoffCompiler* compiler = &decoder.interface(); @@ -1910,9 +1910,7 @@ bool LiftoffCompilationUnit::ExecuteCompilation(CompilationEnv* env, PrintF( "wasm-compilation liftoff phase 1 ok: %u bytes, %0.3f ms decode and " "compile\n", - static_cast(wasm_unit_->func_body_.end - - wasm_unit_->func_body_.start), - compile_ms); + static_cast(func_body.end - func_body.start), compile_ms); } CodeDesc desc; diff --git a/src/wasm/baseline/liftoff-compiler.h b/src/wasm/baseline/liftoff-compiler.h index e9d8e95516..9aeed01628 100644 --- a/src/wasm/baseline/liftoff-compiler.h +++ b/src/wasm/baseline/liftoff-compiler.h @@ -15,6 +15,7 @@ class Counters; namespace wasm { struct CompilationEnv; +struct FunctionBody; class WasmCompilationUnit; struct WasmFeatures; @@ -23,7 +24,8 @@ class LiftoffCompilationUnit final { explicit LiftoffCompilationUnit(WasmCompilationUnit* wasm_unit) : wasm_unit_(wasm_unit) {} - bool ExecuteCompilation(CompilationEnv*, Counters*, WasmFeatures* detected); + bool ExecuteCompilation(CompilationEnv*, const FunctionBody&, Counters*, + WasmFeatures* detected); private: WasmCompilationUnit* const wasm_unit_; diff --git a/src/wasm/compilation-environment.h b/src/wasm/compilation-environment.h index 88d2cb4202..e66929d4e3 100644 --- a/src/wasm/compilation-environment.h +++ b/src/wasm/compilation-environment.h @@ -65,6 +65,14 @@ struct CompilationEnv { lower_simd(lower_simd) {} }; +// The wire bytes are either owned by the StreamingDecoder, or (after streaming) +// by the NativeModule. This class abstracts over the storage location. +class WireBytesStorage { + public: + virtual ~WireBytesStorage() = default; + virtual Vector GetCode(WireBytesRef) const = 0; +}; + // The implementation of {CompilationState} lives in module-compiler.cc. // This is the PIMPL interface to that private class. class CompilationState { @@ -75,6 +83,10 @@ class CompilationState { void SetError(uint32_t func_index, const ResultBase& error_result); + void SetWireBytesStorage(std::shared_ptr); + + std::shared_ptr GetWireBytesStorage(); + private: friend class NativeModule; CompilationState() = delete; diff --git a/src/wasm/function-compiler.cc b/src/wasm/function-compiler.cc index ca40ec0065..e957a2aa6b 100644 --- a/src/wasm/function-compiler.cc +++ b/src/wasm/function-compiler.cc @@ -36,11 +36,9 @@ ExecutionTier WasmCompilationUnit::GetDefaultExecutionTier() { } WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine, - NativeModule* native_module, - FunctionBody body, int index, + NativeModule* native_module, int index, ExecutionTier mode) : wasm_engine_(wasm_engine), - func_body_(body), func_index_(index), native_module_(native_module), mode_(mode) { @@ -62,14 +60,20 @@ WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine, // {TurbofanWasmCompilationUnit} can be opaque in the header file. WasmCompilationUnit::~WasmCompilationUnit() = default; -void WasmCompilationUnit::ExecuteCompilation(CompilationEnv* env, - Counters* counters, - WasmFeatures* detected) { +void WasmCompilationUnit::ExecuteCompilation( + CompilationEnv* env, std::shared_ptr wire_bytes_storage, + Counters* counters, WasmFeatures* detected) { const WasmModule* module = native_module_->module(); + DCHECK_EQ(module, env->module); + + auto* func = &env->module->functions[func_index_]; + Vector code = wire_bytes_storage->GetCode(func->code); + wasm::FunctionBody func_body{func->sig, func->code.offset(), code.start(), + code.end()}; + auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm, function_size_bytes); - size_histogram->AddSample( - static_cast(func_body_.end - func_body_.start)); + size_histogram->AddSample(static_cast(func_body.end - func_body.start)); auto timed_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm_compile, function_time); TimedHistogramScope wasm_compile_function_time_scope(timed_histogram); @@ -81,12 +85,15 @@ void WasmCompilationUnit::ExecuteCompilation(CompilationEnv* env, switch (mode_) { case ExecutionTier::kBaseline: - if (liftoff_unit_->ExecuteCompilation(env, counters, detected)) break; + if (liftoff_unit_->ExecuteCompilation(env, func_body, counters, + detected)) { + break; + } // Otherwise, fall back to turbofan. SwitchMode(ExecutionTier::kOptimized); V8_FALLTHROUGH; case ExecutionTier::kOptimized: - turbofan_unit_->ExecuteCompilation(env, counters, detected); + turbofan_unit_->ExecuteCompilation(env, func_body, counters, detected); break; case ExecutionTier::kInterpreter: UNREACHABLE(); // TODO(titzer): compile interpreter entry stub. @@ -126,10 +133,12 @@ bool WasmCompilationUnit::CompileWasmFunction(Isolate* isolate, wire_bytes.start() + function->code.offset(), wire_bytes.start() + function->code.end_offset()}; - WasmCompilationUnit unit(isolate->wasm_engine(), native_module, function_body, + WasmCompilationUnit unit(isolate->wasm_engine(), native_module, function->func_index, mode); CompilationEnv env = native_module->CreateCompilationEnv(); - unit.ExecuteCompilation(&env, isolate->counters(), detected); + unit.ExecuteCompilation( + &env, native_module->compilation_state()->GetWireBytesStorage(), + isolate->counters(), detected); return !unit.failed(); } diff --git a/src/wasm/function-compiler.h b/src/wasm/function-compiler.h index 8702985773..d56484daac 100644 --- a/src/wasm/function-compiler.h +++ b/src/wasm/function-compiler.h @@ -37,12 +37,13 @@ class WasmCompilationUnit final { // typically means to hold a std::shared_ptr). // If used exclusively from a foreground thread, Isolate::counters() may be // used by callers to pass Counters. - WasmCompilationUnit(WasmEngine*, NativeModule*, FunctionBody, int index, + WasmCompilationUnit(WasmEngine*, NativeModule*, int index, ExecutionTier = GetDefaultExecutionTier()); ~WasmCompilationUnit(); - void ExecuteCompilation(CompilationEnv*, Counters*, WasmFeatures* detected); + void ExecuteCompilation(CompilationEnv*, std::shared_ptr, + Counters*, WasmFeatures* detected); NativeModule* native_module() const { return native_module_; } ExecutionTier mode() const { return mode_; } @@ -58,10 +59,9 @@ class WasmCompilationUnit final { friend class LiftoffCompilationUnit; friend class compiler::TurbofanWasmCompilationUnit; - WasmEngine* wasm_engine_; - FunctionBody func_body_; - int func_index_; - NativeModule* native_module_; + WasmEngine* const wasm_engine_; + const int func_index_; + NativeModule* const native_module_; ExecutionTier mode_; WasmCode* result_ = nullptr; diff --git a/src/wasm/graph-builder-interface.cc b/src/wasm/graph-builder-interface.cc index 0e89927d5f..f09dd463ce 100644 --- a/src/wasm/graph-builder-interface.cc +++ b/src/wasm/graph-builder-interface.cc @@ -821,7 +821,7 @@ DecodeResult BuildTFGraph(AccountingAllocator* allocator, const WasmFeatures& enabled, const wasm::WasmModule* module, compiler::WasmGraphBuilder* builder, - WasmFeatures* detected, FunctionBody& body, + WasmFeatures* detected, const FunctionBody& body, compiler::NodeOriginTable* node_origins) { Zone zone(allocator, ZONE_NAME); WasmFullDecoder decoder( diff --git a/src/wasm/graph-builder-interface.h b/src/wasm/graph-builder-interface.h index 129d108e9f..53885fef38 100644 --- a/src/wasm/graph-builder-interface.h +++ b/src/wasm/graph-builder-interface.h @@ -26,7 +26,7 @@ struct WasmFeatures; DecodeResult BuildTFGraph(AccountingAllocator* allocator, const WasmFeatures& enabled, const WasmModule* module, compiler::WasmGraphBuilder* builder, - WasmFeatures* detected, FunctionBody& body, + WasmFeatures* detected, const FunctionBody& body, compiler::NodeOriginTable* node_origins); } // namespace wasm diff --git a/src/wasm/module-compiler.cc b/src/wasm/module-compiler.cc index bef35046a6..999a24d92a 100644 --- a/src/wasm/module-compiler.cc +++ b/src/wasm/module-compiler.cc @@ -148,6 +148,23 @@ class CompilationStateImpl { error.str()); } + std::shared_ptr GetSharedWireBytesStorage() const { + base::MutexGuard guard(&mutex_); + DCHECK_NOT_NULL(wire_bytes_storage_); + return wire_bytes_storage_; + } + + void SetWireBytesStorage( + std::shared_ptr wire_bytes_storage) { + base::MutexGuard guard(&mutex_); + wire_bytes_storage_ = wire_bytes_storage; + } + + std::shared_ptr GetWireBytesStorage() { + base::MutexGuard guard(&mutex_); + return wire_bytes_storage_; + } + private: struct CompilationError { uint32_t const func_index; @@ -236,6 +253,11 @@ class CompilationStateImpl { // is currently scheduled. LogCodesTask* log_codes_task_ = nullptr; + // Abstraction over the storage of the wire bytes. Held in a shared_ptr so + // that background compilation jobs can keep the storage alive while + // compiling. + std::shared_ptr wire_bytes_storage_; + // End of fields protected by {mutex_}. ////////////////////////////////////////////////////////////////////////////// @@ -419,6 +441,15 @@ void CompilationState::SetError(uint32_t func_index, Impl(this)->SetError(func_index, error_result); } +void CompilationState::SetWireBytesStorage( + std::shared_ptr wire_bytes_storage) { + Impl(this)->SetWireBytesStorage(std::move(wire_bytes_storage)); +} + +std::shared_ptr CompilationState::GetWireBytesStorage() { + return Impl(this)->GetWireBytesStorage(); +} + CompilationState::~CompilationState() { Impl(this)->~CompilationStateImpl(); } // static @@ -456,15 +487,15 @@ WasmCode* LazyCompileFunction(Isolate* isolate, NativeModule* native_module, const uint8_t* module_start = native_module->wire_bytes().start(); const WasmFunction* func = &native_module->module()->functions[func_index]; - FunctionBody body{func->sig, func->code.offset(), - module_start + func->code.offset(), - module_start + func->code.end_offset()}; + FunctionBody func_body{func->sig, func->code.offset(), + module_start + func->code.offset(), + module_start + func->code.end_offset()}; - WasmCompilationUnit unit(isolate->wasm_engine(), native_module, body, - func_index); + WasmCompilationUnit unit(isolate->wasm_engine(), native_module, func_index); CompilationEnv env = native_module->CreateCompilationEnv(); unit.ExecuteCompilation( - &env, isolate->counters(), + &env, native_module->compilation_state()->GetWireBytesStorage(), + isolate->counters(), Impl(native_module->compilation_state())->detected_features()); // If there is a pending error, something really went wrong. The module was @@ -519,19 +550,17 @@ class CompilationUnitBuilder { WasmEngine* wasm_engine) : native_module_(native_module), wasm_engine_(wasm_engine) {} - void AddUnit(const WasmFunction* function, uint32_t buffer_offset, - Vector bytes) { + void AddUnit(uint32_t func_index) { switch (compilation_state()->compile_mode()) { case CompileMode::kTiering: - tiering_units_.emplace_back(CreateUnit(function, buffer_offset, bytes, - ExecutionTier::kOptimized)); - baseline_units_.emplace_back(CreateUnit(function, buffer_offset, bytes, - ExecutionTier::kBaseline)); + tiering_units_.emplace_back( + CreateUnit(func_index, ExecutionTier::kOptimized)); + baseline_units_.emplace_back( + CreateUnit(func_index, ExecutionTier::kBaseline)); return; case CompileMode::kRegular: - baseline_units_.emplace_back( - CreateUnit(function, buffer_offset, bytes, - WasmCompilationUnit::GetDefaultExecutionTier())); + baseline_units_.emplace_back(CreateUnit( + func_index, WasmCompilationUnit::GetDefaultExecutionTier())); return; } UNREACHABLE(); @@ -550,14 +579,10 @@ class CompilationUnitBuilder { } private: - std::unique_ptr CreateUnit(const WasmFunction* function, - uint32_t buffer_offset, - Vector bytes, + std::unique_ptr CreateUnit(uint32_t func_index, ExecutionTier mode) { - return base::make_unique( - wasm_engine_, native_module_, - FunctionBody{function->sig, buffer_offset, bytes.begin(), bytes.end()}, - function->func_index, mode); + return base::make_unique(wasm_engine_, native_module_, + func_index, mode); } CompilationStateImpl* compilation_state() const { @@ -616,7 +641,8 @@ bool FetchAndExecuteCompilationUnit(CompilationEnv* env, // later as soon as Liftoff can compile any function. Then, we can directly // access {unit->mode()} within {ScheduleUnitForFinishing()}. ExecutionTier mode = unit->mode(); - unit->ExecuteCompilation(env, counters, detected); + unit->ExecuteCompilation(env, compilation_state->GetSharedWireBytesStorage(), + counters, detected); if (!unit->failed()) compilation_state->ScheduleCodeLogging(unit->result()); compilation_state->ScheduleUnitForFinishing(std::move(unit), mode); @@ -631,13 +657,7 @@ void InitializeCompilationUnits(NativeModule* native_module, uint32_t start = module->num_imported_functions; uint32_t end = start + module->num_declared_functions; for (uint32_t i = start; i < end; ++i) { - const WasmFunction* func = &module->functions[i]; - uint32_t buffer_offset = func->code.offset(); - Vector bytes(wire_bytes.start() + func->code.offset(), - func->code.end_offset() - func->code.offset()); - - DCHECK_NOT_NULL(native_module); - builder.AddUnit(func, buffer_offset, bytes); + builder.AddUnit(i); } builder.Commit(); } @@ -2283,8 +2303,8 @@ class AsyncStreamingProcessor final : public StreamingProcessor { bool ProcessSection(SectionCode section_code, Vector bytes, uint32_t offset) override; - bool ProcessCodeSectionHeader(size_t functions_count, - uint32_t offset) override; + bool ProcessCodeSectionHeader(size_t functions_count, uint32_t offset, + std::shared_ptr) override; bool ProcessFunctionBody(Vector bytes, uint32_t offset) override; @@ -2810,8 +2830,9 @@ bool AsyncStreamingProcessor::ProcessSection(SectionCode section_code, } // Start the code section. -bool AsyncStreamingProcessor::ProcessCodeSectionHeader(size_t functions_count, - uint32_t offset) { +bool AsyncStreamingProcessor::ProcessCodeSectionHeader( + size_t functions_count, uint32_t offset, + std::shared_ptr wire_bytes_storage) { TRACE_STREAMING("Start the code section with %zu functions...\n", functions_count); if (!decoder_.CheckFunctionsCount(static_cast(functions_count), @@ -2823,6 +2844,8 @@ bool AsyncStreamingProcessor::ProcessCodeSectionHeader(size_t functions_count, // task. job_->DoImmediately( decoder_.shared_module(), false); + job_->native_module_->compilation_state()->SetWireBytesStorage( + std::move(wire_bytes_storage)); auto* compilation_state = Impl(job_->native_module_->compilation_state()); compilation_state->SetNumberOfFunctionsToCompile(functions_count); @@ -2844,8 +2867,7 @@ bool AsyncStreamingProcessor::ProcessFunctionBody(Vector bytes, next_function_, static_cast(bytes.length()), offset, false); uint32_t index = next_function_ + decoder_.module()->num_imported_functions; - const WasmFunction* func = &decoder_.module()->functions[index]; - compilation_unit_builder_->AddUnit(func, offset, bytes); + compilation_unit_builder_->AddUnit(index); ++next_function_; // This method always succeeds. The return value is necessary to comply with // the StreamingProcessor interface. @@ -2870,12 +2892,12 @@ void AsyncStreamingProcessor::OnFinishedStream(OwnedVector bytes) { bool needs_finish = job_->DecrementAndCheckFinisherCount(); if (job_->native_module_ == nullptr) { // We are processing a WebAssembly module without code section. Create the - // runtime objects now (would otherwise happen in {PrepareAndStartCompile}. + // runtime objects now (would otherwise happen in {PrepareAndStartCompile}). job_->PrepareRuntimeObjects(std::move(result).value()); DCHECK(needs_finish); } job_->wire_bytes_ = ModuleWireBytes(bytes.as_vector()); - job_->native_module_->set_wire_bytes(std::move(bytes)); + job_->native_module_->SetWireBytes(std::move(bytes)); if (needs_finish) { HandleScope scope(job_->isolate_); SaveContext saved_context(job_->isolate_); @@ -2916,8 +2938,7 @@ bool AsyncStreamingProcessor::Deserialize(Vector module_bytes, job_->native_module_ = job_->module_object_->native_module(); auto owned_wire_bytes = OwnedVector::Of(wire_bytes); job_->wire_bytes_ = ModuleWireBytes(owned_wire_bytes.as_vector()); - job_->native_module_->set_wire_bytes(std::move(owned_wire_bytes)); - + job_->native_module_->SetWireBytes(std::move(owned_wire_bytes)); job_->FinishCompile(false); return true; } diff --git a/src/wasm/streaming-decoder.cc b/src/wasm/streaming-decoder.cc index 83d84c23bb..d09819781d 100644 --- a/src/wasm/streaming-decoder.cc +++ b/src/wasm/streaming-decoder.cc @@ -389,7 +389,7 @@ StreamingDecoder::DecodeNumberOfFunctions::NextWithValue( return base::make_unique(streaming->module_offset()); } - streaming->StartCodeSection(value_); + streaming->StartCodeSection(value_, streaming->section_buffers_.back()); if (!streaming->ok()) return nullptr; return base::make_unique( section_buffer_, section_buffer_->payload_offset() + bytes_consumed_, @@ -442,6 +442,23 @@ StreamingDecoder::StreamingDecoder( : processor_(std::move(processor)), // A module always starts with a module header. state_(new DecodeModuleHeader()) {} + +StreamingDecoder::SectionBuffer* StreamingDecoder::CreateNewBuffer( + uint32_t module_offset, uint8_t section_id, size_t length, + Vector length_bytes) { + // Check the order of sections. Unknown sections can appear at any position. + if (section_id != kUnknownSectionCode) { + if (section_id < next_section_id_) { + Error("Unexpected section"); + return nullptr; + } + next_section_id_ = section_id + 1; + } + section_buffers_.emplace_back(std::make_shared( + module_offset, section_id, length, length_bytes)); + return section_buffers_.back().get(); +} + } // namespace wasm } // namespace internal } // namespace v8 diff --git a/src/wasm/streaming-decoder.h b/src/wasm/streaming-decoder.h index a8aee17237..3641fd6635 100644 --- a/src/wasm/streaming-decoder.h +++ b/src/wasm/streaming-decoder.h @@ -10,6 +10,7 @@ #include "src/base/macros.h" #include "src/vector.h" +#include "src/wasm/compilation-environment.h" #include "src/wasm/wasm-constants.h" #include "src/wasm/wasm-result.h" @@ -39,8 +40,8 @@ class V8_EXPORT_PRIVATE StreamingProcessor { // Process the start of the code section. Returns true if the processing // finished successfully and the decoding should continue. - virtual bool ProcessCodeSectionHeader(size_t num_functions, - uint32_t offset) = 0; + virtual bool ProcessCodeSectionHeader(size_t num_functions, uint32_t offset, + std::shared_ptr) = 0; // Process a function body. Returns true if the processing finished // successfully and the decoding should continue. @@ -104,7 +105,7 @@ class V8_EXPORT_PRIVATE StreamingDecoder { // The SectionBuffer is the data object for the content of a single section. // It stores all bytes of the section (including section id and section // length), and the offset where the actual payload starts. - class SectionBuffer { + class SectionBuffer : public WireBytesStorage { public: // id: The section id. // payload_length: The length of the payload. @@ -124,6 +125,13 @@ class V8_EXPORT_PRIVATE StreamingDecoder { return static_cast(bytes_.start()[0]); } + Vector GetCode(WireBytesRef ref) const final { + DCHECK_LE(module_offset_, ref.offset()); + uint32_t offset_in_code_buffer = ref.offset() - module_offset_; + return bytes().SubVector(offset_in_code_buffer, + offset_in_code_buffer + ref.length()); + } + uint32_t module_offset() const { return module_offset_; } Vector bytes() const { return bytes_.as_vector(); } Vector payload() const { return bytes() + payload_offset_; } @@ -199,21 +207,9 @@ class V8_EXPORT_PRIVATE StreamingDecoder { class DecodeFunctionBody; // Creates a buffer for the next section of the module. - SectionBuffer* CreateNewBuffer(uint32_t module_offset, uint8_t id, + SectionBuffer* CreateNewBuffer(uint32_t module_offset, uint8_t section_id, size_t length, - Vector length_bytes) { - // Check the order of sections. Unknown sections can appear at any position. - if (id != kUnknownSectionCode) { - if (id < next_section_id_) { - Error("Unexpected section"); - return nullptr; - } - next_section_id_ = id + 1; - } - section_buffers_.emplace_back( - new SectionBuffer(module_offset, id, length, length_bytes)); - return section_buffers_.back().get(); - } + Vector length_bytes); std::unique_ptr Error(VoidResult result) { if (ok_) processor_->OnError(std::move(result)); @@ -242,12 +238,14 @@ class V8_EXPORT_PRIVATE StreamingDecoder { } } - void StartCodeSection(size_t num_functions) { + void StartCodeSection(size_t num_functions, + std::shared_ptr wire_bytes_storage) { if (!ok_) return; // The offset passed to {ProcessCodeSectionHeader} is an error offset and // not the start offset of a buffer. Therefore we need the -1 here. if (!processor_->ProcessCodeSectionHeader(num_functions, - module_offset() - 1)) { + module_offset() - 1, + std::move(wire_bytes_storage))) { ok_ = false; } } @@ -267,7 +265,7 @@ class V8_EXPORT_PRIVATE StreamingDecoder { std::unique_ptr processor_; bool ok_ = true; std::unique_ptr state_; - std::vector> section_buffers_; + std::vector> section_buffers_; uint32_t module_offset_ = 0; size_t total_size_ = 0; uint8_t next_section_id_ = kFirstSectionInModule; diff --git a/src/wasm/wasm-code-manager.cc b/src/wasm/wasm-code-manager.cc index 8ea9ccffd7..cc43d629c8 100644 --- a/src/wasm/wasm-code-manager.cc +++ b/src/wasm/wasm-code-manager.cc @@ -746,6 +746,30 @@ Vector NativeModule::AllocateForCode(size_t size) { return {reinterpret_cast(code_space.begin()), code_space.size()}; } +namespace { +class NativeModuleWireBytesStorage final : public WireBytesStorage { + public: + explicit NativeModuleWireBytesStorage(NativeModule* native_module) + : native_module_(native_module) {} + + Vector GetCode(WireBytesRef ref) const final { + return native_module_->wire_bytes().SubVector(ref.offset(), + ref.end_offset()); + } + + private: + NativeModule* const native_module_; +}; +} // namespace + +void NativeModule::SetWireBytes(OwnedVector wire_bytes) { + wire_bytes_ = std::move(wire_bytes); + if (!wire_bytes.is_empty()) { + compilation_state_->SetWireBytesStorage( + std::make_shared(this)); + } +} + WasmCode* NativeModule::Lookup(Address pc) const { base::MutexGuard lock(&allocation_mutex_); if (owned_code_.empty()) return nullptr; diff --git a/src/wasm/wasm-code-manager.h b/src/wasm/wasm-code-manager.h index 7d13e542cd..d4972513f0 100644 --- a/src/wasm/wasm-code-manager.h +++ b/src/wasm/wasm-code-manager.h @@ -329,11 +329,10 @@ class V8_EXPORT_PRIVATE NativeModule final { void set_lazy_compile_frozen(bool frozen) { lazy_compile_frozen_ = frozen; } bool lazy_compile_frozen() const { return lazy_compile_frozen_; } Vector wire_bytes() const { return wire_bytes_.as_vector(); } - void set_wire_bytes(OwnedVector wire_bytes) { - wire_bytes_ = std::move(wire_bytes); - } const WasmModule* module() const { return module_.get(); } + void SetWireBytes(OwnedVector wire_bytes); + WasmCode* Lookup(Address) const; WasmImportWrapperCache* import_wrapper_cache() const { diff --git a/src/wasm/wasm-objects.cc b/src/wasm/wasm-objects.cc index 33ae92b9de..0b4fb61447 100644 --- a/src/wasm/wasm-objects.cc +++ b/src/wasm/wasm-objects.cc @@ -185,7 +185,7 @@ Handle WasmModuleObject::New( auto native_module = isolate->wasm_engine()->code_manager()->NewNativeModule( isolate, enabled, native_memory_estimate, wasm::NativeModule::kCanAllocateMoreMemory, std::move(shared_module)); - native_module->set_wire_bytes(std::move(wire_bytes)); + native_module->SetWireBytes(std::move(wire_bytes)); native_module->SetRuntimeStubs(isolate); // Delegate to the shared {WasmModuleObject::New} allocator. diff --git a/test/cctest/wasm/wasm-run-utils.cc b/test/cctest/wasm/wasm-run-utils.cc index 1b32407116..c7f539d147 100644 --- a/test/cctest/wasm/wasm-run-utils.cc +++ b/test/cctest/wasm/wasm-run-utils.cc @@ -183,7 +183,7 @@ uint32_t TestingModuleBuilder::AddBytes(Vector bytes) { OwnedVector new_bytes = OwnedVector::New(new_size); memcpy(new_bytes.start(), old_bytes.start(), old_size); memcpy(new_bytes.start() + bytes_offset, bytes.start(), bytes.length()); - native_module_->set_wire_bytes(std::move(new_bytes)); + native_module_->SetWireBytes(std::move(new_bytes)); return bytes_offset; } @@ -419,11 +419,12 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) { func_wire_bytes.start(), func_wire_bytes.end()}; NativeModule* native_module = builder_->instance_object()->module_object()->native_module(); - WasmCompilationUnit unit(isolate()->wasm_engine(), native_module, func_body, + WasmCompilationUnit unit(isolate()->wasm_engine(), native_module, function_->func_index, tier); WasmFeatures unused_detected_features; - unit.ExecuteCompilation(&env, isolate()->counters(), - &unused_detected_features); + unit.ExecuteCompilation( + &env, native_module->compilation_state()->GetWireBytesStorage(), + isolate()->counters(), &unused_detected_features); CHECK(!unit.failed()); if (WasmCode::ShouldBeLogged(isolate())) unit.result()->LogCode(isolate()); } diff --git a/test/unittests/wasm/streaming-decoder-unittest.cc b/test/unittests/wasm/streaming-decoder-unittest.cc index 530ab46a6b..45a27dfb1b 100644 --- a/test/unittests/wasm/streaming-decoder-unittest.cc +++ b/test/unittests/wasm/streaming-decoder-unittest.cc @@ -42,8 +42,8 @@ class MockStreamingProcessor : public StreamingProcessor { return true; } - bool ProcessCodeSectionHeader(size_t num_functions, - uint32_t offset) override { + bool ProcessCodeSectionHeader(size_t num_functions, uint32_t offset, + std::shared_ptr) override { return true; }