1// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/bootstrap_natives.h"
6
7#include "lib/invocation_mirror.h"
8#include "vm/code_patcher.h"
9#include "vm/dart_entry.h"
10#include "vm/exceptions.h"
11#include "vm/heap/heap.h"
12#include "vm/native_entry.h"
13#include "vm/object.h"
14#include "vm/object_store.h"
15#include "vm/resolver.h"
16#include "vm/stack_frame.h"
17#include "vm/symbols.h"
18
19namespace dart {
20
21DEFINE_NATIVE_ENTRY(DartAsync_fatal, 0, 1) {
22 // The dart:async library code entered an unrecoverable state.
23 const Instance& instance =
24 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
25 const char* msg = instance.ToCString();
26 OS::PrintErr(format: "Fatal error in dart:async: %s\n", msg);
27 FATAL("%s", msg);
28 return Object::null();
29}
30
31DEFINE_NATIVE_ENTRY(Object_equals, 0, 1) {
32 // Implemented in the flow graph builder.
33 UNREACHABLE();
34 return Object::null();
35}
36
37static intptr_t GetHash(Isolate* isolate, const ObjectPtr obj) {
38#if defined(HASH_IN_OBJECT_HEADER)
39 return Object::GetCachedHash(obj);
40#else
41 Heap* heap = isolate->group()->heap();
42 ASSERT(obj->IsDartInstance());
43 return heap->GetHash(obj);
44#endif
45}
46
47DEFINE_NATIVE_ENTRY(Object_getHash, 0, 1) {
48 // Please note that no handle is created for the argument.
49 // This is safe since the argument is only used in a tail call.
50 // The performance benefit is more than 5% when using hashCode.
51 intptr_t hash = GetHash(isolate, obj: arguments->NativeArgAt(index: 0));
52 if (LIKELY(hash != 0)) {
53 return Smi::New(value: hash);
54 }
55
56 const Instance& instance =
57 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
58 return instance.IdentityHashCode(thread: arguments->thread());
59}
60
61DEFINE_NATIVE_ENTRY(Object_toString, 0, 1) {
62 const Instance& instance =
63 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
64 if (instance.IsString()) {
65 return instance.ptr();
66 }
67 if (instance.IsAbstractType()) {
68 return AbstractType::Cast(obj: instance).UserVisibleName();
69 }
70 const char* c_str = instance.ToCString();
71 return String::New(cstr: c_str);
72}
73
74DEFINE_NATIVE_ENTRY(Object_runtimeType, 0, 1) {
75 const Instance& instance =
76 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
77 if (instance.IsString()) {
78 return Type::StringType();
79 } else if (instance.IsInteger()) {
80 return Type::IntType();
81 } else if (instance.IsDouble()) {
82 return Type::Double();
83 } else if (instance.IsAbstractType()) {
84 return Type::DartTypeType();
85 } else if (IsArrayClassId(index: instance.GetClassId())) {
86 const auto& cls = Class::Handle(
87 zone, ptr: thread->isolate_group()->object_store()->list_class());
88 auto& type_arguments =
89 TypeArguments::Handle(zone, ptr: instance.GetTypeArguments());
90 type_arguments = type_arguments.FromInstanceTypeArguments(thread, cls);
91 const auto& type = Type::Handle(
92 zone,
93 ptr: Type::New(clazz: cls, arguments: type_arguments, nullability: Nullability::kNonNullable, space: Heap::kNew));
94 type.SetIsFinalized();
95 return type.Canonicalize(thread);
96 }
97
98 return instance.GetType(space: Heap::kNew);
99}
100
101static bool HaveSameRuntimeTypeHelper(Zone* zone,
102 const Instance& left,
103 const Instance& right) {
104 const intptr_t left_cid = left.GetClassId();
105 const intptr_t right_cid = right.GetClassId();
106
107 if (left_cid != right_cid) {
108 if (IsIntegerClassId(index: left_cid)) {
109 return IsIntegerClassId(index: right_cid);
110 } else if (IsStringClassId(index: left_cid)) {
111 return IsStringClassId(index: right_cid);
112 } else if (IsTypeClassId(index: left_cid)) {
113 return IsTypeClassId(index: right_cid);
114 } else if (IsArrayClassId(index: left_cid)) {
115 if (!IsArrayClassId(index: right_cid)) {
116 return false;
117 }
118 // Still need to check type arguments.
119 } else {
120 return false;
121 }
122 }
123
124 if (left_cid == kClosureCid) {
125 const auto& left_closure = Closure::Cast(obj: left);
126 const auto& right_closure = Closure::Cast(obj: right);
127 // If all the components that make up the instantiated signature are equal,
128 // then no need to instantiate.
129 if (left_closure.function_type_arguments() ==
130 right_closure.function_type_arguments() &&
131 left_closure.delayed_type_arguments() ==
132 right_closure.delayed_type_arguments() &&
133 left_closure.instantiator_type_arguments() ==
134 right_closure.instantiator_type_arguments()) {
135 const auto& left_fun = Function::Handle(zone, ptr: left_closure.function());
136 const auto& right_fun = Function::Handle(zone, ptr: right_closure.function());
137 if (left_fun.signature() == right_fun.signature()) {
138 return true;
139 }
140 }
141 const AbstractType& left_type =
142 AbstractType::Handle(zone, ptr: left.GetType(space: Heap::kNew));
143 const AbstractType& right_type =
144 AbstractType::Handle(zone, ptr: right.GetType(space: Heap::kNew));
145 return left_type.IsEquivalent(other: right_type, kind: TypeEquality::kSyntactical);
146 }
147
148 if (left_cid == kRecordCid) {
149 const auto& left_record = Record::Cast(obj: left);
150 const auto& right_record = Record::Cast(obj: right);
151 if (left_record.shape() != right_record.shape()) {
152 return false;
153 }
154 Instance& left_field = Instance::Handle(zone);
155 Instance& right_field = Instance::Handle(zone);
156 const intptr_t num_fields = left_record.num_fields();
157 for (intptr_t i = 0; i < num_fields; ++i) {
158 left_field ^= left_record.FieldAt(field_index: i);
159 right_field ^= right_record.FieldAt(field_index: i);
160 if (!HaveSameRuntimeTypeHelper(zone, left: left_field, right: right_field)) {
161 return false;
162 }
163 }
164 return true;
165 }
166
167 const Class& cls = Class::Handle(zone, ptr: left.clazz());
168 if (!cls.IsGeneric()) {
169 return true;
170 }
171
172 if (left.GetTypeArguments() == right.GetTypeArguments()) {
173 return true;
174 }
175 const TypeArguments& left_type_arguments =
176 TypeArguments::Handle(zone, ptr: left.GetTypeArguments());
177 const TypeArguments& right_type_arguments =
178 TypeArguments::Handle(zone, ptr: right.GetTypeArguments());
179 const intptr_t num_type_args = cls.NumTypeArguments();
180 const intptr_t num_type_params = cls.NumTypeParameters();
181 return left_type_arguments.IsSubvectorEquivalent(
182 other: right_type_arguments, from_index: num_type_args - num_type_params, len: num_type_params,
183 kind: TypeEquality::kSyntactical);
184}
185
186DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 0, 2) {
187 const Instance& left =
188 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
189 const Instance& right =
190 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
191 return Bool::Get(value: HaveSameRuntimeTypeHelper(zone, left, right)).ptr();
192}
193
194DEFINE_NATIVE_ENTRY(Object_instanceOf, 0, 4) {
195 const Instance& instance =
196 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
197 const TypeArguments& instantiator_type_arguments =
198 TypeArguments::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
199 const TypeArguments& function_type_arguments =
200 TypeArguments::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 2));
201 const AbstractType& type =
202 AbstractType::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 3));
203 ASSERT(type.IsFinalized());
204 const bool is_instance_of = instance.IsInstanceOf(
205 other: type, other_instantiator_type_arguments: instantiator_type_arguments, other_function_type_arguments: function_type_arguments);
206 if (FLAG_trace_type_checks) {
207 LogBlock lb;
208 const char* result_str = is_instance_of ? "true" : "false";
209 THR_Print("Native Object.instanceOf: result %s\n", result_str);
210 const AbstractType& instance_type =
211 AbstractType::Handle(zone, ptr: instance.GetType(space: Heap::kNew));
212 THR_Print(" instance type: %s\n",
213 String::Handle(zone, instance_type.Name()).ToCString());
214 THR_Print(" test type: %s\n",
215 String::Handle(zone, type.Name()).ToCString());
216 }
217 return Bool::Get(value: is_instance_of).ptr();
218}
219
220DEFINE_NATIVE_ENTRY(Object_simpleInstanceOf, 0, 2) {
221 // This native is only called when the right hand side passes
222 // SimpleInstanceOfType and it is a non-negative test.
223 const Instance& instance =
224 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
225 const AbstractType& type =
226 AbstractType::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
227 ASSERT(type.IsFinalized());
228 ASSERT(type.IsInstantiated());
229 const bool is_instance_of = instance.IsInstanceOf(
230 other: type, other_instantiator_type_arguments: Object::null_type_arguments(), other_function_type_arguments: Object::null_type_arguments());
231 return Bool::Get(value: is_instance_of).ptr();
232}
233
234DEFINE_NATIVE_ENTRY(AbstractType_toString, 0, 1) {
235 const AbstractType& type =
236 AbstractType::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
237 return type.UserVisibleName();
238}
239
240DEFINE_NATIVE_ENTRY(AbstractType_getHashCode, 0, 1) {
241 const AbstractType& type =
242 AbstractType::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
243 intptr_t hash_val = type.Hash();
244 ASSERT(hash_val > 0);
245 ASSERT(Smi::IsValid(hash_val));
246 return Smi::New(value: hash_val);
247}
248
249DEFINE_NATIVE_ENTRY(AbstractType_equality, 0, 2) {
250 const AbstractType& type =
251 AbstractType::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
252 const Instance& other =
253 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
254 if (type.ptr() == other.ptr()) {
255 return Bool::True().ptr();
256 }
257 return Bool::Get(value: type.IsEquivalent(other, kind: TypeEquality::kSyntactical)).ptr();
258}
259
260DEFINE_NATIVE_ENTRY(Type_equality, 0, 2) {
261 const Type& type = Type::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
262 const Instance& other =
263 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
264 if (type.ptr() == other.ptr()) {
265 return Bool::True().ptr();
266 }
267 return Bool::Get(value: type.IsEquivalent(other, kind: TypeEquality::kSyntactical)).ptr();
268}
269
270DEFINE_NATIVE_ENTRY(LibraryPrefix_isLoaded, 0, 1) {
271 const LibraryPrefix& prefix =
272 LibraryPrefix::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
273 return Bool::Get(value: isolate->IsPrefixLoaded(prefix)).ptr();
274}
275
276DEFINE_NATIVE_ENTRY(LibraryPrefix_setLoaded, 0, 1) {
277 const LibraryPrefix& prefix =
278 LibraryPrefix::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
279 isolate->SetPrefixIsLoaded(prefix);
280 return Instance::null();
281}
282
283DEFINE_NATIVE_ENTRY(LibraryPrefix_loadingUnit, 0, 1) {
284 const LibraryPrefix& prefix =
285 LibraryPrefix::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
286 const Library& target = Library::Handle(zone, ptr: prefix.GetLibrary(index: 0));
287 const LoadingUnit& unit = LoadingUnit::Handle(zone, ptr: target.loading_unit());
288 return Smi::New(value: unit.IsNull() ? LoadingUnit::kIllegalId : unit.id());
289}
290
291DEFINE_NATIVE_ENTRY(LibraryPrefix_issueLoad, 0, 1) {
292 const Smi& id = Smi::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
293 Array& units =
294 Array::Handle(zone, ptr: isolate->group()->object_store()->loading_units());
295 if (units.IsNull()) {
296 // Not actually split.
297 const Library& lib = Library::Handle(zone, ptr: Library::CoreLibrary());
298 const String& sel = String::Handle(zone, ptr: String::New(cstr: "_completeLoads"));
299 const Function& func =
300 Function::Handle(zone, ptr: lib.LookupFunctionAllowPrivate(name: sel));
301 ASSERT(!func.IsNull());
302 const Array& args = Array::Handle(zone, ptr: Array::New(len: 3));
303 args.SetAt(index: 0, value: id);
304 args.SetAt(index: 1, value: String::Handle(zone));
305 args.SetAt(index: 2, value: Bool::Get(value: false));
306 return DartEntry::InvokeFunction(function: func, arguments: args);
307 }
308 ASSERT(id.Value() != LoadingUnit::kIllegalId);
309 LoadingUnit& unit = LoadingUnit::Handle(zone);
310 unit ^= units.At(index: id.Value());
311 return unit.IssueLoad();
312}
313
314DEFINE_NATIVE_ENTRY(Internal_unsafeCast, 0, 1) {
315 UNREACHABLE(); // Should be erased at Kernel translation time.
316 return arguments->NativeArgAt(index: 0);
317}
318
319DEFINE_NATIVE_ENTRY(Internal_nativeEffect, 0, 1) {
320 UNREACHABLE();
321}
322
323DEFINE_NATIVE_ENTRY(Internal_collectAllGarbage, 0, 0) {
324 isolate->group()->heap()->CollectAllGarbage(reason: GCReason::kDebugging,
325 /*compact=*/true);
326 return Object::null();
327}
328
329DEFINE_NATIVE_ENTRY(Internal_deoptimizeFunctionsOnStack, 0, 0) {
330 DeoptimizeFunctionsOnStack();
331 return Object::null();
332}
333
334DEFINE_NATIVE_ENTRY(Internal_randomInstructionsOffsetInsideAllocateObjectStub,
335 0,
336 0) {
337 auto& stub = Code::Handle(
338 zone, ptr: isolate->group()->object_store()->allocate_object_stub());
339 const uword entry = stub.EntryPoint();
340 const uword random_offset = isolate->random()->NextUInt32() % stub.Size();
341 // We return the offset into the isolate instructions instead of the full
342 // address because that fits into small Smis on 32-bit architectures or
343 // compressed pointer builds.
344 const uword instructions_start =
345 reinterpret_cast<uword>(isolate->source()->snapshot_instructions);
346 ASSERT(entry >= instructions_start);
347 return Smi::New(value: (entry - instructions_start) + random_offset);
348}
349
350static bool ExtractInterfaceTypeArgs(Zone* zone,
351 const Class& instance_cls,
352 const TypeArguments& instance_type_args,
353 const Class& interface_cls,
354 TypeArguments* interface_type_args) {
355 Thread* thread = Thread::Current();
356 Class& cur_cls = Class::Handle(zone, ptr: instance_cls.ptr());
357 // The following code is a specialization of Class::IsSubtypeOf().
358 Array& interfaces = Array::Handle(zone);
359 Type& interface = Type::Handle(zone);
360 Class& cur_interface_cls = Class::Handle(zone);
361 TypeArguments& cur_interface_type_args = TypeArguments::Handle(zone);
362 while (true) {
363 // Additional subtyping rules related to 'FutureOr' are not applied.
364 if (cur_cls.ptr() == interface_cls.ptr()) {
365 *interface_type_args = instance_type_args.ptr();
366 return true;
367 }
368 interfaces = cur_cls.interfaces();
369 for (intptr_t i = 0; i < interfaces.Length(); i++) {
370 interface ^= interfaces.At(index: i);
371 ASSERT(interface.IsFinalized());
372 cur_interface_cls = interface.type_class();
373 cur_interface_type_args =
374 interface.GetInstanceTypeArguments(thread, /*canonicalize=*/false);
375 if (!cur_interface_type_args.IsNull() &&
376 !cur_interface_type_args.IsInstantiated()) {
377 cur_interface_type_args = cur_interface_type_args.InstantiateFrom(
378 instantiator_type_arguments: instance_type_args, function_type_arguments: Object::null_type_arguments(), num_free_fun_type_params: kNoneFree,
379 space: Heap::kNew);
380 }
381 if (ExtractInterfaceTypeArgs(zone, instance_cls: cur_interface_cls,
382 instance_type_args: cur_interface_type_args, interface_cls,
383 interface_type_args)) {
384 return true;
385 }
386 }
387 cur_cls = cur_cls.SuperClass();
388 if (cur_cls.IsNull()) {
389 return false;
390 }
391 }
392}
393
394// for documentation see pkg/dart_internal/lib/extract_type_arguments.dart
395DEFINE_NATIVE_ENTRY(Internal_extractTypeArguments, 0, 2) {
396 const Instance& instance =
397 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
398 const Instance& extract =
399 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
400
401 Class& interface_cls = Class::Handle(zone);
402 intptr_t num_type_args = 0;
403 if (arguments->NativeTypeArgCount() >= 1) {
404 const AbstractType& function_type_arg =
405 AbstractType::Handle(zone, ptr: arguments->NativeTypeArgAt(index: 0));
406 if (function_type_arg.IsType() &&
407 (Type::Cast(obj: function_type_arg).arguments() == TypeArguments::null())) {
408 interface_cls = function_type_arg.type_class();
409 num_type_args = interface_cls.NumTypeParameters();
410 }
411 }
412 if (num_type_args == 0) {
413 Exceptions::ThrowArgumentError(arg: String::Handle(
414 zone,
415 ptr: String::New(
416 cstr: "single function type argument must specify a generic class")));
417 }
418 if (instance.IsNull()) {
419 Exceptions::ThrowArgumentError(arg: instance);
420 }
421 // Function 'extract' must be generic and accept the same number of type args,
422 // unless we execute Dart 1.0 code.
423 if (extract.IsNull() || !extract.IsClosure() ||
424 ((num_type_args > 0) && // Dart 1.0 if num_type_args == 0.
425 (Function::Handle(zone, ptr: Closure::Cast(obj: extract).function())
426 .NumTypeParameters() != num_type_args))) {
427 Exceptions::ThrowArgumentError(arg: String::Handle(
428 zone,
429 ptr: String::New(cstr: "argument 'extract' is not a generic function or not one "
430 "accepting the correct number of type arguments")));
431 }
432 TypeArguments& extracted_type_args = TypeArguments::Handle(zone);
433 if (num_type_args > 0) {
434 // The passed instance must implement interface_cls.
435 TypeArguments& interface_type_args = TypeArguments::Handle(zone);
436 interface_type_args = TypeArguments::New(len: num_type_args);
437 Class& instance_cls = Class::Handle(zone, ptr: instance.clazz());
438 TypeArguments& instance_type_args = TypeArguments::Handle(zone);
439 if (instance_cls.NumTypeArguments() > 0) {
440 instance_type_args = instance.GetTypeArguments();
441 }
442 if (!ExtractInterfaceTypeArgs(zone, instance_cls, instance_type_args,
443 interface_cls, interface_type_args: &interface_type_args)) {
444 Exceptions::ThrowArgumentError(arg: String::Handle(
445 zone, ptr: String::New(cstr: "type of argument 'instance' is not a subtype of "
446 "the function type argument")));
447 }
448 if (!interface_type_args.IsNull()) {
449 extracted_type_args = TypeArguments::New(len: num_type_args);
450 const intptr_t offset = interface_cls.NumTypeArguments() - num_type_args;
451 AbstractType& type_arg = AbstractType::Handle(zone);
452 for (intptr_t i = 0; i < num_type_args; i++) {
453 type_arg = interface_type_args.TypeAt(index: offset + i);
454 extracted_type_args.SetTypeAt(index: i, value: type_arg);
455 }
456 extracted_type_args =
457 extracted_type_args.Canonicalize(thread); // Can be null.
458 }
459 }
460 // Call the closure 'extract'.
461 Array& args_desc = Array::Handle(zone);
462 Array& args = Array::Handle(zone);
463 if (extracted_type_args.IsNull()) {
464 args_desc = ArgumentsDescriptor::NewBoxed(type_args_len: 0, num_arguments: 1);
465 args = Array::New(len: 1);
466 args.SetAt(index: 0, value: extract);
467 } else {
468 args_desc = ArgumentsDescriptor::NewBoxed(type_args_len: num_type_args, num_arguments: 1);
469 args = Array::New(len: 2);
470 args.SetAt(index: 0, value: extracted_type_args);
471 args.SetAt(index: 1, value: extract);
472 }
473 const Object& result =
474 Object::Handle(zone, ptr: DartEntry::InvokeClosure(thread, arguments: args, arguments_descriptor: args_desc));
475 if (result.IsError()) {
476 Exceptions::PropagateError(error: Error::Cast(obj: result));
477 UNREACHABLE();
478 }
479 return result.ptr();
480}
481
482DEFINE_NATIVE_ENTRY(Internal_prependTypeArguments, 0, 4) {
483 const TypeArguments& function_type_arguments =
484 TypeArguments::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
485 const TypeArguments& parent_type_arguments =
486 TypeArguments::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
487 GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_parent_len, arguments->NativeArgAt(2));
488 GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_len, arguments->NativeArgAt(3));
489 return function_type_arguments.Prepend(
490 zone, other: parent_type_arguments, other_length: smi_parent_len.Value(), total_length: smi_len.Value());
491}
492
493// Check that a set of type arguments satisfy the type parameter bounds on a
494// closure.
495// Arg0: Closure object
496// Arg1: Type arguments to function
497DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 0, 2) {
498 const Closure& closure =
499 Closure::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
500 const Function& target = Function::Handle(zone, ptr: closure.function());
501 ASSERT(target.IsGeneric()); // No need to check bounds for non-generics.
502 const TypeParameters& type_params =
503 TypeParameters::Handle(zone, ptr: target.type_parameters());
504 if (type_params.IsNull() || type_params.AllDynamicBounds()) {
505 // The function is not generic or the bounds are all dynamic.
506 return Object::null();
507 }
508
509 const TypeArguments& type_args_to_check =
510 TypeArguments::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
511
512 // This should be guaranteed by the front-end.
513 ASSERT(type_args_to_check.IsNull() ||
514 type_params.Length() <= type_args_to_check.Length());
515
516 // The bounds on the closure may need instantiation.
517 const TypeArguments& instantiator_type_args =
518 TypeArguments::Handle(zone, ptr: closure.instantiator_type_arguments());
519 const TypeArguments& function_type_args =
520 TypeArguments::Handle(zone, ptr: closure.function_type_arguments());
521
522 AbstractType& supertype = AbstractType::Handle(zone);
523 AbstractType& subtype = AbstractType::Handle(zone);
524 for (intptr_t i = 0; i < type_params.Length(); ++i) {
525 supertype = type_params.BoundAt(index: i);
526 subtype = type_args_to_check.IsNull() ? Object::dynamic_type().ptr()
527 : type_args_to_check.TypeAt(index: i);
528
529 ASSERT(!subtype.IsNull());
530 ASSERT(!supertype.IsNull());
531
532 // The supertype may not be instantiated.
533 if (!AbstractType::InstantiateAndTestSubtype(
534 subtype: &subtype, supertype: &supertype, instantiator_type_args, function_type_args)) {
535 // Throw a dynamic type error.
536 TokenPosition location = TokenPosition::kNoSource;
537 {
538 DartFrameIterator iterator(Thread::Current(),
539 StackFrameIterator::kNoCrossThreadIteration);
540 StackFrame* caller_frame = iterator.NextFrame();
541 ASSERT(caller_frame != nullptr);
542 location = caller_frame->GetTokenPos();
543 }
544 const auto& parameter_name = String::Handle(zone, ptr: type_params.NameAt(index: i));
545 Exceptions::CreateAndThrowTypeError(location, src_type: subtype, dst_type: supertype,
546 dst_name: parameter_name);
547 UNREACHABLE();
548 }
549 }
550
551 return Object::null();
552}
553
554DEFINE_NATIVE_ENTRY(InvocationMirror_unpackTypeArguments, 0, 2) {
555 const TypeArguments& type_arguments =
556 TypeArguments::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
557 const Smi& num_type_arguments =
558 Smi::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 1));
559 bool all_dynamic = type_arguments.IsNull();
560 const intptr_t len =
561 all_dynamic ? num_type_arguments.Value() : type_arguments.Length();
562 const Array& type_list = Array::Handle(
563 zone, ptr: Array::New(len, element_type: Type::Handle(zone, ptr: Type::DartTypeType())));
564 AbstractType& type = AbstractType::Handle(zone);
565 for (intptr_t i = 0; i < len; i++) {
566 if (all_dynamic) {
567 type_list.SetAt(index: i, value: Object::dynamic_type());
568 } else {
569 type = type_arguments.TypeAt(index: i);
570 type_list.SetAt(index: i, value: type);
571 }
572 }
573 type_list.MakeImmutable();
574 return type_list.ptr();
575}
576
577DEFINE_NATIVE_ENTRY(NoSuchMethodError_existingMethodSignature, 0, 3) {
578 const Instance& receiver =
579 Instance::CheckedHandle(zone, ptr: arguments->NativeArgAt(index: 0));
580 GET_NON_NULL_NATIVE_ARGUMENT(String, method_name, arguments->NativeArgAt(1));
581 GET_NON_NULL_NATIVE_ARGUMENT(Smi, invocation_type, arguments->NativeArgAt(2));
582 InvocationMirror::Level level;
583 InvocationMirror::Kind kind;
584 InvocationMirror::DecodeType(type: invocation_type.Value(), level: &level, kind: &kind);
585
586 Function& function = Function::Handle(zone);
587 if (level == InvocationMirror::Level::kTopLevel) {
588 if (receiver.IsString()) return receiver.ptr();
589 ASSERT(receiver.IsNull());
590 return String::null();
591 }
592 if (receiver.IsType()) {
593 const auto& cls = Class::Handle(zone, ptr: Type::Cast(obj: receiver).type_class());
594 const auto& error = Error::Handle(zone, ptr: cls.EnsureIsFinalized(thread));
595 if (!error.IsNull()) {
596 Exceptions::PropagateError(error);
597 UNREACHABLE();
598 }
599 if (level == InvocationMirror::kConstructor) {
600 function = cls.LookupConstructor(name: method_name);
601 if (function.IsNull()) {
602 function = cls.LookupFactory(name: method_name);
603 }
604 } else {
605 function = cls.LookupStaticFunction(name: method_name);
606 }
607 } else if (receiver.IsClosure()) {
608 function = Closure::Cast(obj: receiver).function();
609 } else {
610 auto& cls = Class::Handle(zone, ptr: receiver.clazz());
611 if (level == InvocationMirror::kSuper) {
612 cls = cls.SuperClass();
613 }
614 function = Resolver::ResolveDynamicAnyArgs(zone, receiver_class: cls, function_name: method_name,
615 /*allow_add=*/false);
616 }
617 if (!function.IsNull()) {
618 return function.UserVisibleSignature();
619 }
620 return String::null();
621}
622
623} // namespace dart
624

source code of flutter_engine/third_party/dart/runtime/lib/object.cc