Commit 5c02c290 authored by Thibaud Michaud's avatar Thibaud Michaud Committed by V8 LUCI CQ

[wasm] Drop suspender param in wasm-to-JS wrapper

The suspender is only needed by the wrapper, do not forward it to the JS
import.

R=ahaas@chromium.org

Bug: v8:12191
Change-Id: Id8e9a820491588b40fffb5dfd8706e85a16b8b23
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3768410Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81818}
parent f7a73d8b
......@@ -6275,12 +6275,14 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
}
int AddArgumentNodes(base::Vector<Node*> args, int pos, int param_count,
const wasm::FunctionSig* sig, Node* context) {
const wasm::FunctionSig* sig, Node* context,
wasm::Suspend suspend) {
// Convert wasm numbers to JS values.
for (int i = 0; i < param_count; ++i) {
Node* param =
Param(i + 1); // Start from index 1 to drop the instance_node.
args[pos++] = ToJS(param, sig->GetParam(i), context);
// Drop the instance node, and possibly the suspender node.
int param_offset = 1 + suspend;
for (int i = 0; i < param_count - suspend; ++i) {
Node* param = Param(i + param_offset);
args[pos++] = ToJS(param, sig->GetParam(i + suspend), context);
}
return pos;
}
......@@ -7060,7 +7062,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// === JS Functions with matching arity ==================================
// =======================================================================
case WasmImportCallKind::kJSFunctionArityMatch: {
base::SmallVector<Node*, 16> args(wasm_count + 7);
base::SmallVector<Node*, 16> args(wasm_count + 7 - suspend);
int pos = 0;
Node* function_context =
gasm_->LoadContextFromJSFunction(callable_node);
......@@ -7071,15 +7073,16 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
BuildReceiverNode(callable_node, native_context, undefined_node);
auto call_descriptor = Linkage::GetJSCallDescriptor(
graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags);
graph()->zone(), false, wasm_count + 1 - suspend,
CallDescriptor::kNoFlags);
// Convert wasm numbers to JS values.
pos = AddArgumentNodes(base::VectorOf(args), pos, wasm_count, sig_,
native_context);
native_context, suspend);
args[pos++] = undefined_node; // new target
args[pos++] =
Int32Constant(JSParameterCount(wasm_count)); // argument count
args[pos++] = Int32Constant(
JSParameterCount(wasm_count - suspend)); // argument count
args[pos++] = function_context;
args[pos++] = effect();
args[pos++] = control();
......@@ -7095,7 +7098,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// === JS Functions with mismatching arity ===============================
// =======================================================================
case WasmImportCallKind::kJSFunctionArityMismatch: {
int pushed_count = std::max(expected_arity, wasm_count);
int pushed_count = std::max(expected_arity, wasm_count - suspend);
base::SmallVector<Node*, 16> args(pushed_count + 7);
int pos = 0;
......@@ -7106,13 +7109,13 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// Convert wasm numbers to JS values.
pos = AddArgumentNodes(base::VectorOf(args), pos, wasm_count, sig_,
native_context);
for (int i = wasm_count; i < expected_arity; ++i) {
native_context, suspend);
for (int i = wasm_count - suspend; i < expected_arity; ++i) {
args[pos++] = undefined_node;
}
args[pos++] = undefined_node; // new target
args[pos++] =
Int32Constant(JSParameterCount(wasm_count)); // argument count
args[pos++] = Int32Constant(
JSParameterCount(wasm_count - suspend)); // argument count
Node* function_context =
gasm_->LoadContextFromJSFunction(callable_node);
......@@ -7133,23 +7136,23 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// === General case of unknown callable ==================================
// =======================================================================
case WasmImportCallKind::kUseCallBuiltin: {
base::SmallVector<Node*, 16> args(wasm_count + 7);
base::SmallVector<Node*, 16> args(wasm_count + 7 - suspend);
int pos = 0;
args[pos++] =
gasm_->GetBuiltinPointerTarget(Builtin::kCall_ReceiverIsAny);
args[pos++] = callable_node;
args[pos++] =
Int32Constant(JSParameterCount(wasm_count)); // argument count
args[pos++] = Int32Constant(
JSParameterCount(wasm_count - suspend)); // argument count
args[pos++] = undefined_node; // receiver
auto call_descriptor = Linkage::GetStubCallDescriptor(
graph()->zone(), CallTrampolineDescriptor{}, wasm_count + 1,
CallDescriptor::kNoFlags, Operator::kNoProperties,
StubCallMode::kCallBuiltinPointer);
graph()->zone(), CallTrampolineDescriptor{},
wasm_count + 1 - suspend, CallDescriptor::kNoFlags,
Operator::kNoProperties, StubCallMode::kCallBuiltinPointer);
// Convert wasm numbers to JS values.
pos = AddArgumentNodes(base::VectorOf(args), pos, wasm_count, sig_,
native_context);
native_context, suspend);
// The native_context is sufficient here, because all kind of callables
// which depend on the context provide their own context. The context
......@@ -7450,7 +7453,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// Convert wasm numbers to JS values.
pos = AddArgumentNodes(base::VectorOf(args), pos, wasm_count, sig_,
native_context);
native_context, wasm::kNoSuspend);
// The native_context is sufficient here, because all kind of
// callables which depend on the context provide their own context.
......@@ -7934,7 +7937,7 @@ WasmImportData ResolveWasmImportCall(
}
if (shared->internal_formal_parameter_count_without_receiver() ==
expected_sig->parameter_count()) {
expected_sig->parameter_count() - suspend) {
return {WasmImportCallKind::kJSFunctionArityMatch, callable, suspend};
}
......
......@@ -1692,6 +1692,7 @@ Handle<WasmJSFunctionData> Factory::NewWasmJSFunctionData(
result.set_serialized_return_count(return_count);
result.set_serialized_parameter_count(parameter_count);
result.set_serialized_signature(*serialized_sig);
result.set_suspend(suspend);
return handle(result, isolate());
}
......
......@@ -2036,6 +2036,22 @@ void WebAssemblyFunctionType(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
} else if (i::WasmJSFunction::IsWasmJSFunction(*arg0)) {
sig = i::Handle<i::WasmJSFunction>::cast(arg0)->GetSignature(&zone);
auto wasm_js_function = i::Handle<i::WasmJSFunction>::cast(arg0);
if (wasm_js_function->shared().wasm_js_function_data().suspend()) {
// If this function is the result of calling
// WebAssembly.suspendOnReturnedPromise(), it takes an extra suspender
// parameter which will be consumed by the wasm-to-JS wrapper.
size_t param_count = sig->parameter_count();
i::wasm::FunctionSig::Builder builder(&zone, 1, param_count + 1);
builder.AddParam(internal::wasm::kWasmAnyRef);
for (size_t i = 0; i < param_count; ++i) {
builder.AddParam(sig->GetParam(i));
}
DCHECK_EQ(1, sig->return_count());
DCHECK_EQ(i::wasm::kWasmAnyRef, sig->GetReturn(0));
builder.AddReturn(i::wasm::kWasmAnyRef);
sig = builder.Build();
}
} else {
thrower.TypeError("Argument 0 must be a WebAssembly.Function");
return;
......@@ -2781,11 +2797,6 @@ void WebAssemblySuspendOnReturnedPromise(
return;
}
sig = i::Handle<i::WasmJSFunction>::cast(arg0)->GetSignature(&zone);
if (sig->parameter_count() == 0 || sig->GetParam(0) != i::wasm::kWasmAnyRef) {
thrower.TypeError("Expected at least one parameter of type %s",
i::wasm::kWasmAnyRef.name().c_str());
return;
}
if (sig->return_count() != 1 || sig->GetReturn(0) != i::wasm::kWasmAnyRef) {
thrower.TypeError("Expected a WebAssembly.Function with return type %s",
i::wasm::kWasmAnyRef.name().c_str());
......
......@@ -2165,22 +2165,22 @@ bool WasmJSFunction::MatchesSignatureForSuspend(const wasm::FunctionSig* sig) {
DCHECK_LE(sig->all().size(), kMaxInt);
int sig_size = static_cast<int>(sig->all().size());
int parameter_count = static_cast<int>(sig->parameter_count());
int return_count = static_cast<int>(sig->return_count());
DisallowHeapAllocation no_alloc;
WasmJSFunctionData function_data = shared().wasm_js_function_data();
if (parameter_count != function_data.serialized_parameter_count()) {
// The suspender parameter is not forwarded to the JS function so the
// parameter count should differ by one.
if (parameter_count != function_data.serialized_parameter_count() + 1) {
return false;
}
if (sig_size == 0) return true; // Prevent undefined behavior.
// This function is only called for functions wrapped by a
// WebAssembly.Suspender object, so the return type has to be externref.
// This function is only called for functions wrapped by
// WebAssembly.suspendOnReturnedPromise, so the return type has to be
// externref.
CHECK_EQ(function_data.serialized_return_count(), 1);
CHECK_EQ(function_data.serialized_signature().get(0), wasm::kWasmAnyRef);
CHECK_GE(sig->parameter_count(), 1);
CHECK_EQ(sig->GetParam(0), wasm::kWasmAnyRef);
const wasm::ValueType* expected = sig->all().begin();
return function_data.serialized_signature().matches(
1, expected + return_count, parameter_count);
const wasm::ValueType* expected = sig->parameters().begin() + 1;
return function_data.serialized_signature().matches(1, expected,
parameter_count - 1);
}
// TODO(9495): Update this if function type variance is introduced.
......
......@@ -76,6 +76,9 @@ extern class WasmJSFunctionData extends WasmFunctionData {
serialized_return_count: Smi;
serialized_parameter_count: Smi;
serialized_signature: PodArrayOfWasmValueType;
// Whether this function is the result of wrapping another function with
// WebAssembly.suspendOnReturnedPromise.
suspend: Smi;
}
extern class WasmCapiFunctionData extends WasmFunctionData {
......
This diff is collapsed.
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