[wasm] Support multi-return WASM function calls from JS
Calling a multi-return WASM function from JS creates an array filled with the returned values. See: https://github.com/WebAssembly/multi-value R=ahaas@chromium.org Bug: v8:9492 Change-Id: I3151212b6784782c8f89908befab9d26b32e5a8b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1739372 Commit-Queue: Thibaud Michaud <thibaudm@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#63110}
This commit is contained in:
parent
42fd0bfd39
commit
179ed98857
@ -5606,9 +5606,25 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
// Clear the ThreadInWasm flag.
|
||||
BuildModifyThreadInWasmFlag(false);
|
||||
|
||||
Node* jsval = sig_->return_count() == 0
|
||||
? BuildLoadUndefinedValueFromInstance()
|
||||
: ToJS(rets[0], sig_->GetReturn());
|
||||
Node* jsval;
|
||||
if (sig_->return_count() == 0) {
|
||||
jsval = BuildLoadUndefinedValueFromInstance();
|
||||
} else if (sig_->return_count() == 1) {
|
||||
jsval = ToJS(rets[0], sig_->GetReturn());
|
||||
} else {
|
||||
int32_t return_count = static_cast<int32_t>(sig_->return_count());
|
||||
Node* size = jsgraph()->SmiConstant(return_count);
|
||||
// TODO(thibaudm): Replace runtime calls with TurboFan code.
|
||||
Node* fixed_array =
|
||||
BuildCallToRuntime(Runtime::kWasmNewMultiReturnFixedArray, &size, 1);
|
||||
for (int i = 0; i < return_count; ++i) {
|
||||
Node* value = ToJS(rets[i], sig_->GetReturn(i));
|
||||
STORE_FIXED_ARRAY_SLOT_ANY(fixed_array, i, value);
|
||||
}
|
||||
jsval = BuildCallToRuntimeWithContext(Runtime::kWasmNewMultiReturnJSArray,
|
||||
js_context, &fixed_array, 1,
|
||||
effect_, Control());
|
||||
}
|
||||
Return(jsval);
|
||||
}
|
||||
|
||||
|
@ -568,5 +568,24 @@ RUNTIME_FUNCTION(Runtime_WasmTableFill) {
|
||||
}
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_WasmNewMultiReturnFixedArray) {
|
||||
DCHECK_EQ(1, args.length());
|
||||
HandleScope scope(isolate);
|
||||
CONVERT_INT32_ARG_CHECKED(size, 0);
|
||||
Handle<FixedArray> fixed_array = isolate->factory()->NewFixedArray(size);
|
||||
return *fixed_array;
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_WasmNewMultiReturnJSArray) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
DCHECK(!isolate->context().is_null());
|
||||
CONVERT_ARG_CHECKED(FixedArray, fixed_array, 0);
|
||||
Handle<FixedArray> fixed_array_handle(fixed_array, isolate);
|
||||
Handle<JSArray> array = isolate->factory()->NewJSArrayWithElements(
|
||||
fixed_array_handle, PACKED_ELEMENTS);
|
||||
return *array;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -529,28 +529,30 @@ namespace internal {
|
||||
F(TypedArraySet, 2, 1) \
|
||||
F(TypedArraySortFast, 1, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_WASM(F, I) \
|
||||
F(ThrowWasmError, 1, 1) \
|
||||
F(ThrowWasmStackOverflow, 0, 1) \
|
||||
F(WasmI32AtomicWait, 4, 1) \
|
||||
F(WasmI64AtomicWait, 5, 1) \
|
||||
F(WasmAtomicNotify, 3, 1) \
|
||||
F(WasmExceptionGetValues, 1, 1) \
|
||||
F(WasmExceptionGetTag, 1, 1) \
|
||||
F(WasmMemoryGrow, 2, 1) \
|
||||
F(WasmRunInterpreter, 2, 1) \
|
||||
F(WasmStackGuard, 0, 1) \
|
||||
F(WasmThrowCreate, 2, 1) \
|
||||
F(WasmThrowTypeError, 0, 1) \
|
||||
F(WasmRefFunc, 1, 1) \
|
||||
F(WasmFunctionTableGet, 3, 1) \
|
||||
F(WasmFunctionTableSet, 4, 1) \
|
||||
F(WasmTableInit, 5, 1) \
|
||||
F(WasmTableCopy, 5, 1) \
|
||||
F(WasmTableGrow, 3, 1) \
|
||||
F(WasmTableFill, 4, 1) \
|
||||
F(WasmIsValidFuncRefValue, 1, 1) \
|
||||
F(WasmCompileLazy, 2, 1)
|
||||
#define FOR_EACH_INTRINSIC_WASM(F, I) \
|
||||
F(ThrowWasmError, 1, 1) \
|
||||
F(ThrowWasmStackOverflow, 0, 1) \
|
||||
F(WasmI32AtomicWait, 4, 1) \
|
||||
F(WasmI64AtomicWait, 5, 1) \
|
||||
F(WasmAtomicNotify, 3, 1) \
|
||||
F(WasmExceptionGetValues, 1, 1) \
|
||||
F(WasmExceptionGetTag, 1, 1) \
|
||||
F(WasmMemoryGrow, 2, 1) \
|
||||
F(WasmRunInterpreter, 2, 1) \
|
||||
F(WasmStackGuard, 0, 1) \
|
||||
F(WasmThrowCreate, 2, 1) \
|
||||
F(WasmThrowTypeError, 0, 1) \
|
||||
F(WasmRefFunc, 1, 1) \
|
||||
F(WasmFunctionTableGet, 3, 1) \
|
||||
F(WasmFunctionTableSet, 4, 1) \
|
||||
F(WasmTableInit, 5, 1) \
|
||||
F(WasmTableCopy, 5, 1) \
|
||||
F(WasmTableGrow, 3, 1) \
|
||||
F(WasmTableFill, 4, 1) \
|
||||
F(WasmIsValidFuncRefValue, 1, 1) \
|
||||
F(WasmCompileLazy, 2, 1) \
|
||||
F(WasmNewMultiReturnFixedArray, 1, 1) \
|
||||
F(WasmNewMultiReturnJSArray, 1, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_RETURN_PAIR_IMPL(F, I) \
|
||||
F(DebugBreakOnBytecode, 1, 2) \
|
||||
|
@ -447,7 +447,7 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
|
||||
}
|
||||
|
||||
bool IsJSCompatibleSignature(const FunctionSig* sig, bool has_bigint_feature) {
|
||||
if (sig->return_count() > 1) {
|
||||
if (!FLAG_experimental_wasm_mv && sig->return_count() > 1) {
|
||||
return false;
|
||||
}
|
||||
for (auto type : sig->all()) {
|
||||
|
@ -319,3 +319,34 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
assertEquals(instance.exports.main(2), 8);
|
||||
assertEquals(instance.exports.main(10), 200);
|
||||
})();
|
||||
|
||||
(function MultiJSReturnTest() {
|
||||
print(arguments.callee.name);
|
||||
let builder = new WasmModuleBuilder();
|
||||
let sig_fi_if = makeSig([kWasmI32, kWasmF32], [kWasmF32, kWasmI32]);
|
||||
|
||||
builder.addFunction("swap", sig_fi_if)
|
||||
.addBody([
|
||||
kExprGetLocal, 1,
|
||||
kExprGetLocal, 0])
|
||||
.exportAs("swap");
|
||||
builder.addFunction("addsubmul", kSig_iii_i)
|
||||
.addBody([
|
||||
kExprGetLocal, 0,
|
||||
kExprGetLocal, 0,
|
||||
kExprI32Add,
|
||||
kExprGetLocal, 0,
|
||||
kExprGetLocal, 0,
|
||||
kExprI32Sub,
|
||||
kExprGetLocal, 0,
|
||||
kExprGetLocal, 0,
|
||||
kExprI32Mul])
|
||||
.exportAs("addsubmul");
|
||||
|
||||
let module = new WebAssembly.Module(builder.toBuffer());
|
||||
let instance = new WebAssembly.Instance(module);
|
||||
assertEquals(instance.exports.swap(0, 1.5), [1.5, 0]);
|
||||
assertEquals(instance.exports.swap(2, 3.75), [3.75, 2]);
|
||||
assertEquals(instance.exports.addsubmul(4), [8, 0, 16]);
|
||||
assertEquals(instance.exports.addsubmul(5), [10, 0, 25]);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user