Skip to content

Commit 49712d8

Browse files
gahaasCommit Bot
authored andcommitted
[wasm] Call AsyncInstantiate directly when instantiating a module object
WebAssembly.instantiate is polymorphic, it can either take a module object as parameter, or a buffer source which should be compiled first. To share code between the two implementations, the module object was first passed to a promise (i.e. which is the result of compilation). However, passing the module object to a promise has a side effect if the module object has a then function. To avoid this side effect I remove this code sharing and call AsyncInstantiate directly in case the parameter is a module object. [email protected] Bug: chromium:836141 Change-Id: I67b76d0d7761c5aeb2cf1deda45b6842e494eed4 Reviewed-on: https://chromium-review.googlesource.com/1025774 Reviewed-by: Michael Starzinger <[email protected]> Commit-Queue: Andreas Haas <[email protected]> Cr-Commit-Position: refs/heads/master@{#52755}
1 parent ba86468 commit 49712d8

2 files changed

Lines changed: 53 additions & 39 deletions

File tree

src/wasm/wasm-js.cc

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -346,25 +346,7 @@ MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
346346
return Utils::ToLocal(instance_object.ToHandleChecked());
347347
}
348348

349-
// Entered as internal implementation detail of sync and async instantiate.
350-
// args[0] *must* be a WebAssembly.Module.
351-
void WebAssemblyInstantiateImplCallback(
352-
const v8::FunctionCallbackInfo<v8::Value>& args) {
353-
DCHECK_GE(args.Length(), 1);
354-
v8::Isolate* isolate = args.GetIsolate();
355-
MicrotasksScope does_not_run_microtasks(isolate,
356-
MicrotasksScope::kDoNotRunMicrotasks);
357-
358-
HandleScope scope(args.GetIsolate());
359-
Local<Value> module = args[0];
360-
Local<Value> ffi = args.Data();
361-
Local<Value> instance;
362-
if (WebAssemblyInstantiateImpl(isolate, module, ffi).ToLocal(&instance)) {
363-
args.GetReturnValue().Set(instance);
364-
}
365-
}
366-
367-
void WebAssemblyInstantiateToPairCallback(
349+
void WebAssemblyInstantiateCallback(
368350
const v8::FunctionCallbackInfo<v8::Value>& args) {
369351
DCHECK_GE(args.Length(), 1);
370352
Isolate* isolate = args.GetIsolate();
@@ -453,7 +435,7 @@ void WebAssemblyInstantiateStreaming(
453435
DCHECK(!module_promise.IsEmpty());
454436
Local<Value> data = args[1];
455437
ASSIGN(Function, instantiate_impl,
456-
Function::New(context, WebAssemblyInstantiateToPairCallback, data));
438+
Function::New(context, WebAssemblyInstantiateCallback, data));
457439
ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
458440
args.GetReturnValue().Set(result);
459441
}
@@ -475,10 +457,12 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
475457
Local<Context> context = isolate->GetCurrentContext();
476458

477459
ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
478-
Local<Promise> module_promise = resolver->GetPromise();
479-
args.GetReturnValue().Set(module_promise);
460+
Local<Promise> promise = resolver->GetPromise();
461+
args.GetReturnValue().Set(promise);
480462

481463
Local<Value> first_arg_value = args[0];
464+
// If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
465+
Local<Value> ffi = args[1];
482466
i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
483467
if (!first_arg->IsJSObject()) {
484468
thrower.TypeError(
@@ -489,26 +473,35 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
489473
return;
490474
}
491475

492-
FunctionCallback instantiator = nullptr;
493476
if (first_arg->IsWasmModuleObject()) {
494-
module_promise = resolver->GetPromise();
495-
if (!resolver->Resolve(context, first_arg_value).IsJust()) return;
496-
instantiator = WebAssemblyInstantiateImplCallback;
497-
} else {
498-
ASSIGN(Function, async_compile, Function::New(context, WebAssemblyCompile));
499-
ASSIGN(Value, async_compile_retval,
500-
async_compile->Call(context, args.Holder(), 1, &first_arg_value));
501-
module_promise = Local<Promise>::Cast(async_compile_retval);
502-
instantiator = WebAssemblyInstantiateToPairCallback;
477+
i::Handle<i::WasmModuleObject> module_obj =
478+
i::Handle<i::WasmModuleObject>::cast(first_arg);
479+
// If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
480+
i::MaybeHandle<i::JSReceiver> maybe_imports =
481+
GetValueAsImports(ffi, &thrower);
482+
483+
if (thrower.error()) {
484+
auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
485+
CHECK_IMPLIES(!maybe.FromMaybe(false),
486+
i_isolate->has_scheduled_exception());
487+
return;
488+
}
489+
490+
i_isolate->wasm_engine()->AsyncInstantiate(
491+
i_isolate, Utils::OpenHandle(*promise), module_obj, maybe_imports);
492+
return;
503493
}
504-
DCHECK(!module_promise.IsEmpty());
505-
DCHECK_NOT_NULL(instantiator);
506-
// If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
507-
// We'll check for that in WebAssemblyInstantiateImpl.
508-
Local<Value> data = args[1];
494+
495+
// We did not get a WasmModuleObject as input, we first have to compile the
496+
// input.
497+
ASSIGN(Function, async_compile, Function::New(context, WebAssemblyCompile));
498+
ASSIGN(Value, async_compile_retval,
499+
async_compile->Call(context, args.Holder(), 1, &first_arg_value));
500+
promise = Local<Promise>::Cast(async_compile_retval);
501+
DCHECK(!promise.IsEmpty());
509502
ASSIGN(Function, instantiate_impl,
510-
Function::New(context, instantiator, data));
511-
ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
503+
Function::New(context, WebAssemblyInstantiateCallback, ffi));
504+
ASSIGN(Promise, result, promise->Then(context, instantiate_impl));
512505
args.GetReturnValue().Set(result);
513506
}
514507

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
load('test/mjsunit/wasm/wasm-constants.js');
6+
load('test/mjsunit/wasm/wasm-module-builder.js');
7+
8+
const builder = new WasmModuleBuilder();
9+
builder.addMemory(16, 32);
10+
builder.addFunction("test", kSig_i_v).addBody([
11+
kExprI32Const, 12, // i32.const 0
12+
]);
13+
14+
let bla = 0;
15+
let module = new WebAssembly.Module(builder.toBuffer());
16+
module.then = () => {
17+
// Use setTimeout to get out of the promise chain.
18+
setTimeout(assertUnreachable);
19+
};
20+
21+
WebAssembly.instantiate(module);

0 commit comments

Comments
 (0)