From 151e9dd509c57e98d8144a9971400498863d49f0 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Wed, 12 Mar 2025 07:47:40 -0700 Subject: [PATCH] [vm, dynamic_modules] Fix instantiated tear-offs of generic static methods and factories TEST=language/function_subtype/bound_closure7_test TEST=language/named_arguments_anywhere/order_side_effects_ok_test TEST=language/regress/regress52243_test Change-Id: I09765f5a272941388fccac65c083d2239da27b1c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/414320 Reviewed-by: Slava Egorov Commit-Queue: Alexander Markov --- runtime/vm/interpreter.cc | 64 ++++++++++++++++++++++++++----------- runtime/vm/runtime_entry.cc | 5 +-- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc index 8e89d734fc7..5839b928e2a 100644 --- a/runtime/vm/interpreter.cc +++ b/runtime/vm/interpreter.cc @@ -3568,33 +3568,60 @@ SwitchDispatch: ClosureDataPtr data = ClosureData::RawCast(function->untag()->data()); FunctionPtr target = Function::RawCast(data->untag()->parent_function()); - const intptr_t type_args_len = - InterpreterHelpers::ArgDescTypeArgsLen(argdesc_); + intptr_t type_args_len = InterpreterHelpers::ArgDescTypeArgsLen(argdesc_); const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0; const intptr_t argc = InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx; ObjectPtr* argv = FrameArguments(FP, argc); - if (type_args_len > 0) { - // Replace closure receiver with type arguments. - argv[1] = argv[0]; - } else if (Function::KindOf(target) == UntaggedFunction::kConstructor) { - // Factory constructors always take type arguments. - FunctionTypePtr signature = - FunctionType::RawCast(function->untag()->signature()); - TypeParametersPtr type_params = signature->untag()->type_parameters(); - TypeArgumentsPtr type_args = (type_params == null_value) - ? TypeArguments::null() - : type_params->untag()->defaults(); - argv[0] = type_args; + TypeParametersPtr type_params = + FunctionType::RawCast(function->untag()->signature()) + ->untag() + ->type_parameters(); + if (type_params == null_value) { + if (type_args_len > 0) { + SP[1] = function; + goto NoSuchMethodFromPrologue; + } + if (Function::KindOf(target) == UntaggedFunction::kConstructor) { + // Factory constructors always take type arguments. + // Replace closure receiver with type arguments. + argv[0] = TypeArguments::null(); + } + } else { + TypeArgumentsPtr delayed_type_arguments = + Closure::RawCast(argv[receiver_idx]) + ->untag() + ->delayed_type_arguments(); + if (delayed_type_arguments != Object::empty_type_arguments().ptr()) { + if (type_args_len > 0) { + SP[1] = function; + goto NoSuchMethodFromPrologue; + } + // Replace closure receiver with type arguments. + argv[0] = delayed_type_arguments; + type_args_len = + Smi::Value(type_params->untag()->names()->untag()->length()); + } else if (type_args_len > 0) { + // Replace closure receiver with type arguments. + argv[1] = argv[0]; + } else if (Function::KindOf(target) == UntaggedFunction::kConstructor) { + // Factory constructors always take type arguments. + // Replace closure receiver with type arguments. + argv[0] = type_params->untag()->defaults(); + type_args_len = + Smi::Value(type_params->untag()->names()->untag()->length()); + } } + SP[1] = target; SP[2] = 0; // Space for result. SP[3] = argdesc_; SP[4] = target; - Exit(thread, FP, SP + 5, pc); + SP[5] = Smi::New(type_args_len); + Exit(thread, FP, SP + 6, pc); INVOKE_RUNTIME(DRT_AdjustArgumentsDesciptorForImplicitClosure, - NativeArguments(thread, 2, SP + 3, SP + 2)); + NativeArguments(thread, 3, SP + 3, SP + 2)); argdesc_ = Array::RawCast(SP[2]); goto TailCallSP1; @@ -3703,9 +3730,10 @@ SwitchDispatch: SP[2] = 0; // Space for result. SP[3] = argdesc_; SP[4] = SP[1]; // Target. - Exit(thread, FP, SP + 5, pc); + SP[5] = 0; // New type_args_len. + Exit(thread, FP, SP + 6, pc); INVOKE_RUNTIME(DRT_AdjustArgumentsDesciptorForImplicitClosure, - NativeArguments(thread, 2, SP + 3, SP + 2)); + NativeArguments(thread, 3, SP + 3, SP + 2)); argdesc_ = Array::RawCast(SP[2]); } diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index daf9e07afed..1aec2d155c2 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -931,14 +931,15 @@ DEFINE_RUNTIME_ENTRY(GetFieldForDispatch, 2) { // into an arguments descriptor for the target function. // Arg0: implicit closure arguments descriptor // Arg1: target function +// Arg2: new type args length // Return value: target arguments descriptor -DEFINE_RUNTIME_ENTRY(AdjustArgumentsDesciptorForImplicitClosure, 2) { +DEFINE_RUNTIME_ENTRY(AdjustArgumentsDesciptorForImplicitClosure, 3) { #if defined(DART_DYNAMIC_MODULES) const auto& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(0)); const auto& target = Function::CheckedHandle(zone, arguments.ArgAt(1)); + intptr_t type_args_len = Smi::CheckedHandle(zone, arguments.ArgAt(2)).Value(); const ArgumentsDescriptor args_desc(descriptor); - intptr_t type_args_len = args_desc.TypeArgsLen(); intptr_t num_arguments = args_desc.Count(); if (target.is_static()) {