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