Commit ecbf6296 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Fix streaming instantiation with no code section

Because of ordering issues we didn't set the wire bytes on the
{NativeModule} during {OnFinishedStream}. We then failed during
instantiation when trying to read the import names from the wire bytes.

This CL fixes this locally without much code churn. I plan to clean up
the interaction between {AsyncCompileJob} and {AsyncStreamingProcessor}
in a follow-up CL.

R=ahaas@chromium.org

Bug: chromium:898310
Change-Id: I06337a04ba380f87b803f325323208298d363f41
Reviewed-on: https://chromium-review.googlesource.com/c/1296467Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56938}
parent 2bb47567
......@@ -2365,12 +2365,6 @@ void AsyncCompileJob::CancelPendingForegroundTask() {
pending_foreground_task_ = nullptr;
}
template <typename Step, typename... Args>
void AsyncCompileJob::DoSync(Args&&... args) {
NextStep<Step>(std::forward<Args>(args)...);
StartForegroundTask();
}
void AsyncCompileJob::StartBackgroundTask() {
auto task = base::make_unique<CompileTask>(this, false);
......@@ -2383,6 +2377,18 @@ void AsyncCompileJob::StartBackgroundTask() {
}
}
template <typename Step, typename... Args>
void AsyncCompileJob::DoSync(Args&&... args) {
NextStep<Step>(std::forward<Args>(args)...);
StartForegroundTask();
}
template <typename Step, typename... Args>
void AsyncCompileJob::DoImmediately(Args&&... args) {
NextStep<Step>(std::forward<Args>(args)...);
ExecuteForegroundTaskImmediately();
}
template <typename Step, typename... Args>
void AsyncCompileJob::DoAsync(Args&&... args) {
NextStep<Step>(std::forward<Args>(args)...);
......@@ -2726,11 +2732,10 @@ bool AsyncStreamingProcessor::ProcessCodeSectionHeader(size_t functions_count,
FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
return false;
}
job_->NextStep<AsyncCompileJob::PrepareAndStartCompile>(
decoder_.shared_module(), false);
// Execute the PrepareAndStartCompile step immediately and not in a separate
// task.
job_->ExecuteForegroundTaskImmediately();
job_->DoImmediately<AsyncCompileJob::PrepareAndStartCompile>(
decoder_.shared_module(), false);
job_->native_module_->compilation_state()->SetNumberOfFunctionsToCompile(
functions_count);
......@@ -2773,26 +2778,26 @@ void AsyncStreamingProcessor::OnFinishedChunk() {
// Finish the processing of the stream.
void AsyncStreamingProcessor::OnFinishedStream(OwnedVector<uint8_t> bytes) {
TRACE_STREAMING("Finish stream...\n");
if (job_->native_module_) {
job_->wire_bytes_ = ModuleWireBytes(bytes.as_vector());
job_->native_module_->set_wire_bytes(std::move(bytes));
}
ModuleResult result = decoder_.FinishDecoding(false);
DCHECK(result.ok());
if (job_->DecrementAndCheckFinisherCount()) {
if (job_->native_module_ == nullptr) {
// 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>(
std::move(result).value(), true);
} else {
HandleScope scope(job_->isolate_);
SaveContext saved_context(job_->isolate_);
job_->isolate_->set_context(*job_->native_context_);
job_->FinishCompile(true);
}
bool needs_finish = job_->DecrementAndCheckFinisherCount();
if (job_->native_module_ == nullptr) {
// 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.
DCHECK(needs_finish);
needs_finish = false;
job_->DoImmediately<AsyncCompileJob::PrepareAndStartCompile>(
std::move(result).value(), true);
}
job_->wire_bytes_ = ModuleWireBytes(bytes.as_vector());
job_->native_module_->set_wire_bytes(std::move(bytes));
if (needs_finish) {
HandleScope scope(job_->isolate_);
SaveContext saved_context(job_->isolate_);
job_->isolate_->set_context(*job_->native_context_);
job_->FinishCompile(true);
}
}
......
......@@ -116,6 +116,10 @@ class AsyncCompileJob {
template <typename Step, typename... Args>
void DoSync(Args&&... args);
// Switches to the compilation step {Step} and immediately executes that step.
template <typename Step, typename... Args>
void DoImmediately(Args&&... args);
// Switches to the compilation step {Step} and starts a background task to
// execute it.
template <typename Step, typename... Args>
......
......@@ -70,3 +70,10 @@ assertPromiseResult(async function badFunctionInTheMiddle() {
let buffer = builder.toBuffer();
await assertCompileError(buffer);
}());
assertPromiseResult(async function importWithoutCode() {
// Regression test for https://crbug.com/898310.
let builder = new WasmModuleBuilder();
builder.addImport('m', 'q', kSig_i_i);
await builder.asyncInstantiate({'m': {'q': i => i}});
}());
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