[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: Ben Titzer <titzer@chromium.org> Cr-Commit-Position: refs/heads/master@{#53801}
This commit is contained in:
parent
e947d21e3d
commit
6be6ec0091
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user