@@ -4089,6 +4089,69 @@ ObjectPtr Class::InvokeSetter(const String& setter_name,
4089
4089
return value.raw();
4090
4090
}
4091
4091
4092
+ // Creates a new array of boxed arguments suitable for invoking the callable
4093
+ // from the original boxed arguments for a static call. Also sets the contents
4094
+ // of the handle pointed to by [callable_args_desc_array_out] to an appropriate
4095
+ // arguments descriptor array for the new arguments.
4096
+ //
4097
+ // Assumes [arg_names] are consistent with [static_args_descriptor].
4098
+ static ArrayPtr CreateCallableArgumentsFromStatic(
4099
+ Zone* zone,
4100
+ const Instance& receiver,
4101
+ const Array& static_args,
4102
+ const Array& arg_names,
4103
+ const ArgumentsDescriptor& static_args_descriptor) {
4104
+ const intptr_t num_static_type_args = static_args_descriptor.TypeArgsLen();
4105
+ const intptr_t num_static_args = static_args_descriptor.Count();
4106
+ // Double check that the static args descriptor expects boxed arguments
4107
+ // and the static args descriptor is consistent with the static arguments.
4108
+ ASSERT_EQUAL(static_args_descriptor.Size(), num_static_args);
4109
+ ASSERT_EQUAL(static_args.Length(),
4110
+ num_static_args + (num_static_type_args > 0 ? 1 : 0));
4111
+ // Add an additional slot to store the callable as the receiver.
4112
+ const auto& callable_args =
4113
+ Array::Handle(zone, Array::New(static_args.Length() + 1));
4114
+ const intptr_t first_arg_index = static_args_descriptor.FirstArgIndex();
4115
+ auto& temp = Object::Handle(zone);
4116
+ // Copy the static args into the corresponding slots of the callable args.
4117
+ if (num_static_type_args > 0) {
4118
+ temp = static_args.At(0);
4119
+ callable_args.SetAt(0, temp);
4120
+ }
4121
+ for (intptr_t i = first_arg_index; i < static_args.Length(); i++) {
4122
+ temp = static_args.At(i);
4123
+ callable_args.SetAt(i + 1, temp);
4124
+ }
4125
+ // Set the receiver slot in the callable args.
4126
+ callable_args.SetAt(first_arg_index, receiver);
4127
+ return callable_args.raw();
4128
+ }
4129
+
4130
+ // Return the result of invoking the callable contained in the arguments.
4131
+ // Performs non-covariant type checks when the callable function does not
4132
+ // expect to be called dynamically.
4133
+ static ObjectPtr InvokeCallableWithChecks(Zone* zone,
4134
+ const Array& args,
4135
+ const Array& args_descriptor_array) {
4136
+ auto& result = Object::Handle(
4137
+ zone, DartEntry::ResolveCallable(args, args_descriptor_array));
4138
+ if (result.IsError()) {
4139
+ return result.raw();
4140
+ }
4141
+ const auto& function =
4142
+ Function::Handle(zone, Function::RawCast(result.raw()));
4143
+ if (!function.IsNull() && !function.CanReceiveDynamicInvocation()) {
4144
+ // Let DoArgumentTypesMatch extract the appropriate instantiator
4145
+ // and function tavs from the arguments (including the callable).
4146
+ ArgumentsDescriptor call_args_descriptor(args_descriptor_array);
4147
+ result = function.DoArgumentTypesMatch(args, call_args_descriptor);
4148
+ if (result.IsError()) {
4149
+ return result.raw();
4150
+ }
4151
+ }
4152
+ return DartEntry::InvokeCallable(function, args, args_descriptor_array);
4153
+ }
4154
+
4092
4155
ObjectPtr Class::Invoke(const String& function_name,
4093
4156
const Array& args,
4094
4157
const Array& arg_names,
@@ -4101,6 +4164,10 @@ ObjectPtr Class::Invoke(const String& function_name,
4101
4164
// We don't pass any explicit type arguments, which will be understood as
4102
4165
// using dynamic for any function type arguments by lower layers.
4103
4166
const int kTypeArgsLen = 0;
4167
+ const Array& args_descriptor_array = Array::Handle(
4168
+ zone, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(),
4169
+ arg_names, Heap::kNew));
4170
+ ArgumentsDescriptor args_descriptor(args_descriptor_array);
4104
4171
4105
4172
Function& function =
4106
4173
Function::Handle(zone, LookupStaticFunction(function_name));
@@ -4118,26 +4185,19 @@ ObjectPtr Class::Invoke(const String& function_name,
4118
4185
if (check_is_entrypoint) {
4119
4186
CHECK_ERROR(EntryPointFieldInvocationError(function_name));
4120
4187
}
4121
- // Make room for the closure (receiver) in the argument list.
4122
- const intptr_t num_args = args.Length();
4123
- const Array& call_args = Array::Handle(zone, Array::New(num_args + 1));
4124
- Object& temp = Object::Handle(zone);
4125
- for (int i = 0; i < num_args; i++) {
4126
- temp = args.At(i);
4127
- call_args.SetAt(i + 1, temp);
4128
- }
4129
- call_args.SetAt(0, getter_result);
4130
- const Array& call_args_descriptor_array = Array::Handle(
4131
- zone, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, call_args.Length(),
4188
+ const auto& call_args_descriptor_array = Array::Handle(
4189
+ zone, ArgumentsDescriptor::NewBoxed(args_descriptor.TypeArgsLen(),
4190
+ args_descriptor.Count() + 1,
4132
4191
arg_names, Heap::kNew));
4133
- // Call the closure.
4134
- return DartEntry::InvokeClosure(call_args, call_args_descriptor_array);
4192
+ const auto& call_args = Array::Handle(
4193
+ zone,
4194
+ CreateCallableArgumentsFromStatic(zone, Instance::Cast(getter_result),
4195
+ args, arg_names, args_descriptor));
4196
+ return InvokeCallableWithChecks(zone, call_args,
4197
+ call_args_descriptor_array);
4135
4198
}
4136
4199
}
4137
- const Array& args_descriptor_array = Array::Handle(
4138
- zone, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(),
4139
- arg_names, Heap::kNew));
4140
- ArgumentsDescriptor args_descriptor(args_descriptor_array);
4200
+
4141
4201
if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
4142
4202
(respect_reflectable && !function.is_reflectable())) {
4143
4203
return ThrowNoSuchMethod(
@@ -12778,14 +12838,22 @@ ObjectPtr Library::Invoke(const String& function_name,
12778
12838
const Array& arg_names,
12779
12839
bool respect_reflectable,
12780
12840
bool check_is_entrypoint) const {
12841
+ Thread* thread = Thread::Current();
12842
+ Zone* zone = thread->zone();
12843
+
12781
12844
// We don't pass any explicit type arguments, which will be understood as
12782
12845
// using dynamic for any function type arguments by lower layers.
12783
12846
const int kTypeArgsLen = 0;
12847
+ const Array& args_descriptor_array = Array::Handle(
12848
+ zone, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(),
12849
+ arg_names, Heap::kNew));
12850
+ ArgumentsDescriptor args_descriptor(args_descriptor_array);
12784
12851
12785
- Function& function = Function::Handle();
12786
- Object& obj = Object::Handle(LookupLocalOrReExportObject(function_name));
12787
- if (obj.IsFunction()) {
12788
- function ^= obj.raw();
12852
+ auto& function = Function::Handle(zone);
12853
+ auto& result =
12854
+ Object::Handle(zone, LookupLocalOrReExportObject(function_name));
12855
+ if (result.IsFunction()) {
12856
+ function ^= result.raw();
12789
12857
}
12790
12858
12791
12859
if (!function.IsNull() && check_is_entrypoint) {
@@ -12794,37 +12862,31 @@ ObjectPtr Library::Invoke(const String& function_name,
12794
12862
12795
12863
if (function.IsNull()) {
12796
12864
// Didn't find a method: try to find a getter and invoke call on its result.
12797
- const Object& getter_result = Object::Handle(InvokeGetter(
12798
- function_name, false, respect_reflectable, check_is_entrypoint));
12865
+ const Object& getter_result = Object::Handle(
12866
+ zone, InvokeGetter(function_name, false, respect_reflectable,
12867
+ check_is_entrypoint));
12799
12868
if (getter_result.raw() != Object::sentinel().raw()) {
12800
12869
if (check_is_entrypoint) {
12801
12870
CHECK_ERROR(EntryPointFieldInvocationError(function_name));
12802
12871
}
12803
- // Make room for the closure (receiver) in arguments.
12804
- intptr_t numArgs = args.Length();
12805
- const Array& call_args = Array::Handle(Array::New(numArgs + 1));
12806
- Object& temp = Object::Handle();
12807
- for (int i = 0; i < numArgs; i++) {
12808
- temp = args.At(i);
12809
- call_args.SetAt(i + 1, temp);
12810
- }
12811
- call_args.SetAt(0, getter_result);
12812
- const Array& call_args_descriptor_array =
12813
- Array::Handle(ArgumentsDescriptor::NewBoxed(
12814
- kTypeArgsLen, call_args.Length(), arg_names, Heap::kNew));
12815
- // Call closure.
12816
- return DartEntry::InvokeClosure(call_args, call_args_descriptor_array);
12872
+ const auto& call_args_descriptor_array = Array::Handle(
12873
+ zone, ArgumentsDescriptor::NewBoxed(args_descriptor.TypeArgsLen(),
12874
+ args_descriptor.Count() + 1,
12875
+ arg_names, Heap::kNew));
12876
+ const auto& call_args = Array::Handle(
12877
+ zone,
12878
+ CreateCallableArgumentsFromStatic(zone, Instance::Cast(getter_result),
12879
+ args, arg_names, args_descriptor));
12880
+ return InvokeCallableWithChecks(zone, call_args,
12881
+ call_args_descriptor_array);
12817
12882
}
12818
12883
}
12819
12884
12820
- const Array& args_descriptor_array =
12821
- Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(),
12822
- arg_names, Heap::kNew));
12823
- ArgumentsDescriptor args_descriptor(args_descriptor_array);
12824
12885
if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
12825
12886
(respect_reflectable && !function.is_reflectable())) {
12826
12887
return ThrowNoSuchMethod(
12827
- AbstractType::Handle(Class::Handle(toplevel_class()).RareType()),
12888
+ AbstractType::Handle(zone,
12889
+ Class::Handle(zone, toplevel_class()).RareType()),
12828
12890
function_name, args, arg_names, InvocationMirror::kTopLevel,
12829
12891
InvocationMirror::kMethod);
12830
12892
}
@@ -17949,8 +18011,7 @@ ObjectPtr Instance::Invoke(const String& function_name,
17949
18011
}
17950
18012
// Replace the closure as the receiver in the arguments list.
17951
18013
args.SetAt(0, getter_result);
17952
- // Call the closure.
17953
- return DartEntry::InvokeClosure(args, args_descriptor);
18014
+ return InvokeCallableWithChecks(zone, args, args_descriptor);
17954
18015
}
17955
18016
}
17956
18017
0 commit comments