[wasm] Suspend on other JS import kinds

The stack-switching variant of the wasm-to-js wrapper was only generated
for js functions with matching arity. Also suspend for js functions with
mismatching arity and unknown callables.

R=ahaas@chromium.org

Bug: v8:12191
Change-Id: Iab3e2d85210c86a814ae1defab9cd57bf74d80d2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3749578
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81605}
This commit is contained in:
Thibaud Michaud 2022-07-08 12:06:54 +02:00 committed by V8 LUCI CQ
parent 7ea0412e55
commit d9e44b2d9b
2 changed files with 33 additions and 11 deletions

View File

@ -7041,7 +7041,9 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
auto call_descriptor = Linkage::GetJSCallDescriptor(
graph()->zone(), false, pushed_count + 1, CallDescriptor::kNoFlags);
call = gasm_->Call(call_descriptor, pos, args.begin());
// TODO(12191): Handle suspending wrapper.
if (suspend == wasm::kSuspend) {
call = BuildSuspend(call, Param(0));
}
break;
}
// =======================================================================
@ -7077,7 +7079,9 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
DCHECK_EQ(pos, args.size());
call = gasm_->Call(call_descriptor, pos, args.begin());
// TODO(12191): Handle suspending wrapper.
if (suspend == wasm::kSuspend) {
call = BuildSuspend(call, Param(0));
}
break;
}
default:

View File

@ -93,18 +93,36 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
kExprCallFunction, import_index, // suspend
]).exportFunc();
let suspender = new WebAssembly.Suspender();
function js_import() {
return Promise.resolve(42);
};
let wasm_js_import = new WebAssembly.Function(
{parameters: [], results: ['externref']}, js_import);
let suspending_wasm_js_import =
suspender.suspendOnReturnedPromise(wasm_js_import);
let instance = builder.instantiate({m: {import: suspending_wasm_js_import}});
let js_import = suspender.suspendOnReturnedPromise(
new WebAssembly.Function(
{parameters: [], results: ['externref']},
() => Promise.resolve(42)));
let instance = builder.instantiate({m: {import: js_import}});
let wrapped_export = suspender.returnPromiseOnSuspend(instance.exports.test);
let combined_promise = wrapped_export();
combined_promise.then(v => assertEquals(42, v));
// Also try with a JS function with a mismatching arity.
suspender = new WebAssembly.Suspender();
js_import = suspender.suspendOnReturnedPromise(
new WebAssembly.Function(
{parameters: [], results: ['externref']},
(unused) => Promise.resolve(42)));
instance = builder.instantiate({m: {import: js_import}});
wrapped_export = suspender.returnPromiseOnSuspend(instance.exports.test);
combined_promise = wrapped_export();
combined_promise.then(v => assertEquals(42, v));
// Also try with a proxy.
suspender = new WebAssembly.Suspender();
js_import = suspender.suspendOnReturnedPromise(
new WebAssembly.Function(
{parameters: [], results: ['externref']},
new Proxy(() => Promise.resolve(42), {})));
instance = builder.instantiate({m: {import: js_import}});
wrapped_export = suspender.returnPromiseOnSuspend(instance.exports.test);
combined_promise = wrapped_export();
combined_promise.then(v => assertEquals(42, v));
})();
// Check that we can suspend back out of a resumed computation.