Commit d7bd2926 authored by snek's avatar snek Committed by V8 LUCI CQ

[fastcall] combine wasm and js fast call builder

A lot of logic is missing from the Wasm entry for fast api calls.
The majority of the lowering is shared between wasm and js, and uses
the same graph operators, so this adds a common fast api call builder
which can be called from the wasm compiler and the js compiler.

Bug: chromium:1052746
Change-Id: I9dbd82548951b2b155a7b2459714239d0b251d71
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3708842
Commit-Queue: snek <snek@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81315}
parent 5fd99133
This diff is collapsed.
This diff is collapsed.
......@@ -34,6 +34,8 @@ struct OverloadsResolutionResult {
// The element type in the typed array argument.
CTypeInfo::Type element_type;
Node* target_address = nullptr;
};
ElementsKind GetTypedArrayElementsKind(CTypeInfo::Type type);
......@@ -44,6 +46,19 @@ OverloadsResolutionResult ResolveOverloads(
bool CanOptimizeFastSignature(const CFunctionInfo* c_signature);
using GetParameter = std::function<Node*(int, OverloadsResolutionResult&,
GraphAssemblerLabel<0>*)>;
using ConvertReturnValue = std::function<Node*(const CFunctionInfo*, Node*)>;
using GenerateSlowApiCall = std::function<Node*()>;
Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
GraphAssembler* graph_assembler,
const FastApiCallFunctionVector& c_functions,
const CFunctionInfo* c_signature, Node* data_argument,
const GetParameter& get_parameter,
const ConvertReturnValue& convert_return_value,
const GenerateSlowApiCall& generate_slow_api_call);
} // namespace fast_api_call
} // namespace compiler
} // namespace internal
......
......@@ -2004,12 +2004,6 @@ const Operator* SimplifiedOperatorBuilder::FastApiCall(
FastApiCallParameters(c_functions, feedback, descriptor));
}
int FastApiCallNode::FastCallExtraInputCount() const {
const CFunctionInfo* signature = Parameters().c_functions()[0].signature;
CHECK_NOT_NULL(signature);
return kEffectAndControlInputCount + (signature->HasOptions() ? 1 : 0);
}
int FastApiCallNode::FastCallArgumentCount() const {
FastApiCallParameters p = FastApiCallParametersOf(node()->op());
const CFunctionInfo* signature = p.c_functions()[0].signature;
......
......@@ -1156,7 +1156,6 @@ class FastApiCallNode final : public SimplifiedNodeWrapperBase {
static constexpr int kHolderInputCount = 1;
static constexpr int kContextAndFrameStateInputCount = 2;
static constexpr int kEffectAndControlInputCount = 2;
int FastCallExtraInputCount() const;
static constexpr int kSlowCallExtraInputCount =
kSlowTargetInputCount + kArityInputCount + kNewTargetInputCount +
kSlowReceiverInputCount + kHolderInputCount +
......
This diff is collapsed.
......@@ -135,7 +135,7 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::NativeModule*,
// Compiles a wrapper to call a Fast API function from Wasm.
wasm::WasmCode* CompileWasmJSFastCallWrapper(wasm::NativeModule*,
const wasm::FunctionSig*,
Handle<JSFunction> target);
Handle<JSReceiver> callable);
// Returns an TurbofanCompilationJob object for a JS to Wasm wrapper.
std::unique_ptr<TurbofanCompilationJob> NewJSToWasmCompilationJob(
......
......@@ -821,6 +821,13 @@ Local<FunctionTemplate> Shell::CreateTestFastCApiTemplate(Isolate* isolate) {
signature, 1, ConstructorBehavior::kThrow,
SideEffectType::kHasSideEffect, {c_function_overloads, 2}));
api_obj_ctor->PrototypeTemplate()->Set(
isolate, "overloaded_add_all_32bit_int_no_sig",
FunctionTemplate::NewWithCFunctionOverloads(
isolate, FastCApiObject::AddAll32BitIntSlowCallback, Local<Value>(),
Local<Signature>(), 1, ConstructorBehavior::kThrow,
SideEffectType::kHasSideEffect, {c_function_overloads, 2}));
CFunction add_all_no_options_c_func = CFunction::Make(
FastCApiObject::AddAllFastCallbackNoOptions V8_IF_USE_SIMULATOR(
FastCApiObject::AddAllFastCallbackNoOptionsPatch));
......
......@@ -1125,12 +1125,10 @@ bool InstanceBuilder::ProcessImportedFunction(
}
case compiler::WasmImportCallKind::kWasmToJSFastApi: {
NativeModule* native_module = instance->module_object().native_module();
DCHECK(js_receiver->IsJSFunction());
Handle<JSFunction> function = Handle<JSFunction>::cast(js_receiver);
DCHECK(js_receiver->IsJSFunction() || js_receiver->IsJSBoundFunction());
WasmCodeRefScope code_ref_scope;
WasmCode* wasm_code = compiler::CompileWasmJSFastCallWrapper(
native_module, expected_sig, function);
native_module, expected_sig, js_receiver);
ImportedFunctionEntry entry(instance, func_index);
entry.SetWasmToJs(isolate_, js_receiver, wasm_code,
isolate_->factory()->undefined_value());
......
......@@ -35,12 +35,21 @@ function buildWasm(name, sig, body) {
[kWasmF64],
),
);
const overloaded_add_all_32bit_int = builder.addImport(
'fast_c_api',
'overloaded_add_all_32bit_int',
makeSig(
[kWasmI32, kWasmI32, kWasmI32, kWasmI32, kWasmI32, kWasmI32, kWasmI32],
[kWasmI32],
),
);
builder
.addFunction(name, sig)
.addBody(body({
add_all_no_options,
add_all_no_options_mismatch,
add_all_nested_bound,
overloaded_add_all_32bit_int,
}))
.exportFunc();
const x = {};
......@@ -51,6 +60,7 @@ function buildWasm(name, sig, body) {
add_all_nested_bound: fast_c_api.add_all_no_options
.bind(fast_c_api)
.bind(x),
overloaded_add_all_32bit_int: fast_c_api.overloaded_add_all_32bit_int_no_sig.bind(fast_c_api),
},
});
return module.exports[name];
......@@ -139,3 +149,33 @@ fast_c_api.reset_counts();
assertEquals(add_all_result, add_all_nested_bound_wasm());
assertEquals(0, fast_c_api.fast_call_count());
assertEquals(1, fast_c_api.slow_call_count());
// ----------- Test overloaded_add_all_32bit_int -----------
const overloaded_add_all_32bit_int_wasm = buildWasm(
'overloaded_add_all_32bit_int_wasm', makeSig([kWasmI32], [kWasmI32]),
({ overloaded_add_all_32bit_int }) => [
kExprLocalGet, 0,
...wasmI32Const(1),
...wasmI32Const(2),
...wasmI32Const(3),
...wasmI32Const(4),
...wasmI32Const(5),
...wasmI32Const(6),
kExprCallFunction, overloaded_add_all_32bit_int,
kExprReturn,
],
);
const overload_result = 1 + 2 + 3 + 4 + 5 + 6;
// Test wasm hits fast path.
fast_c_api.reset_counts();
assertEquals(overload_result, overloaded_add_all_32bit_int_wasm(false));
assertEquals(1, fast_c_api.fast_call_count());
assertEquals(0, fast_c_api.slow_call_count());
// Test wasm hits slow path.
fast_c_api.reset_counts();
assertEquals(overload_result, overloaded_add_all_32bit_int_wasm(true));
assertEquals(1, fast_c_api.fast_call_count());
assertEquals(1, fast_c_api.slow_call_count());
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