Commit 6be6ec00 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Store WasmModule in shared_ptr during async compilation

We currently store the {WasmModule} (generated during decoding) in a
unique_ptr and pass ownership to the {WasmModuleObject} after
compilation.
I plan to move the {Managed<NativeModule>} from {WasmCompiledModule} to
{WasmModuleObject}, which will force us to create the
{WasmModuleObject} *before* compilation, so that the {CompilationState}
is available during compilation.

This CL prepares that refactoring by storing the {WasmModule} in a
{shared_ptr} in the {AsyncCompileJob}. Note that it will eventually be
stored in a {shared_ptr} in the {Managed} anyway.

R=titzer@chromium.org

Change-Id: Iac5e3c1067af2801e938f77a455a68807801526a
Reviewed-on: https://chromium-review.googlesource.com/1104117
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53801}
parent e947d21e
...@@ -1442,7 +1442,7 @@ class BackgroundCompileTask : public CancelableTask { ...@@ -1442,7 +1442,7 @@ class BackgroundCompileTask : public CancelableTask {
} // namespace } // namespace
MaybeHandle<WasmModuleObject> CompileToModuleObject( MaybeHandle<WasmModuleObject> CompileToModuleObject(
Isolate* isolate, ErrorThrower* thrower, std::unique_ptr<WasmModule> module, Isolate* isolate, ErrorThrower* thrower, std::shared_ptr<WasmModule> module,
const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script, const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script,
Vector<const byte> asm_js_offset_table_bytes) { Vector<const byte> asm_js_offset_table_bytes) {
WasmModule* wasm_module = module.get(); WasmModule* wasm_module = module.get();
...@@ -2890,7 +2890,7 @@ void AsyncCompileJob::FinishCompile() { ...@@ -2890,7 +2890,7 @@ void AsyncCompileJob::FinishCompile() {
// breakpoints on a (potentially empty) subset of the instances. // breakpoints on a (potentially empty) subset of the instances.
// Create the module object. // Create the module object.
module_object_ = WasmModuleObject::New( module_object_ = WasmModuleObject::New(
isolate_, compiled_module_, export_wrappers, std::move(module_), isolate_, compiled_module_, export_wrappers, module_,
Handle<SeqOneByteString>::cast(module_bytes), script, Handle<SeqOneByteString>::cast(module_bytes), script,
asm_js_offset_table); asm_js_offset_table);
compiled_module_->GetNativeModule()->SetModuleObject(module_object_); compiled_module_->GetNativeModule()->SetModuleObject(module_object_);
...@@ -3037,7 +3037,7 @@ class AsyncCompileJob::DecodeModule : public AsyncCompileJob::CompileStep { ...@@ -3037,7 +3037,7 @@ class AsyncCompileJob::DecodeModule : public AsyncCompileJob::CompileStep {
} else { } else {
// Decode passed. // Decode passed.
job_->module_ = std::move(result.val); job_->module_ = std::move(result.val);
job_->DoSync<PrepareAndStartCompile>(job_->module_.get(), true); job_->DoSync<PrepareAndStartCompile>(true);
} }
} }
}; };
...@@ -3065,11 +3065,10 @@ class AsyncCompileJob::DecodeFail : public CompileStep { ...@@ -3065,11 +3065,10 @@ class AsyncCompileJob::DecodeFail : public CompileStep {
//========================================================================== //==========================================================================
class AsyncCompileJob::PrepareAndStartCompile : public CompileStep { class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
public: public:
explicit PrepareAndStartCompile(WasmModule* module, bool start_compilation) explicit PrepareAndStartCompile(bool start_compilation)
: module_(module), start_compilation_(start_compilation) {} : start_compilation_(start_compilation) {}
private: private:
WasmModule* module_;
bool start_compilation_; bool start_compilation_;
void RunInForeground() override { void RunInForeground() override {
...@@ -3079,13 +3078,14 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep { ...@@ -3079,13 +3078,14 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
// is done. // is done.
job_->background_task_manager_.CancelAndWait(); job_->background_task_manager_.CancelAndWait();
DCHECK_LE(module_->num_imported_functions, module_->functions.size()); WasmModule* module = job_->module_.get();
DCHECK_LE(module->num_imported_functions, module->functions.size());
// Create the compiled module object and populate with compiled functions // Create the compiled module object and populate with compiled functions
// and information needed at instantiation time. This object needs to be // and information needed at instantiation time. This object needs to be
// serializable. Instantiation may occur off a deserialized version of // serializable. Instantiation may occur off a deserialized version of
// this object. // this object.
ModuleEnv env = CreateDefaultModuleEnv(module_); ModuleEnv env = CreateDefaultModuleEnv(module);
job_->compiled_module_ = NewCompiledModule(job_->isolate_, module_, env); job_->compiled_module_ = NewCompiledModule(job_->isolate_, module, env);
{ {
DeferredHandleScope deferred(job_->isolate_); DeferredHandleScope deferred(job_->isolate_);
...@@ -3093,7 +3093,7 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep { ...@@ -3093,7 +3093,7 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
job_->deferred_handles_.push_back(deferred.Detach()); job_->deferred_handles_.push_back(deferred.Detach());
} }
size_t num_functions = size_t num_functions =
module_->functions.size() - module_->num_imported_functions; module->functions.size() - module->num_imported_functions;
if (num_functions == 0) { if (num_functions == 0) {
// Tiering has nothing to do if module is empty. // Tiering has nothing to do if module is empty.
...@@ -3171,7 +3171,7 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep { ...@@ -3171,7 +3171,7 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
size_t functions_count = GetNumFunctionsToCompile(env.module); size_t functions_count = GetNumFunctionsToCompile(env.module);
compilation_state->SetNumberOfFunctionsToCompile(functions_count); compilation_state->SetNumberOfFunctionsToCompile(functions_count);
// Add compilation units and kick off compilation. // Add compilation units and kick off compilation.
InitializeCompilationUnits(module_->functions, job_->wire_bytes_, InitializeCompilationUnits(module->functions, job_->wire_bytes_,
env.module, env.module,
job_->compiled_module_->GetNativeModule()); job_->compiled_module_->GetNativeModule());
} }
...@@ -3220,9 +3220,8 @@ class AsyncCompileJob::FinishModule : public CompileStep { ...@@ -3220,9 +3220,8 @@ class AsyncCompileJob::FinishModule : public CompileStep {
TRACE_COMPILE("(6) Finish module...\n"); TRACE_COMPILE("(6) Finish module...\n");
job_->AsyncCompileSucceeded(job_->module_object_); job_->AsyncCompileSucceeded(job_->module_object_);
WasmModule* module = job_->module_object_->module();
size_t num_functions = size_t num_functions =
module->functions.size() - module->num_imported_functions; job_->module_->functions.size() - job_->module_->num_imported_functions;
if (job_->compiled_module_->GetNativeModule() if (job_->compiled_module_->GetNativeModule()
->compilation_state() ->compilation_state()
->compile_mode() == CompileMode::kRegular || ->compile_mode() == CompileMode::kRegular ||
...@@ -3301,6 +3300,7 @@ bool AsyncStreamingProcessor::ProcessModuleHeader(Vector<const uint8_t> bytes, ...@@ -3301,6 +3300,7 @@ bool AsyncStreamingProcessor::ProcessModuleHeader(Vector<const uint8_t> bytes,
uint32_t offset) { uint32_t offset) {
TRACE_STREAMING("Process module header...\n"); TRACE_STREAMING("Process module header...\n");
decoder_.StartDecoding(job_->isolate()); decoder_.StartDecoding(job_->isolate());
job_->module_ = decoder_.shared_module();
decoder_.DecodeModuleHeader(bytes, offset); decoder_.DecodeModuleHeader(bytes, offset);
if (!decoder_.ok()) { if (!decoder_.ok()) {
FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false)); FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
...@@ -3351,8 +3351,7 @@ bool AsyncStreamingProcessor::ProcessCodeSectionHeader(size_t functions_count, ...@@ -3351,8 +3351,7 @@ bool AsyncStreamingProcessor::ProcessCodeSectionHeader(size_t functions_count,
FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false)); FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
return false; return false;
} }
job_->NextStep<AsyncCompileJob::PrepareAndStartCompile>(decoder_.module(), job_->NextStep<AsyncCompileJob::PrepareAndStartCompile>(false);
false);
// Execute the PrepareAndStartCompile step immediately and not in a separate // Execute the PrepareAndStartCompile step immediately and not in a separate
// task. The step expects to be run on a separate foreground thread though, so // task. The step expects to be run on a separate foreground thread though, so
// we to increment {num_pending_foreground_tasks_} to look like one. // we to increment {num_pending_foreground_tasks_} to look like one.
...@@ -3409,15 +3408,14 @@ void AsyncStreamingProcessor::OnFinishedStream(std::unique_ptr<uint8_t[]> bytes, ...@@ -3409,15 +3408,14 @@ void AsyncStreamingProcessor::OnFinishedStream(std::unique_ptr<uint8_t[]> bytes,
job_->bytes_copy_.get() + length); job_->bytes_copy_.get() + length);
ModuleResult result = decoder_.FinishDecoding(false); ModuleResult result = decoder_.FinishDecoding(false);
DCHECK(result.ok()); DCHECK(result.ok());
job_->module_ = std::move(result.val); DCHECK_EQ(job_->module_, result.val);
if (job_->DecrementAndCheckFinisherCount()) { if (job_->DecrementAndCheckFinisherCount()) {
if (job_->compiled_module_.is_null()) { if (job_->compiled_module_.is_null()) {
// We are processing a WebAssembly module without code section. We need to // We are processing a WebAssembly module without code section. We need to
// prepare compilation first before we can finish it. // prepare compilation first before we can finish it.
// {PrepareAndStartCompile} will call {FinishCompile} by itself if there // {PrepareAndStartCompile} will call {FinishCompile} by itself if there
// is no code section. // is no code section.
job_->DoSync<AsyncCompileJob::PrepareAndStartCompile>(job_->module_.get(), job_->DoSync<AsyncCompileJob::PrepareAndStartCompile>(true);
true);
} else { } else {
job_->FinishCompile(); job_->FinishCompile();
} }
......
...@@ -47,7 +47,7 @@ std::unique_ptr<CompilationState, CompilationStateDeleter> NewCompilationState( ...@@ -47,7 +47,7 @@ std::unique_ptr<CompilationState, CompilationStateDeleter> NewCompilationState(
ModuleEnv* GetModuleEnv(CompilationState* compilation_state); ModuleEnv* GetModuleEnv(CompilationState* compilation_state);
MaybeHandle<WasmModuleObject> CompileToModuleObject( MaybeHandle<WasmModuleObject> CompileToModuleObject(
Isolate* isolate, ErrorThrower* thrower, std::unique_ptr<WasmModule> module, Isolate* isolate, ErrorThrower* thrower, std::shared_ptr<WasmModule> module,
const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script, const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script,
Vector<const byte> asm_js_offset_table_bytes); Vector<const byte> asm_js_offset_table_bytes);
...@@ -150,7 +150,7 @@ class AsyncCompileJob { ...@@ -150,7 +150,7 @@ class AsyncCompileJob {
ModuleWireBytes wire_bytes_; ModuleWireBytes wire_bytes_;
Handle<Context> context_; Handle<Context> context_;
std::unique_ptr<CompilationResultResolver> resolver_; std::unique_ptr<CompilationResultResolver> resolver_;
std::unique_ptr<WasmModule> module_; std::shared_ptr<WasmModule> module_;
std::vector<DeferredHandles*> deferred_handles_; std::vector<DeferredHandles*> deferred_handles_;
Handle<WasmCompiledModule> compiled_module_; Handle<WasmCompiledModule> compiled_module_;
......
...@@ -893,9 +893,9 @@ class ModuleDecoderImpl : public Decoder { ...@@ -893,9 +893,9 @@ class ModuleDecoderImpl : public Decoder {
return consume_init_expr(nullptr, kWasmStmt); return consume_init_expr(nullptr, kWasmStmt);
} }
WasmModule* module() { return module_.get(); } const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
Counters* GetCounters() { Counters* GetCounters() const {
DCHECK_NOT_NULL(counters_); DCHECK_NOT_NULL(counters_);
return counters_; return counters_;
} }
...@@ -906,7 +906,7 @@ class ModuleDecoderImpl : public Decoder { ...@@ -906,7 +906,7 @@ class ModuleDecoderImpl : public Decoder {
} }
private: private:
std::unique_ptr<WasmModule> module_; std::shared_ptr<WasmModule> module_;
Counters* counters_ = nullptr; Counters* counters_ = nullptr;
// The type section is the first section in a module. // The type section is the first section in a module.
uint8_t next_section_ = kFirstSectionInModule; uint8_t next_section_ = kFirstSectionInModule;
...@@ -1358,7 +1358,9 @@ ModuleResult DecodeWasmModule(Isolate* isolate, const byte* module_start, ...@@ -1358,7 +1358,9 @@ ModuleResult DecodeWasmModule(Isolate* isolate, const byte* module_start,
ModuleDecoder::ModuleDecoder() = default; ModuleDecoder::ModuleDecoder() = default;
ModuleDecoder::~ModuleDecoder() = default; ModuleDecoder::~ModuleDecoder() = default;
WasmModule* ModuleDecoder::module() const { return impl_->module(); } const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
return impl_->shared_module();
}
void ModuleDecoder::StartDecoding(Isolate* isolate, ModuleOrigin origin) { void ModuleDecoder::StartDecoding(Isolate* isolate, ModuleOrigin origin) {
DCHECK_NULL(impl_); DCHECK_NULL(impl_);
......
...@@ -23,7 +23,7 @@ inline bool IsValidSectionCode(uint8_t byte) { ...@@ -23,7 +23,7 @@ inline bool IsValidSectionCode(uint8_t byte) {
const char* SectionName(SectionCode code); const char* SectionName(SectionCode code);
typedef Result<std::unique_ptr<WasmModule>> ModuleResult; typedef Result<std::shared_ptr<WasmModule>> ModuleResult;
typedef Result<std::unique_ptr<WasmFunction>> FunctionResult; typedef Result<std::unique_ptr<WasmFunction>> FunctionResult;
typedef std::vector<std::pair<int, int>> FunctionOffsets; typedef std::vector<std::pair<int, int>> FunctionOffsets;
typedef Result<FunctionOffsets> FunctionOffsetsResult; typedef Result<FunctionOffsets> FunctionOffsetsResult;
...@@ -138,7 +138,8 @@ class ModuleDecoder { ...@@ -138,7 +138,8 @@ class ModuleDecoder {
ModuleResult FinishDecoding(bool verify_functions = true); ModuleResult FinishDecoding(bool verify_functions = true);
WasmModule* module() const; const std::shared_ptr<WasmModule>& shared_module() const;
WasmModule* module() const { return shared_module().get(); }
bool ok(); bool ok();
......
...@@ -215,8 +215,7 @@ size_t GetFunctionOffset(i::Isolate* isolate, const uint8_t* buffer, ...@@ -215,8 +215,7 @@ size_t GetFunctionOffset(i::Isolate* isolate, const uint8_t* buffer,
ModuleResult result = SyncDecodeWasmModule(isolate, buffer, buffer + size, ModuleResult result = SyncDecodeWasmModule(isolate, buffer, buffer + size,
false, ModuleOrigin::kWasmOrigin); false, ModuleOrigin::kWasmOrigin);
CHECK(result.ok()); CHECK(result.ok());
std::unique_ptr<WasmModule> module = std::move(result.val); const WasmFunction* func = &result.val->functions[1];
const WasmFunction* func = &module->functions[1];
return func->code.offset(); return func->code.offset();
} }
......
...@@ -37,7 +37,7 @@ MaybeHandle<WasmInstanceObject> CompileAndInstantiateForTesting( ...@@ -37,7 +37,7 @@ MaybeHandle<WasmInstanceObject> CompileAndInstantiateForTesting(
isolate, thrower, module.ToHandleChecked(), {}, {}); isolate, thrower, module.ToHandleChecked(), {}, {});
} }
std::unique_ptr<WasmModule> DecodeWasmModuleForTesting( std::shared_ptr<WasmModule> DecodeWasmModuleForTesting(
Isolate* isolate, ErrorThrower* thrower, const byte* module_start, Isolate* isolate, ErrorThrower* thrower, const byte* module_start,
const byte* module_end, ModuleOrigin origin, bool verify_functions) { const byte* module_end, ModuleOrigin origin, bool verify_functions) {
// Decode the module, but don't verify function bodies, since we'll // Decode the module, but don't verify function bodies, since we'll
......
...@@ -26,7 +26,7 @@ namespace wasm { ...@@ -26,7 +26,7 @@ namespace wasm {
namespace testing { namespace testing {
// Decodes the given encoded module. // Decodes the given encoded module.
std::unique_ptr<WasmModule> DecodeWasmModuleForTesting( std::shared_ptr<WasmModule> DecodeWasmModuleForTesting(
Isolate* isolate, ErrorThrower* thrower, const byte* module_start, Isolate* isolate, ErrorThrower* thrower, const byte* module_start,
const byte* module_end, ModuleOrigin origin, bool verify_functions = false); const byte* module_end, ModuleOrigin origin, bool verify_functions = false);
......
...@@ -59,8 +59,8 @@ int FuzzWasmSection(SectionCode section, const uint8_t* data, size_t size) { ...@@ -59,8 +59,8 @@ int FuzzWasmSection(SectionCode section, const uint8_t* data, size_t size) {
ErrorThrower thrower(i_isolate, "decoder"); ErrorThrower thrower(i_isolate, "decoder");
std::unique_ptr<const WasmModule> module(testing::DecodeWasmModuleForTesting( testing::DecodeWasmModuleForTesting(i_isolate, &thrower, buffer.begin(),
i_isolate, &thrower, buffer.begin(), buffer.end(), kWasmOrigin)); buffer.end(), kWasmOrigin);
return 0; return 0;
} }
......
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