123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853 |
- From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
- From: John Kleinschmidt <[email protected]>
- Date: Fri, 15 Nov 2024 10:46:43 -0500
- Subject: Revert "[fastapi] Remove dynamic overload resolution"
- Revert this until Node.js decides how to proceed and then pick up their fix.
- Refs: https://github.com/nodejs/node/issues/55452
- Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5956408
- Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5982984
- Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5979766
- This reverts commit c41f7a0ef99bd1c9752ee79923f634145ebc4153.
- diff --git a/src/api/api.cc b/src/api/api.cc
- index d76e52da63748acfb37b31179b3428de77362413..0b30c6568d1a38237f3629fb88a5c9cbf1650f98 100644
- --- a/src/api/api.cc
- +++ b/src/api/api.cc
- @@ -1349,16 +1349,6 @@ Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads(
- i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
- API_RCS_SCOPE(i_isolate, FunctionTemplate, New);
-
- - // Check that all overloads of the fast API callback have different numbers of
- - // parameters. Since the number of overloads is supposed to be small, just
- - // comparing them with each other should be fine.
- - for (size_t i = 0; i < c_function_overloads.size(); ++i) {
- - for (size_t j = i + 1; j < c_function_overloads.size(); ++j) {
- - CHECK_NE(c_function_overloads.data()[i].ArgumentCount(),
- - c_function_overloads.data()[j].ArgumentCount());
- - }
- - }
- -
- if (!Utils::ApiCheck(
- c_function_overloads.empty() ||
- behavior == ConstructorBehavior::kThrow,
- diff --git a/src/compiler/fast-api-calls.cc b/src/compiler/fast-api-calls.cc
- index 2dc99dc83e0f78d2bbb0875cc04064b565deaf06..d560afa2ee9f4384738cddf659a51d4c42b4fe67 100644
- --- a/src/compiler/fast-api-calls.cc
- +++ b/src/compiler/fast-api-calls.cc
- @@ -62,6 +62,52 @@ ElementsKind GetTypedArrayElementsKind(CTypeInfo::Type type) {
- }
- }
-
- +OverloadsResolutionResult ResolveOverloads(
- + const FastApiCallFunctionVector& candidates, unsigned int arg_count) {
- + DCHECK_GT(arg_count, 0);
- +
- + static constexpr int kReceiver = 1;
- +
- + // Only the case of the overload resolution of two functions, one with a
- + // JSArray param and the other with a typed array param is currently
- + // supported.
- + DCHECK_EQ(candidates.size(), 2);
- +
- + for (unsigned int arg_index = kReceiver; arg_index < arg_count; arg_index++) {
- + int index_of_func_with_js_array_arg = -1;
- + int index_of_func_with_typed_array_arg = -1;
- + CTypeInfo::Type element_type = CTypeInfo::Type::kVoid;
- +
- + for (size_t i = 0; i < candidates.size(); i++) {
- + const CTypeInfo& type_info =
- + candidates[i].signature->ArgumentInfo(arg_index);
- + CTypeInfo::SequenceType sequence_type = type_info.GetSequenceType();
- +
- + START_ALLOW_USE_DEPRECATED()
- + if (sequence_type == CTypeInfo::SequenceType::kIsSequence) {
- + DCHECK_LT(index_of_func_with_js_array_arg, 0);
- + index_of_func_with_js_array_arg = static_cast<int>(i);
- + } else if (sequence_type == CTypeInfo::SequenceType::kIsTypedArray) {
- + DCHECK_LT(index_of_func_with_typed_array_arg, 0);
- + index_of_func_with_typed_array_arg = static_cast<int>(i);
- + element_type = type_info.GetType();
- + } else {
- + DCHECK_LT(index_of_func_with_js_array_arg, 0);
- + DCHECK_LT(index_of_func_with_typed_array_arg, 0);
- + }
- + END_ALLOW_USE_DEPRECATED()
- + }
- +
- + if (index_of_func_with_js_array_arg >= 0 &&
- + index_of_func_with_typed_array_arg >= 0) {
- + return {static_cast<int>(arg_index), element_type};
- + }
- + }
- +
- + // No overload found with a JSArray and a typed array as i-th argument.
- + return OverloadsResolutionResult::Invalid();
- +}
- +
- bool CanOptimizeFastSignature(const CFunctionInfo* c_signature) {
- USE(c_signature);
-
- @@ -149,7 +195,8 @@ class FastApiCallBuilder {
- initialize_options_(initialize_options),
- generate_slow_api_call_(generate_slow_api_call) {}
-
- - Node* Build(FastApiCallFunction c_function, Node* data_argument);
- + Node* Build(const FastApiCallFunctionVector& c_functions,
- + const CFunctionInfo* c_signature, Node* data_argument);
-
- private:
- Node* WrapFastCall(const CallDescriptor* call_descriptor, int inputs_size,
- @@ -230,15 +277,35 @@ void FastApiCallBuilder::PropagateException() {
- __ Call(call_descriptor, count, inputs);
- }
-
- -Node* FastApiCallBuilder::Build(FastApiCallFunction c_function,
- +Node* FastApiCallBuilder::Build(const FastApiCallFunctionVector& c_functions,
- + const CFunctionInfo* c_signature,
- Node* data_argument) {
- - const CFunctionInfo* c_signature = c_function.signature;
- const int c_arg_count = c_signature->ArgumentCount();
-
- // Hint to fast path.
- auto if_success = __ MakeLabel();
- auto if_error = __ MakeDeferredLabel();
-
- + // Overload resolution
- + bool generate_fast_call = false;
- + OverloadsResolutionResult overloads_resolution_result =
- + OverloadsResolutionResult::Invalid();
- +
- + if (c_functions.size() == 1) {
- + generate_fast_call = true;
- + } else {
- + DCHECK_EQ(c_functions.size(), 2);
- + overloads_resolution_result = ResolveOverloads(c_functions, c_arg_count);
- + if (overloads_resolution_result.is_valid()) {
- + generate_fast_call = true;
- + }
- + }
- +
- + if (!generate_fast_call) {
- + // Only generate the slow call.
- + return generate_slow_api_call_();
- + }
- +
- // Generate fast call.
-
- const int kFastTargetAddressInputIndex = 0;
- @@ -263,11 +330,18 @@ Node* FastApiCallBuilder::Build(FastApiCallFunction c_function,
- // address associated to the first and only element in the c_functions vector.
- // If there are multiple overloads the value of this input will be set later
- // with a Phi node created by AdaptOverloadedFastCallArgument.
- - inputs[kFastTargetAddressInputIndex] = __ ExternalConstant(
- - ExternalReference::Create(c_function.address, ref_type));
- + inputs[kFastTargetAddressInputIndex] =
- + (c_functions.size() == 1) ? __ ExternalConstant(ExternalReference::Create(
- + c_functions[0].address, ref_type))
- + : nullptr;
-
- for (int i = 0; i < c_arg_count; ++i) {
- - inputs[i + kFastTargetAddressInputCount] = get_parameter_(i, &if_error);
- + inputs[i + kFastTargetAddressInputCount] =
- + get_parameter_(i, overloads_resolution_result, &if_error);
- + if (overloads_resolution_result.target_address) {
- + inputs[kFastTargetAddressInputIndex] =
- + overloads_resolution_result.target_address;
- + }
- }
- DCHECK_NOT_NULL(inputs[kFastTargetAddressInputIndex]);
-
- @@ -368,7 +442,8 @@ Node* FastApiCallBuilder::Build(FastApiCallFunction c_function,
-
- Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
- GraphAssembler* graph_assembler,
- - FastApiCallFunction c_function, Node* data_argument,
- + const FastApiCallFunctionVector& c_functions,
- + const CFunctionInfo* c_signature, Node* data_argument,
- const GetParameter& get_parameter,
- const ConvertReturnValue& convert_return_value,
- const InitializeOptions& initialize_options,
- @@ -376,7 +451,7 @@ Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
- FastApiCallBuilder builder(isolate, graph, graph_assembler, get_parameter,
- convert_return_value, initialize_options,
- generate_slow_api_call);
- - return builder.Build(c_function, data_argument);
- + return builder.Build(c_functions, c_signature, data_argument);
- }
-
- } // namespace fast_api_call
- diff --git a/src/compiler/fast-api-calls.h b/src/compiler/fast-api-calls.h
- index 171e66c427991bfe7db5c2875d12559767a24b55..b97b37e5746433d3801de19d4666a19afc223cdc 100644
- --- a/src/compiler/fast-api-calls.h
- +++ b/src/compiler/fast-api-calls.h
- @@ -40,16 +40,21 @@ struct OverloadsResolutionResult {
-
- ElementsKind GetTypedArrayElementsKind(CTypeInfo::Type type);
-
- +OverloadsResolutionResult ResolveOverloads(
- + const FastApiCallFunctionVector& candidates, unsigned int arg_count);
- +
- bool CanOptimizeFastSignature(const CFunctionInfo* c_signature);
-
- -using GetParameter = std::function<Node*(int, GraphAssemblerLabel<0>*)>;
- +using GetParameter = std::function<Node*(int, OverloadsResolutionResult&,
- + GraphAssemblerLabel<0>*)>;
- using ConvertReturnValue = std::function<Node*(const CFunctionInfo*, Node*)>;
- using InitializeOptions = std::function<void(Node*)>;
- using GenerateSlowApiCall = std::function<Node*()>;
-
- Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
- GraphAssembler* graph_assembler,
- - FastApiCallFunction c_function, Node* data_argument,
- + const FastApiCallFunctionVector& c_functions,
- + const CFunctionInfo* c_signature, Node* data_argument,
- const GetParameter& get_parameter,
- const ConvertReturnValue& convert_return_value,
- const InitializeOptions& initialize_options,
- diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc
- index d75a38769d582cd6e5a807f9670732dc92d77b7e..a29bd4a5be0c9a268386898f8a52e98933211b6c 100644
- --- a/src/compiler/js-call-reducer.cc
- +++ b/src/compiler/js-call-reducer.cc
- @@ -631,11 +631,11 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
- FastApiCallReducerAssembler(
- JSCallReducer* reducer, Node* node,
- const FunctionTemplateInfoRef function_template_info,
- - FastApiCallFunction c_function, Node* receiver, Node* holder,
- - const SharedFunctionInfoRef shared, Node* target, const int arity,
- - Node* effect)
- + const FastApiCallFunctionVector& c_candidate_functions, Node* receiver,
- + Node* holder, const SharedFunctionInfoRef shared, Node* target,
- + const int arity, Node* effect)
- : JSCallReducerAssembler(reducer, node),
- - c_function_(c_function),
- + c_candidate_functions_(c_candidate_functions),
- function_template_info_(function_template_info),
- receiver_(receiver),
- holder_(holder),
- @@ -643,6 +643,7 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
- target_(target),
- arity_(arity) {
- DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
- + CHECK_GT(c_candidate_functions.size(), 0);
- InitializeEffectControl(effect, NodeProperties::GetControlInput(node));
- }
-
- @@ -654,7 +655,7 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
- // All functions in c_candidate_functions_ have the same number of
- // arguments, so extract c_argument_count from the first function.
- const int c_argument_count =
- - static_cast<int>(c_function_.signature->ArgumentCount());
- + static_cast<int>(c_candidate_functions_[0].signature->ArgumentCount());
- CHECK_GE(c_argument_count, kReceiver);
-
- const int slow_arg_count =
- @@ -755,12 +756,13 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
-
- TNode<Object> FastApiCall(CallDescriptor* descriptor, Node** inputs,
- size_t inputs_size) {
- - return AddNode<Object>(graph()->NewNode(
- - simplified()->FastApiCall(c_function_, feedback(), descriptor),
- - static_cast<int>(inputs_size), inputs));
- + return AddNode<Object>(
- + graph()->NewNode(simplified()->FastApiCall(c_candidate_functions_,
- + feedback(), descriptor),
- + static_cast<int>(inputs_size), inputs));
- }
-
- - FastApiCallFunction c_function_;
- + const FastApiCallFunctionVector c_candidate_functions_;
- const FunctionTemplateInfoRef function_template_info_;
- Node* const receiver_;
- Node* const holder_;
- @@ -3886,10 +3888,11 @@ Reduction JSCallReducer::ReduceCallWasmFunction(Node* node,
- // Returns an array with the indexes of the remaining entries in S, which
- // represents the set of "optimizable" function overloads.
-
- -FastApiCallFunction GetFastApiCallTarget(
- - JSHeapBroker* broker, FunctionTemplateInfoRef function_template_info,
- - size_t arg_count) {
- - if (!v8_flags.turbo_fast_api_calls) return {0, nullptr};
- +FastApiCallFunctionVector CanOptimizeFastCall(
- + JSHeapBroker* broker, Zone* zone,
- + FunctionTemplateInfoRef function_template_info, size_t arg_count) {
- + FastApiCallFunctionVector result(zone);
- + if (!v8_flags.turbo_fast_api_calls) return result;
-
- static constexpr int kReceiver = 1;
-
- @@ -3918,15 +3921,15 @@ FastApiCallFunction GetFastApiCallTarget(
- static_cast<uint8_t>(c_signature->ArgumentInfo(i).GetFlags());
- if (flags & static_cast<uint8_t>(CTypeInfo::Flags::kEnforceRangeBit)) {
- // Bailout
- - return {0, nullptr};
- + return FastApiCallFunctionVector(zone);
- }
- }
- #endif
- - return {functions[i], c_signature};
- + result.push_back({functions[i], c_signature});
- }
- }
-
- - return {0, nullptr};
- + return result;
- }
-
- Reduction JSCallReducer::ReduceCallApiFunction(Node* node,
- @@ -4109,13 +4112,15 @@ Reduction JSCallReducer::ReduceCallApiFunction(Node* node,
- }
-
- // Handles overloaded functions.
- - FastApiCallFunction c_function =
- - GetFastApiCallTarget(broker(), function_template_info, argc);
-
- - if (c_function.address) {
- + FastApiCallFunctionVector c_candidate_functions = CanOptimizeFastCall(
- + broker(), graph()->zone(), function_template_info, argc);
- + DCHECK_LE(c_candidate_functions.size(), 2);
- +
- + if (!c_candidate_functions.empty()) {
- FastApiCallReducerAssembler a(this, node, function_template_info,
- - c_function, receiver, holder, shared, target,
- - argc, effect);
- + c_candidate_functions, receiver, holder,
- + shared, target, argc, effect);
- Node* fast_call_subgraph = a.ReduceFastApiCall();
-
- return Replace(fast_call_subgraph);
- diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
- index 377d36b1d880892d0d446ee386d21028d3ffec16..ebb8bcd585f6b185e355922fd97c94bd0136d968 100644
- --- a/src/compiler/simplified-lowering.cc
- +++ b/src/compiler/simplified-lowering.cc
- @@ -2015,7 +2015,7 @@ class RepresentationSelector {
- // argument, which must be a JSArray in one function and a TypedArray in the
- // other function, and both JSArrays and TypedArrays have the same UseInfo
- // UseInfo::AnyTagged(). All the other argument types must match.
- - const CFunctionInfo* c_signature = op_params.c_function().signature;
- + const CFunctionInfo* c_signature = op_params.c_functions()[0].signature;
- const int c_arg_count = c_signature->ArgumentCount();
- CallDescriptor* call_descriptor = op_params.descriptor();
- // Arguments for CallApiCallbackOptimizedXXX builtin (including context)
- @@ -2057,8 +2057,12 @@ class RepresentationSelector {
-
- // Effect and Control.
- ProcessRemainingInputs<T>(node, value_input_count);
- + if (op_params.c_functions().empty()) {
- + SetOutput<T>(node, MachineRepresentation::kTagged);
- + return;
- + }
-
- - CTypeInfo return_type = op_params.c_function().signature->ReturnInfo();
- + CTypeInfo return_type = op_params.c_functions()[0].signature->ReturnInfo();
- switch (return_type.GetType()) {
- case CTypeInfo::Type::kBool:
- SetOutput<T>(node, MachineRepresentation::kBit);
- diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc
- index d0405cf5bc25d47b7cf8bfd03b0bb639df4eddd4..f5810d72d99f4ecfe668d9e1fd9b3ad2ea123875 100644
- --- a/src/compiler/simplified-operator.cc
- +++ b/src/compiler/simplified-operator.cc
- @@ -2096,21 +2096,26 @@ FastApiCallParameters const& FastApiCallParametersOf(const Operator* op) {
- }
-
- std::ostream& operator<<(std::ostream& os, FastApiCallParameters const& p) {
- - FastApiCallFunction c_function = p.c_function();
- - os << c_function.address << ":" << c_function.signature << ", ";
- + const auto& c_functions = p.c_functions();
- + for (size_t i = 0; i < c_functions.size(); i++) {
- + os << c_functions[i].address << ":" << c_functions[i].signature << ", ";
- + }
- return os << p.feedback() << ", " << p.descriptor();
- }
-
- size_t hash_value(FastApiCallParameters const& p) {
- - FastApiCallFunction c_function = p.c_function();
- - size_t hash = base::hash_combine(c_function.address, c_function.signature);
- + const auto& c_functions = p.c_functions();
- + size_t hash = 0;
- + for (size_t i = 0; i < c_functions.size(); i++) {
- + hash = base::hash_combine(c_functions[i].address, c_functions[i].signature);
- + }
- return base::hash_combine(hash, FeedbackSource::Hash()(p.feedback()),
- p.descriptor());
- }
-
- bool operator==(FastApiCallParameters const& lhs,
- FastApiCallParameters const& rhs) {
- - return lhs.c_function() == rhs.c_function() &&
- + return lhs.c_functions() == rhs.c_functions() &&
- lhs.feedback() == rhs.feedback() &&
- lhs.descriptor() == rhs.descriptor();
- }
- @@ -2320,11 +2325,19 @@ const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement(
- }
-
- const Operator* SimplifiedOperatorBuilder::FastApiCall(
- - FastApiCallFunction c_function, FeedbackSource const& feedback,
- - CallDescriptor* descriptor) {
- - CHECK_NOT_NULL(c_function.signature);
- - const CFunctionInfo* signature = c_function.signature;
- + const FastApiCallFunctionVector& c_functions,
- + FeedbackSource const& feedback, CallDescriptor* descriptor) {
- + DCHECK(!c_functions.empty());
- +
- + // All function overloads have the same number of arguments and options.
- + const CFunctionInfo* signature = c_functions[0].signature;
- const int c_arg_count = signature->ArgumentCount();
- + for (size_t i = 1; i < c_functions.size(); i++) {
- + CHECK_NOT_NULL(c_functions[i].signature);
- + DCHECK_EQ(c_functions[i].signature->ArgumentCount(), c_arg_count);
- + DCHECK_EQ(c_functions[i].signature->HasOptions(),
- + c_functions[0].signature->HasOptions());
- + }
- // Arguments for CallApiCallbackOptimizedXXX builtin (including context)
- // plus JS arguments (including receiver).
- int slow_arg_count = static_cast<int>(descriptor->ParameterCount());
- @@ -2334,13 +2347,13 @@ const Operator* SimplifiedOperatorBuilder::FastApiCall(
- return zone()->New<Operator1<FastApiCallParameters>>(
- IrOpcode::kFastApiCall, Operator::kNoProperties, "FastApiCall",
- value_input_count, 1, 1, 1, 1, 2,
- - FastApiCallParameters(c_function, feedback, descriptor));
- + FastApiCallParameters(c_functions, feedback, descriptor));
- }
-
- // static
- int FastApiCallNode::FastCallArgumentCount(Node* node) {
- FastApiCallParameters p = FastApiCallParametersOf(node->op());
- - const CFunctionInfo* signature = p.c_function().signature;
- + const CFunctionInfo* signature = p.c_functions()[0].signature;
- CHECK_NOT_NULL(signature);
- return signature->ArgumentCount();
- }
- diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h
- index 5cb305f8db8419bcaedc89dbd9d68226bcf90551..19cc23394d5dd729974ff4faf0e4f7cf54c4710e 100644
- --- a/src/compiler/simplified-operator.h
- +++ b/src/compiler/simplified-operator.h
- @@ -742,25 +742,35 @@ struct FastApiCallFunction {
- return address == rhs.address && signature == rhs.signature;
- }
- };
- +typedef ZoneVector<FastApiCallFunction> FastApiCallFunctionVector;
-
- class FastApiCallParameters {
- public:
- - explicit FastApiCallParameters(FastApiCallFunction c_function,
- + explicit FastApiCallParameters(const FastApiCallFunctionVector& c_functions,
- FeedbackSource const& feedback,
- CallDescriptor* descriptor)
- - : c_function_(c_function), feedback_(feedback), descriptor_(descriptor) {}
- + : c_functions_(c_functions),
- + feedback_(feedback),
- + descriptor_(descriptor) {}
-
- - FastApiCallFunction c_function() const { return c_function_; }
- + const FastApiCallFunctionVector& c_functions() const { return c_functions_; }
- FeedbackSource const& feedback() const { return feedback_; }
- CallDescriptor* descriptor() const { return descriptor_; }
- - const CFunctionInfo* signature() const { return c_function_.signature; }
- + const CFunctionInfo* signature() const {
- + DCHECK(!c_functions_.empty());
- + return c_functions_[0].signature;
- + }
- unsigned int argument_count() const {
- const unsigned int count = signature()->ArgumentCount();
- + DCHECK(base::all_of(c_functions_, [count](const auto& f) {
- + return f.signature->ArgumentCount() == count;
- + }));
- return count;
- }
-
- private:
- - FastApiCallFunction c_function_;
- + // A single FastApiCall node can represent multiple overloaded functions.
- + const FastApiCallFunctionVector c_functions_;
-
- const FeedbackSource feedback_;
- CallDescriptor* descriptor_;
- @@ -1233,9 +1243,9 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
- const Operator* Unsigned32Divide();
-
- // Represents the inputs necessary to construct a fast and a slow API call.
- - const Operator* FastApiCall(FastApiCallFunction c_function,
- - FeedbackSource const& feedback,
- - CallDescriptor* descriptor);
- + const Operator* FastApiCall(
- + const FastApiCallFunctionVector& c_candidate_functions,
- + FeedbackSource const& feedback, CallDescriptor* descriptor);
-
- #ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA
- const Operator* GetContinuationPreservedEmbedderData();
- diff --git a/src/compiler/turbofan-typer.cc b/src/compiler/turbofan-typer.cc
- index 811c9c5ab82ebbdf6ca14a2fd99c3b154609d506..f36916c1a0d39293f01eca84cac6ef83096cd25e 100644
- --- a/src/compiler/turbofan-typer.cc
- +++ b/src/compiler/turbofan-typer.cc
- @@ -1190,8 +1190,11 @@ Type Typer::Visitor::TypeCall(Node* node) { return Type::Any(); }
-
- Type Typer::Visitor::TypeFastApiCall(Node* node) {
- FastApiCallParameters const& op_params = FastApiCallParametersOf(node->op());
- + if (op_params.c_functions().empty()) {
- + return Type::Undefined();
- + }
-
- - const CFunctionInfo* c_signature = op_params.c_function().signature;
- + const CFunctionInfo* c_signature = op_params.c_functions()[0].signature;
- CTypeInfo return_type = c_signature->ReturnInfo();
-
- switch (return_type.GetType()) {
- diff --git a/src/compiler/turboshaft/fast-api-call-lowering-reducer.h b/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
- index 2dec266f9e648391fe61a62931cca1ad20de719c..dc27e91ad0da93a5b68053f132f219f95f641ca1 100644
- --- a/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
- +++ b/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
- @@ -29,23 +29,41 @@ class FastApiCallLoweringReducer : public Next {
- base::Vector<const OpIndex> arguments,
- const FastApiCallParameters* parameters,
- base::Vector<const RegisterRepresentation> out_reps) {
- - FastApiCallFunction c_function = parameters->c_function;
- + const auto& c_functions = parameters->c_functions;
- const auto& c_signature = parameters->c_signature();
- const int c_arg_count = c_signature->ArgumentCount();
- DCHECK_EQ(c_arg_count, arguments.size());
- + const auto& resolution_result = parameters->resolution_result;
-
- Label<> handle_error(this);
- Label<Word32> done(this);
- Variable result = __ NewVariable(RegisterRepresentation::FromCTypeInfo(
- c_signature->ReturnInfo(), c_signature->GetInt64Representation()));
-
- - OpIndex callee = __ ExternalConstant(ExternalReference::Create(
- - c_function.address, ExternalReference::FAST_C_CALL));
- -
- + OpIndex callee;
- base::SmallVector<OpIndex, 16> args;
- for (int i = 0; i < c_arg_count; ++i) {
- + // Check if this is the argument on which we need to perform overload
- + // resolution.
- + if (i == resolution_result.distinguishable_arg_index) {
- + DCHECK_GT(c_functions.size(), 1);
- + // This only happens when the FastApiCall node represents multiple
- + // overloaded functions and {i} is the index of the distinguishable
- + // argument.
- + OpIndex arg_i;
- + std::tie(callee, arg_i) = AdaptOverloadedFastCallArgument(
- + arguments[i], c_functions, resolution_result, handle_error);
- + args.push_back(arg_i);
- + } else {
- CTypeInfo type = c_signature->ArgumentInfo(i);
- args.push_back(AdaptFastCallArgument(arguments[i], type, handle_error));
- + }
- + }
- +
- + if (c_functions.size() == 1) {
- + DCHECK(!callee.valid());
- + callee = __ ExternalConstant(ExternalReference::Create(
- + c_functions[0].address, ExternalReference::FAST_C_CALL));
- }
-
- // While adapting the arguments, we might have noticed an inconsistency that
- @@ -137,6 +155,56 @@ class FastApiCallLoweringReducer : public Next {
- }
-
- private:
- + std::pair<OpIndex, OpIndex> AdaptOverloadedFastCallArgument(
- + OpIndex argument, const FastApiCallFunctionVector& c_functions,
- + const fast_api_call::OverloadsResolutionResult& resolution_result,
- + Label<>& handle_error) {
- + Label<WordPtr, WordPtr> done(this);
- +
- + for (size_t func_index = 0; func_index < c_functions.size(); ++func_index) {
- + const CFunctionInfo* c_signature = c_functions[func_index].signature;
- + CTypeInfo arg_type = c_signature->ArgumentInfo(
- + resolution_result.distinguishable_arg_index);
- +
- + Label<> next(this);
- +
- + // Check that the value is a HeapObject.
- + GOTO_IF(__ ObjectIsSmi(argument), handle_error);
- +
- + switch (arg_type.GetSequenceType()) {
- + case CTypeInfo::SequenceType::kIsSequence: {
- + CHECK_EQ(arg_type.GetType(), CTypeInfo::Type::kVoid);
- +
- + // Check that the value is a JSArray.
- + V<Map> map = __ LoadMapField(argument);
- + V<Word32> instance_type = __ LoadInstanceTypeField(map);
- + GOTO_IF_NOT(__ Word32Equal(instance_type, JS_ARRAY_TYPE), next);
- +
- + OpIndex argument_to_pass = __ AdaptLocalArgument(argument);
- + OpIndex target_address = __ ExternalConstant(
- + ExternalReference::Create(c_functions[func_index].address,
- + ExternalReference::FAST_C_CALL));
- + GOTO(done, target_address, argument_to_pass);
- + break;
- + }
- + START_ALLOW_USE_DEPRECATED()
- + case CTypeInfo::SequenceType::kIsTypedArray:
- + UNREACHABLE();
- + END_ALLOW_USE_DEPRECATED()
- +
- + default: {
- + UNREACHABLE();
- + }
- + }
- +
- + BIND(next);
- + }
- + GOTO(handle_error);
- +
- + BIND(done, callee, arg);
- + return {callee, arg};
- + }
- +
- template <typename T>
- V<T> Checked(V<Tuple<T, Word32>> result, Label<>& otherwise) {
- V<Word32> result_state = __ template Projection<1>(result);
- diff --git a/src/compiler/turboshaft/graph-builder.cc b/src/compiler/turboshaft/graph-builder.cc
- index f24cd884bf7810aaed5e58b2044c2770653266f1..d79f6c801d2562a3cd65597d79050791fee3ad08 100644
- --- a/src/compiler/turboshaft/graph-builder.cc
- +++ b/src/compiler/turboshaft/graph-builder.cc
- @@ -1974,7 +1974,7 @@ OpIndex GraphBuilder::Process(
- DCHECK(dominating_frame_state.valid());
- FastApiCallNode n(node);
- const auto& params = n.Parameters();
- - FastApiCallFunction c_function = params.c_function();
- + const FastApiCallFunctionVector& c_functions = params.c_functions();
- const int c_arg_count = params.argument_count();
-
- base::SmallVector<OpIndex, 16> slow_call_arguments;
- @@ -2141,6 +2141,40 @@ OpIndex GraphBuilder::Process(
- Block* catch_block = Map(block->SuccessorAt(1));
- catch_scope.emplace(assembler, catch_block);
- }
- + // Overload resolution.
- + auto resolution_result =
- + fast_api_call::OverloadsResolutionResult::Invalid();
- + if (c_functions.size() != 1) {
- + DCHECK_EQ(c_functions.size(), 2);
- + resolution_result =
- + fast_api_call::ResolveOverloads(c_functions, c_arg_count);
- + if (!resolution_result.is_valid()) {
- + V<Object> fallback_result = V<Object>::Cast(__ Call(
- + slow_call_callee, dominating_frame_state,
- + base::VectorOf(slow_call_arguments),
- + TSCallDescriptor::Create(params.descriptor(), CanThrow::kYes,
- + LazyDeoptOnThrow::kNo,
- + __ graph_zone())));
- + Variable result =
- + __ NewVariable(RegisterRepresentation::FromCTypeInfo(
- + c_functions[0].signature->ReturnInfo(),
- + c_functions[0].signature->GetInt64Representation()));
- + convert_fallback_return(
- + result, c_functions[0].signature->GetInt64Representation(),
- + c_functions[0].signature->ReturnInfo().GetType(),
- + fallback_result);
- + V<Any> value = __ GetVariable(result);
- + if (is_final_control) {
- + // The `__ Call()` before has already created exceptional
- + // control flow and bound a new block for the success case. So we
- + // can just `Goto` the block that Turbofan designated as the
- + // `IfSuccess` successor.
- + __ Goto(Map(block->SuccessorAt(0)));
- + }
- + return value;
- + }
- + }
- +
- // Prepare FastCallApiOp parameters.
- base::SmallVector<OpIndex, 16> arguments;
- for (int i = 0; i < c_arg_count; ++i) {
- @@ -2150,8 +2184,8 @@ OpIndex GraphBuilder::Process(
-
- V<Context> context = Map(n.Context());
-
- - const FastApiCallParameters* parameters =
- - FastApiCallParameters::Create(c_function, __ graph_zone());
- + const FastApiCallParameters* parameters = FastApiCallParameters::Create(
- + c_functions, resolution_result, __ graph_zone());
-
- // There is one return in addition to the return value of the C function,
- // which indicates if a fast API call actually happened.
- diff --git a/src/compiler/turboshaft/operations.h b/src/compiler/turboshaft/operations.h
- index a26611708f2dd162e127d7a7c9af9135892d0b40..b04639190b239af92a2845886e5852080e6e454a 100644
- --- a/src/compiler/turboshaft/operations.h
- +++ b/src/compiler/turboshaft/operations.h
- @@ -6386,16 +6386,24 @@ struct Float64SameValueOp : FixedArityOperationT<2, Float64SameValueOp> {
- };
-
- struct FastApiCallParameters : public NON_EXPORTED_BASE(ZoneObject) {
- - FastApiCallFunction c_function;
- + const FastApiCallFunctionVector c_functions;
- + fast_api_call::OverloadsResolutionResult resolution_result;
-
- - const CFunctionInfo* c_signature() const { return c_function.signature; }
- + const CFunctionInfo* c_signature() const { return c_functions[0].signature; }
-
- - explicit FastApiCallParameters(FastApiCallFunction c_function)
- - : c_function(c_function) {}
- + FastApiCallParameters(
- + const FastApiCallFunctionVector& c_functions,
- + const fast_api_call::OverloadsResolutionResult& resolution_result)
- + : c_functions(c_functions), resolution_result(resolution_result) {
- + DCHECK_LT(0, c_functions.size());
- + }
-
- - static const FastApiCallParameters* Create(FastApiCallFunction c_function,
- - Zone* graph_zone) {
- - return graph_zone->New<FastApiCallParameters>(c_function);
- + static const FastApiCallParameters* Create(
- + const FastApiCallFunctionVector& c_functions,
- + const fast_api_call::OverloadsResolutionResult& resolution_result,
- + Zone* graph_zone) {
- + return graph_zone->New<FastApiCallParameters>(std::move(c_functions),
- + resolution_result);
- }
- };
-
- diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
- index 5ad805a11f7de73f06518ee3cf878ca492c0c652..2571f2800450cb8582198dc7cb7ef58311c52dae 100644
- --- a/src/compiler/wasm-compiler.cc
- +++ b/src/compiler/wasm-compiler.cc
- @@ -8356,13 +8356,19 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
- wasm::ObjectAccess::ToTagged(
- FunctionTemplateInfo::kCallbackDataOffset));
-
- - FastApiCallFunction c_function{c_address, c_signature};
- + FastApiCallFunctionVector fast_api_call_function_vector(mcgraph()->zone());
- + fast_api_call_function_vector.push_back({c_address, c_signature});
- Node* call = fast_api_call::BuildFastApiCall(
- - target->GetIsolate(), graph(), gasm_.get(), c_function,
- - api_data_argument,
- + target->GetIsolate(), graph(), gasm_.get(),
- + fast_api_call_function_vector, c_signature, api_data_argument,
- // Load and convert parameters passed to C function
- - [this, c_signature, receiver_node](int param_index,
- - GraphAssemblerLabel<0>*) {
- + [this, c_signature, receiver_node](
- + int param_index,
- + fast_api_call::OverloadsResolutionResult& overloads,
- + GraphAssemblerLabel<0>*) {
- + // Wasm does not currently support overloads
- + CHECK(!overloads.is_valid());
- +
- if (param_index == 0) {
- return gasm_->AdaptLocalArgument(receiver_node);
- }
- diff --git a/src/d8/d8-test.cc b/src/d8/d8-test.cc
- index 6467930fbb39a67a10d6822545e985965ced83ad..1c99e4d89cbc605c6c1b75ce31b09b67334a10ee 100644
- --- a/src/d8/d8-test.cc
- +++ b/src/d8/d8-test.cc
- @@ -443,6 +443,20 @@ class FastCApiObject {
- }
- }
-
- + static int32_t AddAllIntInvalidCallback(Local<Object> receiver,
- + int32_t arg_i32,
- + FastApiCallbackOptions& options) {
- + // This should never be called
- + UNREACHABLE();
- + }
- +
- + static int32_t AddAllIntInvalidOverloadCallback(
- + Local<Object> receiver, Local<Object> seq_arg,
- + FastApiCallbackOptions& options) {
- + // This should never be called
- + UNREACHABLE();
- + }
- +
- #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
- static AnyCType Add32BitIntFastCallbackPatch(AnyCType receiver,
- AnyCType arg_i32,
- @@ -1553,6 +1567,22 @@ Local<FunctionTemplate> Shell::CreateTestFastCApiTemplate(Isolate* isolate) {
- signature, 1, ConstructorBehavior::kThrow,
- SideEffectType::kHasSideEffect, {add_all_overloads, 2}));
-
- + CFunction add_all_int_invalid_func =
- + CFunction::Make(FastCApiObject::AddAllIntInvalidCallback);
- + CFunction add_all_int_invalid_overload =
- + CFunction::Make(FastCApiObject::AddAllIntInvalidOverloadCallback);
- +
- + const CFunction add_all_invalid_overloads[] = {
- + add_all_int_invalid_func,
- + add_all_int_invalid_overload,
- + };
- + api_obj_ctor->PrototypeTemplate()->Set(
- + isolate, "add_all_invalid_overload",
- + FunctionTemplate::NewWithCFunctionOverloads(
- + isolate, FastCApiObject::AddAllSequenceSlowCallback, Local<Value>(),
- + signature, 1, ConstructorBehavior::kThrow,
- + SideEffectType::kHasSideEffect, {add_all_invalid_overloads, 2}));
- +
- CFunction add_all_32bit_int_8args_c_func = CFunction::Make(
- FastCApiObject::AddAll32BitIntFastCallback_8Args V8_IF_USE_SIMULATOR(
- FastCApiObject::AddAll32BitIntFastCallback_8ArgsPatch));
- diff --git a/test/mjsunit/compiler/fast-api-sequences.js b/test/mjsunit/compiler/fast-api-sequences.js
- index 6a982bbbfe13ae792a3d3a1d3376f71b6b00d38a..4318f60fc70f0a2684c6f233861e513063f8e542 100644
- --- a/test/mjsunit/compiler/fast-api-sequences.js
- +++ b/test/mjsunit/compiler/fast-api-sequences.js
- @@ -81,6 +81,30 @@ for (let i = 0; i < 100; i++) {
- ExpectFastCall(overloaded_test, 62);
- })();
-
- +// Test function with invalid overloads.
- +(function () {
- + function overloaded_test() {
- + return fast_c_api.add_all_invalid_overload(
- + [26, -6, 42]);
- + }
- +
- + %PrepareFunctionForOptimization(overloaded_test);
- + result = overloaded_test();
- + assertEquals(62, result);
- +
- + fast_c_api.reset_counts();
- + %OptimizeFunctionOnNextCall(overloaded_test);
- + result = overloaded_test();
- + assertEquals(62, result);
- + // Here we deopt because with this invalid overload:
- + // - add_all_int_invalid_func(Receiver, Bool, Int32, Options)
- + // - add_all_seq_c_func(Receiver, Bool, JSArray, Options)
- + // we expect that a number will be passed as 3rd argument
- + // (SimplifiedLowering takes the type from the first overloaded function).
- + assertUnoptimized(overloaded_test);
- + assertEquals(0, fast_c_api.fast_call_count());
- +})();
- +
- // ----------- Test different TypedArray functions. -----------
- // ----------- add_all_<TYPE>_typed_array -----------
- // `add_all_<TYPE>_typed_array` have the following signature:
- diff --git a/test/mjsunit/regress/regress-335548148.js b/test/mjsunit/regress/regress-335548148.js
- new file mode 100644
- index 0000000000000000000000000000000000000000..4725c48990767fc2a469a5ab3c04ba96e11bf54c
- --- /dev/null
- +++ b/test/mjsunit/regress/regress-335548148.js
- @@ -0,0 +1,29 @@
- +// Copyright 2024 the V8 project authors. All rights reserved.
- +// Use of this source code is governed by a BSD-style license that can be
- +// found in the LICENSE file.
- +
- +// Flags: --turbo-fast-api-calls --expose-fast-api --allow-natives-syntax --turbofan
- +// --always-turbofan is disabled because we rely on particular feedback for
- +// optimizing to the fastest path.
- +// Flags: --no-always-turbofan
- +// The test relies on optimizing/deoptimizing at predictable moments, so
- +// it's not suitable for deoptimization fuzzing.
- +// Flags: --deopt-every-n-times=0
- +// Flags: --fast-api-allow-float-in-sim
- +
- +const __v_0 = new d8.test.FastCAPI();
- +
- +function __f_0(__v_4, __v_5) {
- + try {
- + // Call the API function with an invalid parameter. Because of the invalid
- + // parameter the overload resolution of the fast API cannot figure out
- + // which function should be called, and therefore emits code for a normal
- + // API call.
- + __v_0.add_all_invalid_overload(__v_5, Object.prototype);
- + } catch (e) {}
- +}
- +
- +%PrepareFunctionForOptimization(__f_0);
- +__f_0(Number.MIN_VALUE, Number.MIN_VALUE);
- +%OptimizeFunctionOnNextCall(__f_0);
- +__f_0(Number.MIN_VALUE, Number.MIN_VALUE);
|