Flutter Engine
The Flutter Engine
object.h
Go to the documentation of this file.
1// Copyright (c) 2012, 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#ifndef RUNTIME_VM_OBJECT_H_
6#define RUNTIME_VM_OBJECT_H_
7
8#if defined(SHOULD_NOT_INCLUDE_RUNTIME)
9#error "Should not include runtime"
10#endif
11
12#include <limits>
13#include <tuple>
14#include <utility>
15
16#include "include/dart_api.h"
17#include "platform/assert.h"
18#include "platform/atomic.h"
20#include "platform/utils.h"
21#include "vm/bitmap.h"
22#include "vm/code_comments.h"
23#include "vm/code_entry_kind.h"
27#include "vm/dart.h"
28#include "vm/flags.h"
29#include "vm/globals.h"
30#include "vm/growable_array.h"
31#include "vm/handles.h"
32#include "vm/heap/heap.h"
33#include "vm/isolate.h"
34#include "vm/json_stream.h"
35#include "vm/os.h"
36#include "vm/raw_object.h"
37#include "vm/report.h"
39#include "vm/thread.h"
40#include "vm/token_position.h"
41
42namespace dart {
43
44// Forward declarations.
45namespace compiler {
46class Assembler;
47}
48
49namespace kernel {
50class Program;
51class TreeNode;
52} // namespace kernel
53
54#define DEFINE_FORWARD_DECLARATION(clazz) class clazz;
56#undef DEFINE_FORWARD_DECLARATION
57class Api;
58class ArgumentsDescriptor;
59class Closure;
60class Code;
61class DeoptInstr;
62class DisassemblyFormatter;
63class FinalizablePersistentHandle;
64class FlowGraphCompiler;
65class HierarchyInfo;
66class LocalScope;
67class CallSiteResetter;
68class CodeStatistics;
69class IsolateGroupReloadContext;
70class ObjectGraphCopier;
71class FunctionTypeMapping;
72class NativeArguments;
73
74#define REUSABLE_FORWARD_DECLARATION(name) class Reusable##name##HandleScope;
76#undef REUSABLE_FORWARD_DECLARATION
77
78class Symbols;
79class BaseTextBuffer;
80
81#if defined(DEBUG)
82#define CHECK_HANDLE() CheckHandle();
83#else
84#define CHECK_HANDLE()
85#endif
86
87// For AllStatic classes like OneByteString. Checks that
88// ContainsCompressedPointers() returns the same value for AllStatic class and
89// class used for handles.
90#define ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(object, handle) \
91 public: /* NOLINT */ \
92 using UntaggedObjectType = dart::Untagged##object; \
93 using ObjectPtrType = dart::object##Ptr; \
94 static_assert(std::is_base_of<dart::handle##Ptr, ObjectPtrType>::value, \
95 #object "Ptr must be a subtype of " #handle "Ptr"); \
96 static_assert(dart::handle::ContainsCompressedPointers() == \
97 UntaggedObjectType::kContainsCompressedPointers, \
98 "Pointer compression in Untagged" #object \
99 " must match pointer compression in Untagged" #handle); \
100 static constexpr bool ContainsCompressedPointers() { \
101 return UntaggedObjectType::kContainsCompressedPointers; \
102 } \
103 \
104 private: /* NOLINT */
105
106#define BASE_OBJECT_IMPLEMENTATION(object, super) \
107 public: /* NOLINT */ \
108 using UntaggedObjectType = dart::Untagged##object; \
109 using ObjectPtrType = dart::object##Ptr; \
110 static_assert(!dart::super::ContainsCompressedPointers() || \
111 UntaggedObjectType::kContainsCompressedPointers, \
112 "Untagged" #object \
113 " must have compressed pointers, as supertype Untagged" #super \
114 " has compressed pointers"); \
115 static constexpr bool ContainsCompressedPointers() { \
116 return UntaggedObjectType::kContainsCompressedPointers; \
117 } \
118 object##Ptr ptr() const { \
119 return static_cast<object##Ptr>(ptr_); \
120 } \
121 bool Is##object() const { \
122 return true; \
123 } \
124 DART_NOINLINE static object& Handle() { \
125 return static_cast<object&>( \
126 HandleImpl(Thread::Current()->zone(), object::null(), kClassId)); \
127 } \
128 DART_NOINLINE static object& Handle(Zone* zone) { \
129 return static_cast<object&>(HandleImpl(zone, object::null(), kClassId)); \
130 } \
131 DART_NOINLINE static object& Handle(object##Ptr ptr) { \
132 return static_cast<object&>( \
133 HandleImpl(Thread::Current()->zone(), ptr, kClassId)); \
134 } \
135 DART_NOINLINE static object& Handle(Zone* zone, object##Ptr ptr) { \
136 return static_cast<object&>(HandleImpl(zone, ptr, kClassId)); \
137 } \
138 DART_NOINLINE static object& ZoneHandle() { \
139 return static_cast<object&>( \
140 ZoneHandleImpl(Thread::Current()->zone(), object::null(), kClassId)); \
141 } \
142 DART_NOINLINE static object& ZoneHandle(Zone* zone) { \
143 return static_cast<object&>( \
144 ZoneHandleImpl(zone, object::null(), kClassId)); \
145 } \
146 DART_NOINLINE static object& ZoneHandle(object##Ptr ptr) { \
147 return static_cast<object&>( \
148 ZoneHandleImpl(Thread::Current()->zone(), ptr, kClassId)); \
149 } \
150 DART_NOINLINE static object& ZoneHandle(Zone* zone, object##Ptr ptr) { \
151 return static_cast<object&>(ZoneHandleImpl(zone, ptr, kClassId)); \
152 } \
153 static object* ReadOnlyHandle() { \
154 return static_cast<object*>(ReadOnlyHandleImpl(kClassId)); \
155 } \
156 DART_NOINLINE static object& CheckedHandle(Zone* zone, ObjectPtr ptr) { \
157 object* obj = reinterpret_cast<object*>(VMHandles::AllocateHandle(zone)); \
158 initializeHandle(obj, ptr); \
159 if (!obj->Is##object()) { \
160 FATAL("Handle check failed: saw %s expected %s", obj->ToCString(), \
161 #object); \
162 } \
163 return *obj; \
164 } \
165 DART_NOINLINE static object& CheckedZoneHandle(Zone* zone, ObjectPtr ptr) { \
166 object* obj = \
167 reinterpret_cast<object*>(VMHandles::AllocateZoneHandle(zone)); \
168 initializeHandle(obj, ptr); \
169 if (!obj->Is##object()) { \
170 FATAL("Handle check failed: saw %s expected %s", obj->ToCString(), \
171 #object); \
172 } \
173 return *obj; \
174 } \
175 DART_NOINLINE static object& CheckedZoneHandle(ObjectPtr ptr) { \
176 return CheckedZoneHandle(Thread::Current()->zone(), ptr); \
177 } \
178 /* T::Cast cannot be applied to a null Object, because the object vtable */ \
179 /* is not setup for type T, although some methods are supposed to work */ \
180 /* with null, for example Instance::Equals(). */ \
181 static const object& Cast(const Object& obj) { \
182 ASSERT(obj.Is##object()); \
183 return reinterpret_cast<const object&>(obj); \
184 } \
185 static object##Ptr RawCast(ObjectPtr raw) { \
186 ASSERT(Is##object##NoHandle(raw)); \
187 return static_cast<object##Ptr>(raw); \
188 } \
189 static object##Ptr null() { \
190 return static_cast<object##Ptr>(Object::null()); \
191 } \
192 virtual const char* ToCString() const; \
193 static const ClassId kClassId = k##object##Cid; \
194 \
195 private: /* NOLINT */ \
196 /* Initialize the handle based on the ptr in the presence of null. */ \
197 static void initializeHandle(object* obj, ObjectPtr ptr) { \
198 obj->setPtr(ptr, kClassId); \
199 } \
200 /* Disallow allocation, copy constructors and override super assignment. */ \
201 public: /* NOLINT */ \
202 void operator delete(void* pointer) { \
203 UNREACHABLE(); \
204 } \
205 \
206 private: /* NOLINT */ \
207 void* operator new(size_t size); \
208 object(const object& value) = delete; \
209 void operator=(super##Ptr value) = delete; \
210 void operator=(const object& value) = delete; \
211 void operator=(const super& value) = delete;
212
213// Conditionally include object_service.cc functionality in the vtable to avoid
214// link errors like the following:
215//
216// object.o:(.rodata._ZTVN4....E[_ZTVN4...E]+0x278):
217// undefined reference to
218// `dart::Instance::PrintSharedInstanceJSON(dart::JSONObject*, bool) const'.
219//
220#ifndef PRODUCT
221#define OBJECT_SERVICE_SUPPORT(object) \
222 protected: /* NOLINT */ \
223 /* Object is printed as JSON into stream. If ref is true only a header */ \
224 /* with an object id is printed. If ref is false the object is fully */ \
225 /* printed. */ \
226 virtual void PrintJSONImpl(JSONStream* stream, bool ref) const; \
227 /* Prints JSON objects that describe the implementation-level fields of */ \
228 /* the current Object to |jsarr_fields|. */ \
229 virtual void PrintImplementationFieldsImpl(const JSONArray& jsarr_fields) \
230 const; \
231 virtual const char* JSONType() const { \
232 return "" #object; \
233 }
234#else
235#define OBJECT_SERVICE_SUPPORT(object) protected: /* NOLINT */
236#endif // !PRODUCT
237
238#define SNAPSHOT_SUPPORT(object) \
239 friend class object##MessageSerializationCluster; \
240 friend class object##MessageDeserializationCluster;
241
242#define OBJECT_IMPLEMENTATION(object, super) \
243 public: /* NOLINT */ \
244 DART_NOINLINE void operator=(object##Ptr value) { \
245 initializeHandle(this, value); \
246 } \
247 DART_NOINLINE void operator^=(ObjectPtr value) { \
248 initializeHandle(this, value); \
249 ASSERT(IsNull() || Is##object()); \
250 } \
251 \
252 protected: /* NOLINT */ \
253 object() : super() {} \
254 BASE_OBJECT_IMPLEMENTATION(object, super) \
255 OBJECT_SERVICE_SUPPORT(object) \
256 friend class Object;
257
258extern "C" void DFLRT_ExitSafepoint(NativeArguments __unusable_);
259
260#define HEAP_OBJECT_IMPLEMENTATION(object, super) \
261 OBJECT_IMPLEMENTATION(object, super); \
262 Untagged##object* untag() const { \
263 ASSERT(ptr() != null()); \
264 return const_cast<Untagged##object*>(ptr()->untag()); \
265 } \
266 SNAPSHOT_SUPPORT(object) \
267 friend class StackFrame; \
268 friend class Thread; \
269 friend void DFLRT_ExitSafepoint(NativeArguments __unusable_);
270
271// This macro is used to denote types that do not have a sub-type.
272#define FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super) \
273 public: /* NOLINT */ \
274 void operator=(object##Ptr value) { \
275 ptr_ = value; \
276 CHECK_HANDLE(); \
277 } \
278 void operator^=(ObjectPtr value) { \
279 ptr_ = value; \
280 CHECK_HANDLE(); \
281 } \
282 \
283 private: /* NOLINT */ \
284 object() : super() {} \
285 BASE_OBJECT_IMPLEMENTATION(object, super) \
286 OBJECT_SERVICE_SUPPORT(object) \
287 Untagged##object* untag() const { \
288 ASSERT(ptr() != null()); \
289 return const_cast<Untagged##object*>(ptr()->untag()); \
290 } \
291 static intptr_t NextFieldOffset() { \
292 return -kWordSize; \
293 } \
294 SNAPSHOT_SUPPORT(rettype) \
295 friend class Object; \
296 friend class StackFrame; \
297 friend class Thread; \
298 friend void DFLRT_ExitSafepoint(NativeArguments __unusable_);
299
300#define FINAL_HEAP_OBJECT_IMPLEMENTATION(object, super) \
301 FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, object, super)
302
303#define MINT_OBJECT_IMPLEMENTATION(object, rettype, super) \
304 FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super)
305
306// In precompiled runtime, there is no access to runtime_api.cc since host
307// and target are the same. In those cases, the namespace dart is used to refer
308// to the target namespace
309#if defined(DART_PRECOMPILED_RUNTIME)
310namespace RTN = dart;
311#else
312namespace RTN = dart::compiler::target;
313#endif // defined(DART_PRECOMPILED_RUNTIME)
314
315class Object {
316 public:
319
320 // We use 30 bits for the hash code so hashes in a snapshot taken on a
321 // 64-bit architecture stay in Smi range when loaded on a 32-bit
322 // architecture.
323 static constexpr intptr_t kHashBits = 30;
324
325 static ObjectPtr RawCast(ObjectPtr obj) { return obj; }
326
327 virtual ~Object() {}
328
329 static constexpr bool ContainsCompressedPointers() {
331 }
332 ObjectPtr ptr() const { return ptr_; }
333 void operator=(ObjectPtr value) { initializeHandle(this, value); }
334
335 bool IsCanonical() const { return ptr()->untag()->IsCanonical(); }
336 void SetCanonical() const { ptr()->untag()->SetCanonical(); }
337 void ClearCanonical() const { ptr()->untag()->ClearCanonical(); }
338 bool IsImmutable() const { return ptr()->untag()->IsImmutable(); }
339 void SetImmutable() const { ptr()->untag()->SetImmutable(); }
340 void ClearImmutable() const { ptr()->untag()->ClearImmutable(); }
341 intptr_t GetClassId() const {
342 return !ptr()->IsHeapObject() ? static_cast<intptr_t>(kSmiCid)
343 : ptr()->untag()->GetClassId();
344 }
345 inline ClassPtr clazz() const;
346 static intptr_t tags_offset() { return OFFSET_OF(UntaggedObject, tags_); }
347
348// Class testers.
349#define DEFINE_CLASS_TESTER(clazz) \
350 virtual bool Is##clazz() const { return false; } \
351 static bool Is##clazz##NoHandle(ObjectPtr ptr) { \
352 /* Use a stack handle to make RawCast safe in contexts where handles */ \
353 /* should not be allocated, such as GC or runtime transitions. Not */ \
354 /* using Object's constructor to avoid Is##clazz being de-virtualized. */ \
355 char buf[sizeof(Object)]; \
356 Object* obj = reinterpret_cast<Object*>(&buf); \
357 initializeHandle(obj, ptr); \
358 return obj->IsNull() || obj->Is##clazz(); \
359 }
361#undef DEFINE_CLASS_TESTER
362
363 bool IsNull() const { return ptr_ == null_; }
364
365 // Matches Object.toString on instances (except String::ToCString, bug 20583).
366 virtual const char* ToCString() const {
367 if (IsNull()) {
368 return "null";
369 } else {
370 return "Object";
371 }
372 }
373
374#ifndef PRODUCT
375 void PrintJSON(JSONStream* stream, bool ref = true) const;
376 virtual void PrintJSONImpl(JSONStream* stream, bool ref) const;
379 const JSONArray& jsarr_fields) const;
380 virtual const char* JSONType() const { return IsNull() ? "null" : "Object"; }
381#endif
382
383 // Returns the name that is used to identify an object in the
384 // namespace dictionary.
385 // Object::DictionaryName() returns String::null(). Only subclasses
386 // of Object that need to be entered in the library and library prefix
387 // namespaces need to provide an implementation.
388 virtual StringPtr DictionaryName() const;
389
390 bool IsNew() const { return ptr()->IsNewObject(); }
391 bool IsOld() const { return ptr()->IsOldObject(); }
392#if defined(DEBUG)
393 bool InVMIsolateHeap() const;
394#else
395 bool InVMIsolateHeap() const { return ptr()->untag()->InVMIsolateHeap(); }
396#endif // DEBUG
397
398 // Print the object on stdout for debugging.
399 void Print() const;
400
401#if defined(DEBUG)
402 bool IsZoneHandle() const;
403 bool IsReadOnlyHandle() const;
404 bool IsNotTemporaryScopedHandle() const;
405#endif
406
407 static Object& Handle() {
408 return HandleImpl(Thread::Current()->zone(), null_, kObjectCid);
409 }
410 static Object& Handle(Zone* zone) {
411 return HandleImpl(zone, null_, kObjectCid);
412 }
414 return HandleImpl(Thread::Current()->zone(), ptr, kObjectCid);
415 }
416 static Object& Handle(Zone* zone, ObjectPtr ptr) {
417 return HandleImpl(zone, ptr, kObjectCid);
418 }
419 static Object& ZoneHandle() {
420 return ZoneHandleImpl(Thread::Current()->zone(), null_, kObjectCid);
421 }
422 static Object& ZoneHandle(Zone* zone) {
423 return ZoneHandleImpl(zone, null_, kObjectCid);
424 }
426 return ZoneHandleImpl(Thread::Current()->zone(), ptr, kObjectCid);
427 }
429 return ZoneHandleImpl(zone, ptr, kObjectCid);
430 }
431 static Object* ReadOnlyHandle() { return ReadOnlyHandleImpl(kObjectCid); }
432
433 static ObjectPtr null() { return null_; }
434
435#if defined(HASH_IN_OBJECT_HEADER)
436 static uint32_t GetCachedHash(const ObjectPtr obj) {
437 return obj->untag()->GetHeaderHash();
438 }
439
440 static uint32_t SetCachedHashIfNotSet(ObjectPtr obj, uint32_t hash) {
441 return obj->untag()->SetHeaderHashIfNotSet(hash);
442 }
443#endif
444
445 // The list below enumerates read-only handles for singleton
446 // objects that are shared between the different isolates.
447 //
448 // - sentinel is a value that cannot be produced by Dart code. It can be used
449 // to mark special values, for example to distinguish "uninitialized" fields.
450 // - transition_sentinel is a value marking that we are transitioning from
451 // sentinel, e.g., computing a field value. Used to detect circular
452 // initialization.
453 // - unknown_constant and non_constant are optimizing compiler's constant
454 // propagation constants.
455 // - optimized_out results from deopt environment pruning or failure to
456 // capture variables in a closure's context
457#define SHARED_READONLY_HANDLES_LIST(V) \
458 V(Object, null_object) \
459 V(Class, null_class) \
460 V(Array, null_array) \
461 V(String, null_string) \
462 V(Instance, null_instance) \
463 V(Function, null_function) \
464 V(FunctionType, null_function_type) \
465 V(RecordType, null_record_type) \
466 V(TypeArguments, null_type_arguments) \
467 V(CompressedStackMaps, null_compressed_stackmaps) \
468 V(Closure, null_closure) \
469 V(TypeArguments, empty_type_arguments) \
470 V(Array, empty_array) \
471 V(Array, empty_instantiations_cache_array) \
472 V(Array, empty_subtype_test_cache_array) \
473 V(ContextScope, empty_context_scope) \
474 V(ObjectPool, empty_object_pool) \
475 V(CompressedStackMaps, empty_compressed_stackmaps) \
476 V(PcDescriptors, empty_descriptors) \
477 V(LocalVarDescriptors, empty_var_descriptors) \
478 V(ExceptionHandlers, empty_exception_handlers) \
479 V(ExceptionHandlers, empty_async_exception_handlers) \
480 V(Array, synthetic_getter_parameter_types) \
481 V(Array, synthetic_getter_parameter_names) \
482 V(Sentinel, sentinel) \
483 V(Sentinel, transition_sentinel) \
484 V(Sentinel, unknown_constant) \
485 V(Sentinel, non_constant) \
486 V(Sentinel, optimized_out) \
487 V(Bool, bool_true) \
488 V(Bool, bool_false) \
489 V(Smi, smi_illegal_cid) \
490 V(Smi, smi_zero) \
491 V(ApiError, no_callbacks_error) \
492 V(UnwindError, unwind_in_progress_error) \
493 V(LanguageError, snapshot_writer_error) \
494 V(LanguageError, branch_offset_error) \
495 V(LanguageError, speculative_inlining_error) \
496 V(LanguageError, background_compilation_error) \
497 V(LanguageError, out_of_memory_error) \
498 V(Array, vm_isolate_snapshot_object_table) \
499 V(Type, dynamic_type) \
500 V(Type, void_type) \
501 V(AbstractType, null_abstract_type)
502
503#define DEFINE_SHARED_READONLY_HANDLE_GETTER(Type, name) \
504 static const Type& name() { \
505 ASSERT(name##_ != nullptr); \
506 return *name##_; \
507 }
509#undef DEFINE_SHARED_READONLY_HANDLE_GETTER
510
511 static void set_vm_isolate_snapshot_object_table(const Array& table);
512
513 static ClassPtr class_class() { return class_class_; }
514 static ClassPtr dynamic_class() { return dynamic_class_; }
515 static ClassPtr void_class() { return void_class_; }
516 static ClassPtr type_parameters_class() { return type_parameters_class_; }
517 static ClassPtr type_arguments_class() { return type_arguments_class_; }
518 static ClassPtr patch_class_class() { return patch_class_class_; }
519 static ClassPtr function_class() { return function_class_; }
520 static ClassPtr closure_data_class() { return closure_data_class_; }
521 static ClassPtr ffi_trampoline_data_class() {
522 return ffi_trampoline_data_class_;
523 }
524 static ClassPtr field_class() { return field_class_; }
525 static ClassPtr script_class() { return script_class_; }
526 static ClassPtr library_class() { return library_class_; }
527 static ClassPtr namespace_class() { return namespace_class_; }
528 static ClassPtr kernel_program_info_class() {
529 return kernel_program_info_class_;
530 }
531 static ClassPtr code_class() { return code_class_; }
532 static ClassPtr instructions_class() { return instructions_class_; }
533 static ClassPtr instructions_section_class() {
534 return instructions_section_class_;
535 }
536 static ClassPtr instructions_table_class() {
537 return instructions_table_class_;
538 }
539 static ClassPtr object_pool_class() { return object_pool_class_; }
540 static ClassPtr pc_descriptors_class() { return pc_descriptors_class_; }
541 static ClassPtr code_source_map_class() { return code_source_map_class_; }
542 static ClassPtr compressed_stackmaps_class() {
543 return compressed_stackmaps_class_;
544 }
545 static ClassPtr var_descriptors_class() { return var_descriptors_class_; }
546 static ClassPtr exception_handlers_class() {
547 return exception_handlers_class_;
548 }
549 static ClassPtr context_class() { return context_class_; }
550 static ClassPtr context_scope_class() { return context_scope_class_; }
551 static ClassPtr sentinel_class() { return sentinel_class_; }
552 static ClassPtr api_error_class() { return api_error_class_; }
553 static ClassPtr language_error_class() { return language_error_class_; }
554 static ClassPtr unhandled_exception_class() {
555 return unhandled_exception_class_;
556 }
557 static ClassPtr unwind_error_class() { return unwind_error_class_; }
558 static ClassPtr singletargetcache_class() { return singletargetcache_class_; }
559 static ClassPtr unlinkedcall_class() { return unlinkedcall_class_; }
561 return monomorphicsmiablecall_class_;
562 }
563 static ClassPtr icdata_class() { return icdata_class_; }
564 static ClassPtr megamorphic_cache_class() { return megamorphic_cache_class_; }
565 static ClassPtr subtypetestcache_class() { return subtypetestcache_class_; }
566 static ClassPtr loadingunit_class() { return loadingunit_class_; }
568 return weak_serialization_reference_class_;
569 }
570 static ClassPtr weak_array_class() { return weak_array_class_; }
571
572 // Initialize the VM isolate.
573 static void InitNullAndBool(IsolateGroup* isolate_group);
574 static void Init(IsolateGroup* isolate_group);
575 static void InitVtables();
576 static void FinishInit(IsolateGroup* isolate_group);
577 static void FinalizeVMIsolate(IsolateGroup* isolate_group);
578 static void FinalizeReadOnlyObject(ObjectPtr object);
579
580 static void Cleanup();
581
582 // Initialize a new isolate either from a Kernel IR, from source, or from a
583 // snapshot.
584 static ErrorPtr Init(IsolateGroup* isolate_group,
585 const uint8_t* kernel_buffer,
586 intptr_t kernel_buffer_size);
587
588 static void MakeUnusedSpaceTraversable(const Object& obj,
589 intptr_t original_size,
590 intptr_t used_size);
591
592 static intptr_t InstanceSize() {
594 }
595
596 template <class FakeObject>
597 static void VerifyBuiltinVtable(intptr_t cid) {
598 FakeObject fake;
599 if (cid >= kNumPredefinedCids) {
600 cid = kInstanceCid;
601 }
602 ASSERT(builtin_vtables_[cid] == fake.vtable());
603 }
604 static void VerifyBuiltinVtables();
605
606 static const ClassId kClassId = kObjectCid;
607
608 // Different kinds of name visibility.
610 // Internal names are the true names of classes, fields,
611 // etc. inside the vm. These names include privacy suffixes,
612 // getter prefixes, and trailing dots on unnamed constructors.
613 //
614 // The names of core implementation classes (like _OneByteString)
615 // are preserved as well.
616 //
617 // e.g.
618 // private getter -> get:foo@6be832b
619 // private constructor -> _MyClass@6b3832b.
620 // private named constructor -> _MyClass@6b3832b.named
621 // core impl class name shown -> _OneByteString
623
624 // Scrubbed names drop privacy suffixes, getter prefixes, and
625 // trailing dots on unnamed constructors. These names are used in
626 // the vm service.
627 //
628 // e.g.
629 // get:foo@6be832b -> foo
630 // _MyClass@6b3832b. -> _MyClass
631 // _MyClass@6b3832b.named -> _MyClass.named
632 // _OneByteString -> _OneByteString (not remapped)
634
635 // User visible names are appropriate for reporting type errors
636 // directly to programmers. The names have been scrubbed and
637 // the names of core implementation classes are remapped to their
638 // public interface names.
639 //
640 // e.g.
641 // get:foo@6be832b -> foo
642 // _MyClass@6b3832b. -> _MyClass
643 // _MyClass@6b3832b.named -> _MyClass.named
644 // _OneByteString -> String (remapped)
646 };
647
648 // Sometimes simple formating might produce the same name for two different
649 // entities, for example we might inject a synthetic forwarder into the
650 // class which has the same name as an already existing function, or
651 // two different types can be formatted as X<T> because T has different
652 // meaning (refers to a different type parameter) in these two types.
653 // Such ambiguity might be acceptable in some contexts but not in others, so
654 // some formatting methods have two modes - one which tries to be more
655 // user friendly, and another one which tries to avoid name conflicts by
656 // emitting longer and less user friendly names.
658 kYes,
659 kNo,
660 };
661
662 static bool ShouldHaveImmutabilityBitSet(classid_t class_id);
663
664 protected:
665 friend ObjectPtr AllocateObject(intptr_t, intptr_t, intptr_t);
666
667 // Used for extracting the C++ vtable during bringup.
668 Object() : ptr_(null_) {}
669
670 uword raw_value() const { return static_cast<uword>(ptr()); }
671
672 inline void setPtr(ObjectPtr value, intptr_t default_cid);
673 void CheckHandle() const;
674 DART_NOINLINE static Object& HandleImpl(Zone* zone,
676 intptr_t default_cid) {
677 Object* obj = reinterpret_cast<Object*>(VMHandles::AllocateHandle(zone));
678 obj->setPtr(ptr, default_cid);
679 return *obj;
680 }
681 DART_NOINLINE static Object& ZoneHandleImpl(Zone* zone,
683 intptr_t default_cid) {
684 Object* obj =
685 reinterpret_cast<Object*>(VMHandles::AllocateZoneHandle(zone));
686 obj->setPtr(ptr, default_cid);
687 return *obj;
688 }
689 DART_NOINLINE static Object* ReadOnlyHandleImpl(intptr_t cid) {
690 Object* obj = reinterpret_cast<Object*>(Dart::AllocateReadOnlyHandle());
691 obj->setPtr(Object::null(), cid);
692 return obj;
693 }
694
695 // Memcpy to account for the strict aliasing rule.
696 // Explicit cast to silence -Wdynamic-class-memaccess.
697 // This is still undefined behavior because we're messing with the internal
698 // representation of C++ objects, but works okay in practice with
699 // -fno-strict-vtable-pointers.
702 memcpy(&result, reinterpret_cast<const void*>(this), // NOLINT
703 sizeof(result));
704 return result;
705 }
707 memcpy(reinterpret_cast<void*>(this), &value, // NOLINT
708 sizeof(cpp_vtable));
709 }
710
711 static ObjectPtr Allocate(intptr_t cls_id,
712 intptr_t size,
713 Heap::Space space,
714 bool compressed,
715 uword ptr_field_start_offset,
716 uword ptr_field_end_offset);
717
718 // Templates of Allocate that retrieve the appropriate values to pass from
719 // the class.
720
721 template <typename T>
722 DART_FORCE_INLINE static typename T::ObjectPtrType Allocate(
723 Heap::Space space) {
724 return static_cast<typename T::ObjectPtrType>(Allocate(
725 T::kClassId, T::InstanceSize(), space, T::ContainsCompressedPointers(),
726 Object::from_offset<T>(), Object::to_offset<T>()));
727 }
728 template <typename T>
729 DART_FORCE_INLINE static typename T::ObjectPtrType Allocate(
730 Heap::Space space,
731 intptr_t elements) {
732 return static_cast<typename T::ObjectPtrType>(
733 Allocate(T::kClassId, T::InstanceSize(elements), space,
734 T::ContainsCompressedPointers(), Object::from_offset<T>(),
735 Object::to_offset<T>(elements)));
736 }
737
738 // Additional versions that also take a class_id for types like Array, Map,
739 // and Set that have more than one possible class id.
740
741 template <typename T>
742 DART_FORCE_INLINE static typename T::ObjectPtrType AllocateVariant(
743 intptr_t class_id,
744 Heap::Space space) {
745 return static_cast<typename T::ObjectPtrType>(Allocate(
746 class_id, T::InstanceSize(), space, T::ContainsCompressedPointers(),
747 Object::from_offset<T>(), Object::to_offset<T>()));
748 }
749 template <typename T>
750 DART_FORCE_INLINE static typename T::ObjectPtrType
751 AllocateVariant(intptr_t class_id, Heap::Space space, intptr_t elements) {
752 return static_cast<typename T::ObjectPtrType>(
753 Allocate(class_id, T::InstanceSize(elements), space,
754 T::ContainsCompressedPointers(), Object::from_offset<T>(),
755 Object::to_offset<T>(elements)));
756 }
757
758 static constexpr intptr_t RoundedAllocationSize(intptr_t size) {
760 }
761
762 bool Contains(uword addr) const { return ptr()->untag()->Contains(addr); }
763
764 // Start of field mutator guards.
765 //
766 // All writes to heap objects should ultimately pass through one of the
767 // methods below or their counterparts in UntaggedObject, to ensure that the
768 // write barrier is correctly applied.
769
770 template <typename type, std::memory_order order = std::memory_order_relaxed>
771 type LoadPointer(type const* addr) const {
772 return ptr()->untag()->LoadPointer<type, order>(addr);
773 }
774
775 template <typename type, std::memory_order order = std::memory_order_relaxed>
776 void StorePointer(type const* addr, type value) const {
777 ptr()->untag()->StorePointer<type, order>(addr, value);
778 }
779 template <typename type,
780 typename compressed_type,
781 std::memory_order order = std::memory_order_relaxed>
782 void StoreCompressedPointer(compressed_type const* addr, type value) const {
783 ptr()->untag()->StoreCompressedPointer<type, compressed_type, order>(addr,
784 value);
785 }
786 template <typename type>
788 type value,
789 Thread* thread) const {
790 ptr()->untag()->StorePointerUnaligned<type>(addr, value, thread);
791 }
792
793 // Use for storing into an explicitly Smi-typed field of an object
794 // (i.e., both the previous and new value are Smis).
795 void StoreSmi(SmiPtr const* addr, SmiPtr value) const {
796 ptr()->untag()->StoreSmi(addr, value);
797 }
798
799 template <typename FieldType>
800 void StoreSimd128(const FieldType* addr, simd128_value_t value) const {
801 ASSERT(Contains(reinterpret_cast<uword>(addr)));
802 value.writeTo(const_cast<FieldType*>(addr));
803 }
804
805 template <typename FieldType>
806 FieldType LoadNonPointer(const FieldType* addr) const {
807 return *const_cast<FieldType*>(addr);
808 }
809
810 template <typename FieldType, std::memory_order order>
811 FieldType LoadNonPointer(const FieldType* addr) const {
812 return reinterpret_cast<std::atomic<FieldType>*>(
813 const_cast<FieldType*>(addr))
814 ->load(order);
815 }
816
817 // Needs two template arguments to allow assigning enums to fixed-size ints.
818 template <typename FieldType, typename ValueType>
819 void StoreNonPointer(const FieldType* addr, ValueType value) const {
820 // Can't use Contains, as it uses tags_, which is set through this method.
821 ASSERT(reinterpret_cast<uword>(addr) >= UntaggedObject::ToAddr(ptr()));
822 *const_cast<FieldType*>(addr) = value;
823 }
824
825 template <typename FieldType, typename ValueType, std::memory_order order>
826 void StoreNonPointer(const FieldType* addr, ValueType value) const {
827 // Can't use Contains, as it uses tags_, which is set through this method.
828 ASSERT(reinterpret_cast<uword>(addr) >= UntaggedObject::ToAddr(ptr()));
829 reinterpret_cast<std::atomic<FieldType>*>(const_cast<FieldType*>(addr))
830 ->store(value, order);
831 }
832
833 // Provides non-const access to non-pointer fields within the object. Such
834 // access does not need a write barrier, but it is *not* GC-safe, since the
835 // object might move, hence must be fully contained within a NoSafepointScope.
836 template <typename FieldType>
837 FieldType* UnsafeMutableNonPointer(const FieldType* addr) const {
838 // Allow pointers at the end of variable-length data, and disallow pointers
839 // within the header word.
840 ASSERT(Contains(reinterpret_cast<uword>(addr) - 1) &&
841 Contains(reinterpret_cast<uword>(addr) - kWordSize));
842 // At least check that there is a NoSafepointScope and hope it's big enough.
843 ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
844 return const_cast<FieldType*>(addr);
845 }
846
847// Fail at link time if StoreNonPointer or UnsafeMutableNonPointer is
848// instantiated with an object pointer type.
849#define STORE_NON_POINTER_ILLEGAL_TYPE(type) \
850 template <typename ValueType> \
851 void StoreNonPointer(type##Ptr const* addr, ValueType value) const { \
852 UnimplementedMethod(); \
853 } \
854 type##Ptr* UnsafeMutableNonPointer(type##Ptr const* addr) const { \
855 UnimplementedMethod(); \
856 return nullptr; \
857 }
858
861#undef STORE_NON_POINTER_ILLEGAL_TYPE
862
863 // Allocate an object and copy the body of 'orig'.
864 static ObjectPtr Clone(const Object& orig,
865 Heap::Space space,
866 bool load_with_relaxed_atomics = false);
867
868 // End of field mutator guards.
869
870 ObjectPtr ptr_; // The raw object reference.
871
872 protected:
873 // The first offset in an allocated object of the given type that contains a
874 // (possibly compressed) object pointer. Used to initialize object pointer
875 // fields to Object::null() instead of 0.
876 //
877 // Always returns an offset after the object header tags.
878 template <typename T>
879 DART_FORCE_INLINE static uword from_offset() {
880 return UntaggedObject::from_offset<typename T::UntaggedObjectType>();
881 }
882
883 // The last offset in an allocated object of the given type that contains a
884 // (possibly compressed) object pointer. Used to initialize object pointer
885 // fields to Object::null() instead of 0.
886 //
887 // Takes an optional argument that is the number of elements in the payload,
888 // which is ignored if the object never contains a payload.
889 //
890 // If there are no pointer fields in the object, then
891 // to_offset<T>() < from_offset<T>().
892 template <typename T>
893 DART_FORCE_INLINE static uword to_offset(intptr_t length = 0) {
894 return UntaggedObject::to_offset<typename T::UntaggedObjectType>(length);
895 }
896
898 const char* protocol_type,
899 bool ref) const;
900
901 private:
902 static intptr_t NextFieldOffset() {
903 // Indicates this class cannot be extended by dart code.
904 return -kWordSize;
905 }
906
907 static void InitializeObject(uword address,
908 intptr_t id,
909 intptr_t size,
910 bool compressed,
911 uword ptr_field_start_offset,
912 uword ptr_field_end_offset);
913
914 // Templates of InitializeObject that retrieve the appropriate values to pass
915 // from the class.
916
917 template <typename T>
918 DART_FORCE_INLINE static void InitializeObject(uword address) {
919 return InitializeObject(address, T::kClassId, T::InstanceSize(),
920 T::ContainsCompressedPointers(),
921 Object::from_offset<T>(), Object::to_offset<T>());
922 }
923 template <typename T>
924 DART_FORCE_INLINE static void InitializeObject(uword address,
925 intptr_t elements) {
926 return InitializeObject(address, T::kClassId, T::InstanceSize(elements),
927 T::ContainsCompressedPointers(),
928 Object::from_offset<T>(),
929 Object::to_offset<T>(elements));
930 }
931
932 // Additional versions that also take a class_id for types like Array, Map,
933 // and Set that have more than one possible class id.
934
935 template <typename T>
936 DART_FORCE_INLINE static void InitializeObjectVariant(uword address,
937 intptr_t class_id) {
938 return InitializeObject(address, class_id, T::InstanceSize(),
939 T::ContainsCompressedPointers(),
940 Object::from_offset<T>(), Object::to_offset<T>());
941 }
942 template <typename T>
943 DART_FORCE_INLINE static void InitializeObjectVariant(uword address,
944 intptr_t class_id,
945 intptr_t elements) {
946 return InitializeObject(address, class_id, T::InstanceSize(elements),
947 T::ContainsCompressedPointers(),
948 Object::from_offset<T>(),
949 Object::to_offset<T>(elements));
950 }
951
952 static void RegisterClass(const Class& cls,
953 const String& name,
954 const Library& lib);
955 static void RegisterPrivateClass(const Class& cls,
956 const String& name,
957 const Library& lib);
958
959 /* Initialize the handle based on the ptr in the presence of null. */
960 static void initializeHandle(Object* obj, ObjectPtr ptr) {
961 obj->setPtr(ptr, kObjectCid);
962 }
963
964 static cpp_vtable builtin_vtables_[kNumPredefinedCids];
965
966 // The static values below are singletons shared between the different
967 // isolates. They are all allocated in the non-GC'd Dart::vm_isolate_.
968 static ObjectPtr null_;
969 static BoolPtr true_;
970 static BoolPtr false_;
971
972 static ClassPtr class_class_;
973 static ClassPtr dynamic_class_;
974 static ClassPtr void_class_;
975 static ClassPtr type_parameters_class_;
976 static ClassPtr type_arguments_class_;
977 static ClassPtr patch_class_class_;
978 static ClassPtr function_class_;
979 static ClassPtr closure_data_class_;
980 static ClassPtr ffi_trampoline_data_class_;
981 static ClassPtr field_class_;
982 static ClassPtr script_class_;
983 static ClassPtr library_class_;
984 static ClassPtr namespace_class_;
985 static ClassPtr kernel_program_info_class_;
986 static ClassPtr code_class_;
987 static ClassPtr instructions_class_;
988 static ClassPtr instructions_section_class_;
989 static ClassPtr instructions_table_class_;
990 static ClassPtr object_pool_class_;
991 static ClassPtr pc_descriptors_class_;
992 static ClassPtr code_source_map_class_;
993 static ClassPtr compressed_stackmaps_class_;
994 static ClassPtr var_descriptors_class_;
995 static ClassPtr exception_handlers_class_;
996 static ClassPtr context_class_;
997 static ClassPtr context_scope_class_;
998 static ClassPtr sentinel_class_;
999 static ClassPtr singletargetcache_class_;
1000 static ClassPtr unlinkedcall_class_;
1001 static ClassPtr monomorphicsmiablecall_class_;
1002 static ClassPtr icdata_class_;
1003 static ClassPtr megamorphic_cache_class_;
1004 static ClassPtr subtypetestcache_class_;
1005 static ClassPtr loadingunit_class_;
1006 static ClassPtr api_error_class_;
1007 static ClassPtr language_error_class_;
1008 static ClassPtr unhandled_exception_class_;
1009 static ClassPtr unwind_error_class_;
1010 static ClassPtr weak_serialization_reference_class_;
1011 static ClassPtr weak_array_class_;
1012
1013#define DECLARE_SHARED_READONLY_HANDLE(Type, name) static Type* name##_;
1015#undef DECLARE_SHARED_READONLY_HANDLE
1016
1017 friend void ClassTable::Register(const Class& cls);
1018 friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const;
1019 friend class Closure;
1021 friend class ObjectGraphCopier; // For Object::InitializeObject
1023 friend class OneByteString;
1024 friend class TwoByteString;
1025 friend class Thread;
1026
1027#define REUSABLE_FRIEND_DECLARATION(name) \
1028 friend class Reusable##name##HandleScope;
1030#undef REUSABLE_FRIEND_DECLARATION
1031
1034};
1035
1036// Used to declare setters and getters for untagged object fields that are
1037// defined with the WSR_COMPRESSED_POINTER_FIELD macro.
1038//
1039// In the precompiler, the getter transparently unwraps the
1040// WeakSerializationReference, if present, to get the wrapped value of the
1041// appropriate type, since a WeakSerializationReference object should be
1042// transparent to the parts of the precompiler that are not the serializer.
1043// Meanwhile, the setter takes an Object to allow the precompiler to set the
1044// field to a WeakSerializationReference.
1045//
1046// Since WeakSerializationReferences are only used during precompilation,
1047// this macro creates the normally expected getter and setter otherwise.
1048#if defined(DART_PRECOMPILER)
1049#define PRECOMPILER_WSR_FIELD_DECLARATION(Type, Name) \
1050 Type##Ptr Name() const; \
1051 void set_##Name(const Object& value) const { \
1052 untag()->set_##Name(value.ptr()); \
1053 }
1054#else
1055#define PRECOMPILER_WSR_FIELD_DECLARATION(Type, Name) \
1056 Type##Ptr Name() const { \
1057 return untag()->Name(); \
1058 } \
1059 void set_##Name(const Type& value) const;
1060#endif
1061
1062class PassiveObject : public Object {
1063 public:
1066
1068 PassiveObject* obj =
1069 reinterpret_cast<PassiveObject*>(VMHandles::AllocateHandle(zone));
1070 obj->ptr_ = ptr;
1071 obj->set_vtable(0);
1072 return *obj;
1073 }
1075 return Handle(Thread::Current()->zone(), ptr);
1076 }
1078 return Handle(Thread::Current()->zone(), Object::null());
1079 }
1080 static PassiveObject& Handle(Zone* zone) {
1081 return Handle(zone, Object::null());
1082 }
1084 PassiveObject* obj =
1085 reinterpret_cast<PassiveObject*>(VMHandles::AllocateZoneHandle(zone));
1086 obj->ptr_ = ptr;
1087 obj->set_vtable(0);
1088 return *obj;
1089 }
1091 return ZoneHandle(Thread::Current()->zone(), ptr);
1092 }
1094 return ZoneHandle(Thread::Current()->zone(), Object::null());
1095 }
1097 return ZoneHandle(zone, Object::null());
1098 }
1099
1100 private:
1101 PassiveObject() : Object() {}
1102 DISALLOW_ALLOCATION();
1103 DISALLOW_COPY_AND_ASSIGN(PassiveObject);
1104};
1105
1106// A URIs array contains triplets of strings.
1107// The first string in the triplet is a type name (usually a class).
1108// The second string in the triplet is the URI of the type.
1109// The third string in the triplet is "print" if the triplet should be printed.
1111
1112enum class Nullability : uint8_t {
1113 kNullable = 0,
1114 kNonNullable = 1,
1115};
1116
1117// Equality kind between types.
1118enum class TypeEquality {
1119 kCanonical = 0,
1120 kSyntactical = 1,
1121 kInSubtypeTest = 2,
1122};
1123
1124// The NNBDCompiledMode reflects the mode in which constants of the library were
1125// compiled by CFE.
1127 kStrong = 0,
1128 kWeak = 1,
1129 kAgnostic = 2,
1130 kInvalid = 3,
1131};
1132
1133class Class : public Object {
1134 public:
1140 };
1141
1142 bool HasCompressedPointers() const;
1143 intptr_t host_instance_size() const {
1145 return (untag()->host_instance_size_in_words_ * kCompressedWordSize);
1146 }
1147 intptr_t target_instance_size() const {
1149#if defined(DART_PRECOMPILER)
1150 return (untag()->target_instance_size_in_words_ *
1152#else
1153 return host_instance_size();
1154#endif // defined(DART_PRECOMPILER)
1155 }
1156 static intptr_t host_instance_size(ClassPtr clazz) {
1157 return (clazz->untag()->host_instance_size_in_words_ * kCompressedWordSize);
1158 }
1159 static intptr_t target_instance_size(ClassPtr clazz) {
1160#if defined(DART_PRECOMPILER)
1161 return (clazz->untag()->target_instance_size_in_words_ *
1163#else
1164 return host_instance_size(clazz);
1165#endif // defined(DART_PRECOMPILER)
1166 }
1167 void set_instance_size(intptr_t host_value_in_bytes,
1168 intptr_t target_value_in_bytes) const {
1171 host_value_in_bytes / kCompressedWordSize,
1172 target_value_in_bytes / compiler::target::kCompressedWordSize);
1173 }
1174 void set_instance_size_in_words(intptr_t host_value,
1175 intptr_t target_value) const {
1176 ASSERT(
1178 StoreNonPointer(&untag()->host_instance_size_in_words_, host_value);
1179#if defined(DART_PRECOMPILER)
1180 ASSERT(
1183 StoreNonPointer(&untag()->target_instance_size_in_words_, target_value);
1184#else
1185 // Could be different only during cross-compilation.
1186 ASSERT_EQUAL(host_value, target_value);
1187#endif // defined(DART_PRECOMPILER)
1188 }
1189
1190 intptr_t host_next_field_offset() const {
1191 return untag()->host_next_field_offset_in_words_ * kCompressedWordSize;
1192 }
1193 intptr_t target_next_field_offset() const {
1194#if defined(DART_PRECOMPILER)
1195 return untag()->target_next_field_offset_in_words_ *
1197#else
1198 return host_next_field_offset();
1199#endif // defined(DART_PRECOMPILER)
1200 }
1201 void set_next_field_offset(intptr_t host_value_in_bytes,
1202 intptr_t target_value_in_bytes) const {
1204 host_value_in_bytes / kCompressedWordSize,
1205 target_value_in_bytes / compiler::target::kCompressedWordSize);
1206 }
1207 void set_next_field_offset_in_words(intptr_t host_value,
1208 intptr_t target_value) const {
1209 // Assert that the next field offset is either negative (ie, this object
1210 // can't be extended by dart code), or rounds up to the kObjectAligned
1211 // instance size.
1212 ASSERT((host_value < 0) ||
1213 ((host_value <= untag()->host_instance_size_in_words_) &&
1214 (host_value + (kObjectAlignment / kCompressedWordSize) >
1215 untag()->host_instance_size_in_words_)));
1216 StoreNonPointer(&untag()->host_next_field_offset_in_words_, host_value);
1217#if defined(DART_PRECOMPILER)
1218 ASSERT((target_value < 0) ||
1219 ((target_value <= untag()->target_instance_size_in_words_) &&
1220 (target_value + (compiler::target::kObjectAlignment /
1222 untag()->target_instance_size_in_words_)));
1223 StoreNonPointer(&untag()->target_next_field_offset_in_words_, target_value);
1224#else
1225 // Could be different only during cross-compilation.
1226 ASSERT_EQUAL(host_value, target_value);
1227#endif // defined(DART_PRECOMPILER)
1228 }
1229
1230 static bool is_valid_id(intptr_t value) {
1232 }
1233 intptr_t id() const { return untag()->id_; }
1234 void set_id(intptr_t value) const {
1236 StoreNonPointer(&untag()->id_, value);
1237 }
1238 static intptr_t id_offset() { return OFFSET_OF(UntaggedClass, id_); }
1239
1240#if !defined(DART_PRECOMPILED_RUNTIME)
1241 // If the interface of this class has a single concrete implementation, either
1242 // via `extends` or by `implements`, returns its CID.
1243 // If it has no implementation, returns kIllegalCid.
1244 // If it has more than one implementation, returns kDynamicCid.
1245 intptr_t implementor_cid() const { return untag()->implementor_cid_; }
1246
1247 // Returns true if the implementor tracking state changes and so must be
1248 // propagated to this class's superclass and interfaces.
1249 bool NoteImplementor(const Class& implementor) const;
1250#endif
1251
1252 static intptr_t num_type_arguments_offset() {
1253 return OFFSET_OF(UntaggedClass, num_type_arguments_);
1254 }
1255
1256 StringPtr Name() const;
1257 StringPtr ScrubbedName() const;
1258 const char* ScrubbedNameCString() const;
1259 StringPtr UserVisibleName() const;
1260 const char* UserVisibleNameCString() const;
1261
1262 const char* NameCString(NameVisibility name_visibility) const;
1263
1264 // The mixin for this class if one exists. Otherwise, returns a raw pointer
1265 // to this class.
1266 ClassPtr Mixin() const;
1267
1268 bool IsInFullSnapshot() const;
1269
1270 virtual StringPtr DictionaryName() const { return Name(); }
1271
1272 ScriptPtr script() const { return untag()->script(); }
1273 void set_script(const Script& value) const;
1274
1275#if !defined(DART_PRECOMPILED_RUNTIME)
1276 KernelProgramInfoPtr KernelProgramInfo() const;
1277#endif
1278
1280#if defined(DART_PRECOMPILED_RUNTIME)
1281 return TokenPosition::kNoSource;
1282#else
1283 return untag()->token_pos_;
1284#endif // defined(DART_PRECOMPILED_RUNTIME)
1285 }
1286
1287#if !defined(DART_PRECOMPILED_RUNTIME)
1288 void set_token_pos(TokenPosition value) const;
1289#endif // !defined(DART_PRECOMPILED_RUNTIME)
1290
1292#if defined(DART_PRECOMPILED_RUNTIME)
1293 return TokenPosition::kNoSource;
1294#else
1295 return untag()->end_token_pos_;
1296#endif // defined(DART_PRECOMPILED_RUNTIME)
1297 }
1298
1299#if !defined(DART_PRECOMPILED_RUNTIME)
1301#endif // !defined(DART_PRECOMPILED_RUNTIME)
1302
1303 uint32_t Hash() const;
1304 static uint32_t Hash(ClassPtr);
1305
1306 int32_t SourceFingerprint() const;
1307
1308 // Return the Type with type arguments instantiated to bounds.
1309 TypePtr RareType() const;
1310
1311 // Return the non-nullable Type whose arguments are the type parameters
1312 // declared by this class.
1313 TypePtr DeclarationType() const;
1314
1315 static intptr_t declaration_type_offset() {
1316 return OFFSET_OF(UntaggedClass, declaration_type_);
1317 }
1318
1319 // Returns flattened instance type arguments vector for
1320 // instance of this class, parameterized with declared
1321 // type parameters of this class.
1322 TypeArgumentsPtr GetDeclarationInstanceTypeArguments() const;
1323
1324 // Returns flattened instance type arguments vector for
1325 // instance of this type, parameterized with given type arguments.
1326 //
1327 // Length of [type_arguments] should match number of type parameters
1328 // returned by [NumTypeParameters].
1329 TypeArgumentsPtr GetInstanceTypeArguments(Thread* thread,
1330 const TypeArguments& type_arguments,
1331 bool canonicalize = true) const;
1332
1333 LibraryPtr library() const { return untag()->library(); }
1334 void set_library(const Library& value) const;
1335
1336 // The formal type parameters and their bounds (no defaults), are specified as
1337 // an object of type TypeParameters.
1338 TypeParametersPtr type_parameters() const {
1340 return untag()->type_parameters();
1341 }
1342 void set_type_parameters(const TypeParameters& value) const;
1343 intptr_t NumTypeParameters(Thread* thread) const;
1344 intptr_t NumTypeParameters() const {
1346 }
1347
1348 // Return the type parameter declared at index.
1349 TypeParameterPtr TypeParameterAt(
1350 intptr_t index,
1351 Nullability nullability = Nullability::kNonNullable) const;
1352
1353 // Length of the flattened instance type arguments vector.
1354 // Includes type arguments of the super class.
1355 intptr_t NumTypeArguments() const;
1356
1357 // Return true if this class declares type parameters.
1358 bool IsGeneric() const {
1359 // If the declaration is not loaded, fall back onto NumTypeParameters.
1360 if (!is_declaration_loaded()) {
1361 return NumTypeParameters(Thread::Current()) > 0;
1362 }
1363 return type_parameters() != Object::null();
1364 }
1365
1366 // Returns a canonicalized vector of the type parameters instantiated
1367 // to bounds (e.g., the type arguments used if no TAV is provided for class
1368 // instantiation).
1369 //
1370 // If non-generic, the empty type arguments vector is returned.
1371 TypeArgumentsPtr DefaultTypeArguments(Zone* zone) const;
1372
1373 // If this class is parameterized, each instance has a type_arguments field.
1374 static constexpr intptr_t kNoTypeArguments = -1;
1377 if (untag()->host_type_arguments_field_offset_in_words_ ==
1379 return kNoTypeArguments;
1380 }
1381 return untag()->host_type_arguments_field_offset_in_words_ *
1383 }
1385#if defined(DART_PRECOMPILER)
1387 if (untag()->target_type_arguments_field_offset_in_words_ ==
1390 }
1391 return untag()->target_type_arguments_field_offset_in_words_ *
1393#else
1395#endif // defined(DART_PRECOMPILER)
1396 }
1397 void set_type_arguments_field_offset(intptr_t host_value_in_bytes,
1398 intptr_t target_value_in_bytes) const {
1399 intptr_t host_value, target_value;
1400 if (host_value_in_bytes == kNoTypeArguments ||
1401 target_value_in_bytes == RTN::Class::kNoTypeArguments) {
1402 ASSERT(host_value_in_bytes == kNoTypeArguments &&
1403 target_value_in_bytes == RTN::Class::kNoTypeArguments);
1404 host_value = kNoTypeArguments;
1405 target_value = RTN::Class::kNoTypeArguments;
1406 } else {
1408 host_value = host_value_in_bytes / kCompressedWordSize;
1409 target_value =
1410 target_value_in_bytes / compiler::target::kCompressedWordSize;
1411 }
1412 set_type_arguments_field_offset_in_words(host_value, target_value);
1413 }
1415 intptr_t target_value) const {
1416 StoreNonPointer(&untag()->host_type_arguments_field_offset_in_words_,
1417 host_value);
1418#if defined(DART_PRECOMPILER)
1419 StoreNonPointer(&untag()->target_type_arguments_field_offset_in_words_,
1420 target_value);
1421#else
1422 // Could be different only during cross-compilation.
1423 ASSERT_EQUAL(host_value, target_value);
1424#endif // defined(DART_PRECOMPILER)
1425 }
1427 return OFFSET_OF(UntaggedClass, host_type_arguments_field_offset_in_words_);
1428 }
1429
1430 // The super type of this class, Object type if not explicitly specified.
1431 TypePtr super_type() const {
1433 return untag()->super_type();
1434 }
1435 void set_super_type(const Type& value) const;
1436 static intptr_t super_type_offset() {
1437 return OFFSET_OF(UntaggedClass, super_type_);
1438 }
1439
1440 // Asserts that the class of the super type has been resolved.
1441 // If |class_table| is provided it will be used to resolve class id to the
1442 // actual class object, instead of using current class table on the isolate
1443 // group.
1444 ClassPtr SuperClass(ClassTable* class_table = nullptr) const;
1445
1446 // Interfaces is an array of Types.
1447 ArrayPtr interfaces() const {
1449 return untag()->interfaces();
1450 }
1451 void set_interfaces(const Array& value) const;
1452
1453 // Returns whether a path from [this] to [cls] can be found, where the first
1454 // element is a direct supertype of [this], each following element is a direct
1455 // supertype of the previous element and the final element has [cls] as its
1456 // type class. If [this] and [cls] are the same class, then the path is empty.
1457 //
1458 // If [path] is not nullptr, then the elements of the path are added to it.
1459 // This path can then be used to compute type arguments of [cls] given type
1460 // arguments for an instance of [this].
1461 //
1462 // Note: There may be multiple paths to [cls], but the result of applying each
1463 // path must be equal to the other results.
1464 bool FindInstantiationOf(Zone* zone,
1465 const Class& cls,
1467 bool consider_only_super_classes = false) const;
1469 const Class& cls,
1470 bool consider_only_super_classes = false) const {
1471 return FindInstantiationOf(zone, cls, /*path=*/nullptr,
1472 consider_only_super_classes);
1473 }
1474
1475 // Returns whether a path from [this] to [type] can be found, where the first
1476 // element is a direct supertype of [this], each following element is a direct
1477 // supertype of the previous element and the final element has the same type
1478 // class as [type]. If [this] is the type class of [type], then the path is
1479 // empty.
1480 //
1481 // If [path] is not nullptr, then the elements of the path are added to it.
1482 // This path can then be used to compute type arguments of [type]'s type
1483 // class given type arguments for an instance of [this].
1484 //
1485 // Note: There may be multiple paths to [type]'s type class, but the result of
1486 // applying each path must be equal to the other results.
1487 bool FindInstantiationOf(Zone* zone,
1488 const Type& type,
1490 bool consider_only_super_classes = false) const;
1492 const Type& type,
1493 bool consider_only_super_classes = false) const {
1494 return FindInstantiationOf(zone, type, /*path=*/nullptr,
1495 consider_only_super_classes);
1496 }
1497
1498 // If [this] is a subtype of a type with type class [cls], then this
1499 // returns [cls]<X_0, ..., X_n>, where n is the number of type arguments for
1500 // [cls] and where each type argument X_k is either instantiated or has free
1501 // class type parameters corresponding to the type parameters of [this].
1502 // Thus, given an instance of [this], the result can be instantiated
1503 // with the instance type arguments to get the type of the instance.
1504 //
1505 // If [this] is not a subtype of a type with type class [cls], returns null.
1506 TypePtr GetInstantiationOf(Zone* zone, const Class& cls) const;
1507
1508 // If [this] is a subtype of [type], then this returns [cls]<X_0, ..., X_n>,
1509 // where [cls] is the type class of [type], n is the number of type arguments
1510 // for [cls], and where each type argument X_k is either instantiated or has
1511 // free class type parameters corresponding to the type parameters of [this].
1512 // Thus, given an instance of [this], the result can be instantiated with the
1513 // instance type arguments to get the type of the instance.
1514 //
1515 // If [this] is not a subtype of a type with type class [cls], returns null.
1516 TypePtr GetInstantiationOf(Zone* zone, const Type& type) const;
1517
1518#if !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
1519 // Returns the list of classes directly implementing this class.
1520 GrowableObjectArrayPtr direct_implementors() const {
1522 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
1523 return untag()->direct_implementors();
1524 }
1525 GrowableObjectArrayPtr direct_implementors_unsafe() const {
1526 return untag()->direct_implementors();
1527 }
1528#endif // !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
1529
1530#if !defined(DART_PRECOMPILED_RUNTIME)
1531 void set_direct_implementors(const GrowableObjectArray& implementors) const;
1532 void AddDirectImplementor(const Class& subclass, bool is_mixin) const;
1533#endif // !defined(DART_PRECOMPILED_RUNTIME)
1534
1535#if !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
1536 // Returns the list of classes having this class as direct superclass.
1537 GrowableObjectArrayPtr direct_subclasses() const {
1539 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
1540 return direct_subclasses_unsafe();
1541 }
1542 GrowableObjectArrayPtr direct_subclasses_unsafe() const {
1543 return untag()->direct_subclasses();
1544 }
1545#endif // !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
1546
1547#if !defined(DART_PRECOMPILED_RUNTIME)
1548 void set_direct_subclasses(const GrowableObjectArray& subclasses) const;
1549 void AddDirectSubclass(const Class& subclass) const;
1550#endif // !defined(DART_PRECOMPILED_RUNTIME)
1551
1552 // Check if this class represents the class of null.
1553 bool IsNullClass() const { return id() == kNullCid; }
1554
1555 // Check if this class represents the 'dynamic' class.
1556 bool IsDynamicClass() const { return id() == kDynamicCid; }
1557
1558 // Check if this class represents the 'void' class.
1559 bool IsVoidClass() const { return id() == kVoidCid; }
1560
1561 // Check if this class represents the 'Never' class.
1562 bool IsNeverClass() const { return id() == kNeverCid; }
1563
1564 // Check if this class represents the 'Object' class.
1565 bool IsObjectClass() const { return id() == kInstanceCid; }
1566
1567 // Check if this class represents the 'Function' class.
1568 bool IsDartFunctionClass() const;
1569
1570 // Check if this class represents the 'Future' class.
1571 bool IsFutureClass() const;
1572
1573 // Check if this class represents the 'FutureOr' class.
1574 bool IsFutureOrClass() const { return id() == kFutureOrCid; }
1575
1576 // Check if this class represents the 'Closure' class.
1577 bool IsClosureClass() const { return id() == kClosureCid; }
1578 static bool IsClosureClass(ClassPtr cls) {
1579 return GetClassId(cls) == kClosureCid;
1580 }
1581
1582 // Check if this class represents the 'Record' class.
1583 bool IsRecordClass() const { return id() == kRecordCid; }
1584
1585 static bool IsInFullSnapshot(ClassPtr cls) {
1586 NoSafepointScope no_safepoint;
1588 cls->untag()->library()->untag()->flags_);
1589 }
1590
1591 static intptr_t GetClassId(ClassPtr cls) {
1592 NoSafepointScope no_safepoint;
1593 return cls->untag()->id_;
1594 }
1595
1596 // Returns true if the type specified by cls, type_arguments, and nullability
1597 // is a subtype of the other type.
1598 static bool IsSubtypeOf(
1599 const Class& cls,
1600 const TypeArguments& type_arguments,
1601 Nullability nullability,
1602 const AbstractType& other,
1603 Heap::Space space,
1604 FunctionTypeMapping* function_type_equivalence = nullptr);
1605
1606 // Check if this is the top level class.
1607 bool IsTopLevel() const;
1608
1609 bool IsPrivate() const;
1610
1612 ErrorPtr VerifyEntryPoint() const;
1613
1614 // Returns an array of instance and static fields defined by this class.
1615 ArrayPtr fields() const {
1616 // We rely on the fact that any loads from the array are dependent loads
1617 // and avoid the load-acquire barrier here.
1618 return untag()->fields();
1619 }
1620 void SetFields(const Array& value) const;
1621 void AddField(const Field& field) const;
1622 void AddFields(const GrowableArray<const Field*>& fields) const;
1623
1624 intptr_t FindFieldIndex(const Field& needle) const;
1625 FieldPtr FieldFromIndex(intptr_t idx) const;
1626
1627 // If this is a dart:internal.ClassID class, then inject our own const
1628 // fields. Returns true if synthetic fields are injected and regular
1629 // field declarations should be ignored.
1630 bool InjectCIDFields() const;
1631
1632 // Returns an array of all instance fields of this class and its superclasses
1633 // indexed by offset in words.
1634 // If |class_table| is provided it will be used to resolve super classes by
1635 // class id, instead of the current class_table stored in the isolate.
1636 ArrayPtr OffsetToFieldMap(ClassTable* class_table = nullptr) const;
1637
1638 // Returns true if non-static fields are defined.
1639 bool HasInstanceFields() const;
1640
1641 ArrayPtr current_functions() const {
1642 // We rely on the fact that any loads from the array are dependent loads
1643 // and avoid the load-acquire barrier here.
1644 return untag()->functions();
1645 }
1646 ArrayPtr functions() const {
1648 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
1649 return current_functions();
1650 }
1651 void SetFunctions(const Array& value) const;
1652 void AddFunction(const Function& function) const;
1653 intptr_t FindFunctionIndex(const Function& needle) const;
1654 FunctionPtr FunctionFromIndex(intptr_t idx) const;
1655 intptr_t FindImplicitClosureFunctionIndex(const Function& needle) const;
1656 FunctionPtr ImplicitClosureFunctionFromIndex(intptr_t idx) const;
1657
1658 FunctionPtr LookupFunctionReadLocked(const String& name) const;
1659 FunctionPtr LookupDynamicFunctionUnsafe(const String& name) const;
1660
1661 FunctionPtr LookupDynamicFunctionAllowPrivate(const String& name) const;
1662 FunctionPtr LookupStaticFunction(const String& name) const;
1663 FunctionPtr LookupStaticFunctionAllowPrivate(const String& name) const;
1664 FunctionPtr LookupConstructor(const String& name) const;
1665 FunctionPtr LookupConstructorAllowPrivate(const String& name) const;
1666 FunctionPtr LookupFactory(const String& name) const;
1667 FunctionPtr LookupFactoryAllowPrivate(const String& name) const;
1668 FunctionPtr LookupFunctionAllowPrivate(const String& name) const;
1669 FunctionPtr LookupGetterFunction(const String& name) const;
1670 FunctionPtr LookupSetterFunction(const String& name) const;
1671 FieldPtr LookupInstanceField(const String& name) const;
1672 FieldPtr LookupStaticField(const String& name) const;
1673 FieldPtr LookupField(const String& name) const;
1674 FieldPtr LookupFieldAllowPrivate(const String& name,
1675 bool instance_only = false) const;
1676 FieldPtr LookupInstanceFieldAllowPrivate(const String& name) const;
1677 FieldPtr LookupStaticFieldAllowPrivate(const String& name) const;
1678
1679 // The methods above are more efficient than this generic one.
1680 InstancePtr LookupCanonicalInstance(Zone* zone, const Instance& value) const;
1681
1682 InstancePtr InsertCanonicalConstant(Zone* zone,
1683 const Instance& constant) const;
1684
1685 static intptr_t InstanceSize() {
1686 return RoundedAllocationSize(sizeof(UntaggedClass));
1687 }
1688
1689 // Returns true if any class implements this interface via `implements`.
1690 // Returns false if all possible implementations of this interface must be
1691 // instances of this class or its subclasses.
1692 bool is_implemented() const { return ImplementedBit::decode(state_bits()); }
1693 void set_is_implemented() const;
1694 void set_is_implemented_unsafe() const;
1695
1696 bool is_abstract() const { return AbstractBit::decode(state_bits()); }
1697 void set_is_abstract() const;
1698
1700 return ClassLoadingBits::decode(state_bits());
1701 }
1702
1705 }
1706 void set_is_declaration_loaded() const;
1708
1709 bool is_type_finalized() const {
1711 }
1712 void set_is_type_finalized() const;
1713
1715 return SynthesizedClassBit::decode(state_bits());
1716 }
1717 void set_is_synthesized_class() const;
1719
1720 bool is_enum_class() const { return EnumBit::decode(state_bits()); }
1721 void set_is_enum_class() const;
1722
1723 bool is_finalized() const {
1724 return ClassFinalizedBits::decode(state_bits()) ==
1726 ClassFinalizedBits::decode(state_bits()) ==
1728 }
1729 void set_is_finalized() const;
1730 void set_is_finalized_unsafe() const;
1731
1733 return ClassFinalizedBits::decode(state_bits()) ==
1735 }
1736 void set_is_allocate_finalized() const;
1737
1738 bool is_prefinalized() const {
1739 return ClassFinalizedBits::decode(state_bits()) ==
1741 }
1742
1743 void set_is_prefinalized() const;
1744
1745 bool is_const() const { return ConstBit::decode(state_bits()); }
1746 void set_is_const() const;
1747
1748 // Tests if this is a mixin application class which was desugared
1749 // to a normal class by kernel mixin transformation
1750 // (pkg/kernel/lib/transformations/mixin_full_resolution.dart).
1751 //
1752 // In such case, its mixed-in type was pulled into the end of
1753 // interfaces list.
1755 return TransformedMixinApplicationBit::decode(state_bits());
1756 }
1758
1759 bool is_sealed() const { return SealedBit::decode(state_bits()); }
1760 void set_is_sealed() const;
1761
1762 bool is_mixin_class() const { return MixinClassBit::decode(state_bits()); }
1763 void set_is_mixin_class() const;
1764
1765 bool is_base_class() const { return BaseClassBit::decode(state_bits()); }
1766 void set_is_base_class() const;
1767
1768 bool is_interface_class() const {
1769 return InterfaceClassBit::decode(state_bits());
1770 }
1771 void set_is_interface_class() const;
1772
1773 bool is_final() const { return FinalBit::decode(state_bits()); }
1774 void set_is_final() const;
1775
1777 return FieldsMarkedNullableBit::decode(state_bits());
1778 }
1779 void set_is_fields_marked_nullable() const;
1780
1781 bool is_allocated() const { return IsAllocatedBit::decode(state_bits()); }
1782 void set_is_allocated(bool value) const;
1783 void set_is_allocated_unsafe(bool value) const;
1784
1785 bool is_loaded() const { return IsLoadedBit::decode(state_bits()); }
1786 void set_is_loaded(bool value) const;
1787
1788 uint16_t num_native_fields() const { return untag()->num_native_fields_; }
1789 void set_num_native_fields(uint16_t value) const {
1790 StoreNonPointer(&untag()->num_native_fields_, value);
1791 }
1792 static uint16_t NumNativeFieldsOf(ClassPtr clazz) {
1793 return clazz->untag()->num_native_fields_;
1794 }
1795 static bool IsIsolateUnsendable(ClassPtr clazz) {
1796 return IsIsolateUnsendableBit::decode(clazz->untag()->state_bits_);
1797 }
1798
1799#if !defined(DART_PRECOMPILED_RUNTIME)
1800 CodePtr allocation_stub() const { return untag()->allocation_stub(); }
1801 void set_allocation_stub(const Code& value) const;
1802#endif // !defined(DART_PRECOMPILED_RUNTIME)
1803
1804 intptr_t kernel_offset() const {
1805#if defined(DART_PRECOMPILED_RUNTIME)
1806 return 0;
1807#else
1808 return untag()->kernel_offset_;
1809#endif
1810 }
1811
1812 void set_kernel_offset(intptr_t value) const {
1813#if defined(DART_PRECOMPILED_RUNTIME)
1814 UNREACHABLE();
1815#else
1816 ASSERT(value >= 0);
1817 StoreNonPointer(&untag()->kernel_offset_, value);
1818#endif
1819 }
1820
1821 void DisableAllocationStub() const;
1822
1823 ArrayPtr constants() const;
1824 void set_constants(const Array& value) const;
1825
1826 intptr_t FindInvocationDispatcherFunctionIndex(const Function& needle) const;
1827 FunctionPtr InvocationDispatcherFunctionFromIndex(intptr_t idx) const;
1828
1829 FunctionPtr GetInvocationDispatcher(const String& target_name,
1830 const Array& args_desc,
1832 bool create_if_absent) const;
1833
1834 FunctionPtr GetRecordFieldGetter(const String& getter_name) const;
1835
1836 void Finalize() const;
1837
1838 ObjectPtr Invoke(const String& selector,
1839 const Array& arguments,
1840 const Array& argument_names,
1841 bool respect_reflectable = true,
1842 bool check_is_entrypoint = false) const;
1843 ObjectPtr InvokeGetter(const String& selector,
1844 bool throw_nsm_if_absent,
1845 bool respect_reflectable = true,
1846 bool check_is_entrypoint = false) const;
1847 ObjectPtr InvokeSetter(const String& selector,
1848 const Instance& argument,
1849 bool respect_reflectable = true,
1850 bool check_is_entrypoint = false) const;
1851
1852 // Evaluate the given expression as if it appeared in a static method of this
1853 // class and return the resulting value, or an error object if evaluating the
1854 // expression fails. The method has the formal (type) parameters given in
1855 // (type_)param_names, and is invoked with the (type)argument values given in
1856 // (type_)param_values.
1858 const ExternalTypedData& kernel_buffer,
1859 const Array& type_definitions,
1860 const Array& param_values,
1861 const TypeArguments& type_param_values) const;
1862
1863 // Load class declaration (super type, interfaces, type parameters and
1864 // number of type arguments) if it is not loaded yet.
1865 void EnsureDeclarationLoaded() const;
1866
1867 ErrorPtr EnsureIsFinalized(Thread* thread) const;
1868 ErrorPtr EnsureIsAllocateFinalized(Thread* thread) const;
1869
1870 // Allocate a class used for VM internal objects.
1871 template <class FakeObject, class TargetFakeObject>
1872 static ClassPtr New(IsolateGroup* isolate_group, bool register_class = true);
1873
1874 // Allocate instance classes.
1875 static ClassPtr New(const Library& lib,
1876 const String& name,
1877 const Script& script,
1879 bool register_class = true);
1880 static ClassPtr NewNativeWrapper(const Library& library,
1881 const String& name,
1882 int num_fields);
1883
1884 // Allocate the raw string classes.
1885 static ClassPtr NewStringClass(intptr_t class_id,
1886 IsolateGroup* isolate_group);
1887
1888 // Allocate the raw TypedData classes.
1889 static ClassPtr NewTypedDataClass(intptr_t class_id,
1890 IsolateGroup* isolate_group);
1891
1892 // Allocate the raw TypedDataView/ByteDataView classes.
1893 static ClassPtr NewTypedDataViewClass(intptr_t class_id,
1894 IsolateGroup* isolate_group);
1895 static ClassPtr NewUnmodifiableTypedDataViewClass(
1896 intptr_t class_id,
1897 IsolateGroup* isolate_group);
1898
1899 // Allocate the raw ExternalTypedData classes.
1900 static ClassPtr NewExternalTypedDataClass(intptr_t class_id,
1901 IsolateGroup* isolate);
1902
1903 // Allocate the raw Pointer classes.
1904 static ClassPtr NewPointerClass(intptr_t class_id,
1905 IsolateGroup* isolate_group);
1906
1907#if !defined(DART_PRECOMPILED_RUNTIME)
1908 // Register code that has used CHA for optimization.
1909 // TODO(srdjan): Also register kind of CHA optimization (e.g.: leaf class,
1910 // leaf method, ...).
1911 void RegisterCHACode(const Code& code);
1912
1913 void DisableCHAOptimizedCode(const Class& subclass);
1914
1916
1918
1919 // Return the list of code objects that were compiled using CHA of this class.
1920 // These code objects will be invalidated if new subclasses of this class
1921 // are finalized.
1922 WeakArrayPtr dependent_code() const;
1923 void set_dependent_code(const WeakArray& array) const;
1924#endif // !defined(DART_PRECOMPILED_RUNTIME)
1925
1926 bool TraceAllocation(IsolateGroup* isolate_group) const;
1927 void SetTraceAllocation(bool trace_allocation) const;
1928
1929 void CopyStaticFieldValues(ProgramReloadContext* reload_context,
1930 const Class& old_cls) const;
1931 void PatchFieldsAndFunctions() const;
1933 const Class& new_cls) const;
1934 void CopyCanonicalConstants(const Class& old_cls) const;
1935 void CopyDeclarationType(const Class& old_cls) const;
1936 void CheckReload(const Class& replacement,
1937 ProgramReloadContext* context) const;
1938
1939 void AddInvocationDispatcher(const String& target_name,
1940 const Array& args_desc,
1941 const Function& dispatcher) const;
1942
1943 static int32_t host_instance_size_in_words(const ClassPtr cls) {
1944 return cls->untag()->host_instance_size_in_words_;
1945 }
1946
1947 static int32_t target_instance_size_in_words(const ClassPtr cls) {
1948#if defined(DART_PRECOMPILER)
1949 return cls->untag()->target_instance_size_in_words_;
1950#else
1951 return host_instance_size_in_words(cls);
1952#endif // defined(DART_PRECOMPILER)
1953 }
1954
1955 static int32_t host_next_field_offset_in_words(const ClassPtr cls) {
1956 return cls->untag()->host_next_field_offset_in_words_;
1957 }
1958
1959 static int32_t target_next_field_offset_in_words(const ClassPtr cls) {
1960#if defined(DART_PRECOMPILER)
1961 return cls->untag()->target_next_field_offset_in_words_;
1962#else
1964#endif // defined(DART_PRECOMPILER)
1965 }
1966
1967 static int32_t host_type_arguments_field_offset_in_words(const ClassPtr cls) {
1968 return cls->untag()->host_type_arguments_field_offset_in_words_;
1969 }
1970
1972 const ClassPtr cls) {
1973#if defined(DART_PRECOMPILER)
1974 return cls->untag()->target_type_arguments_field_offset_in_words_;
1975#else
1977#endif // defined(DART_PRECOMPILER)
1978 }
1979
1980 static intptr_t UnboxedFieldSizeInBytesByCid(intptr_t cid);
1981 void MarkFieldBoxedDuringReload(ClassTable* class_table,
1982 const Field& field) const;
1983
1984#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
1986#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
1987
1988 private:
1989 TypePtr declaration_type() const {
1990 return untag()->declaration_type<std::memory_order_acquire>();
1991 }
1992
1993 // Caches the declaration type of this class.
1994 void set_declaration_type(const Type& type) const;
1995
1996 TypeArgumentsPtr declaration_instance_type_arguments() const {
1997 return untag()
1998 ->declaration_instance_type_arguments<std::memory_order_acquire>();
1999 }
2000 void set_declaration_instance_type_arguments(
2001 const TypeArguments& value) const;
2002
2003 bool CanReloadFinalized(const Class& replacement,
2004 ProgramReloadContext* context) const;
2005 bool CanReloadPreFinalized(const Class& replacement,
2006 ProgramReloadContext* context) const;
2007
2008 // Tells whether instances need morphing for reload.
2009 bool RequiresInstanceMorphing(ClassTable* class_table,
2010 const Class& replacement) const;
2011
2012 template <class FakeInstance, class TargetFakeInstance>
2013 static ClassPtr NewCommon(intptr_t index);
2014
2015 enum MemberKind {
2016 kAny = 0,
2017 kStatic,
2018 kInstance,
2019 kInstanceAllowAbstract,
2020 kConstructor,
2021 kFactory,
2022 };
2023 enum StateBits {
2024 kConstBit = 0,
2025 kImplementedBit = 1,
2026 kClassFinalizedPos = 2,
2027 kClassFinalizedSize = 2,
2028 kClassLoadingPos = kClassFinalizedPos + kClassFinalizedSize, // = 4
2029 kClassLoadingSize = 2,
2030 kAbstractBit = kClassLoadingPos + kClassLoadingSize, // = 6
2031 kSynthesizedClassBit,
2032 kMixinAppAliasBit,
2033 kMixinTypeAppliedBit,
2034 kFieldsMarkedNullableBit,
2035 kEnumBit,
2036 kTransformedMixinApplicationBit,
2037 kIsAllocatedBit,
2038 kIsLoadedBit,
2039 kHasPragmaBit,
2040 kSealedBit,
2041 kMixinClassBit,
2042 kBaseClassBit,
2043 kInterfaceClassBit,
2044 kFinalBit,
2045 // Whether instances of the class cannot be sent across ports.
2046 //
2047 // Will be true iff
2048 // - class is marked with `@pragma('vm:isolate-unsendable')
2049 // - super class / super interface classes are marked as unsendable.
2050 // - class has native fields.
2051 kIsIsolateUnsendableBit,
2052 // True if this class has `@pragma('vm:isolate-unsendable')` annotation or
2053 // base class or implemented interfaces has this bit.
2054 kIsIsolateUnsendableDueToPragmaBit,
2055 // Will be set to 1 for the following classes:
2056 //
2057 // 1. Deeply immutable class.
2058 // a. Statically guaranteed deeply immutable classes.
2059 // `@pragma('vm:deeply-immutable')`.
2060 // b. VM recognized deeply immutable classes.
2061 // `IsDeeplyImmutableCid(intptr_t predefined_cid)`.
2062 //
2063 // See also ImmutableBit in raw_object.h.
2064 kIsDeeplyImmutableBit,
2065 // This class is a subtype of Future.
2066 kIsFutureSubtypeBit,
2067 // This class has a non-abstract subtype which is a subtype of Future.
2068 // It means that variable of static type based on this class may hold
2069 // a Future instance.
2070 kCanBeFutureBit,
2071 // This class can be extended, implemented or mixed-in by
2072 // a dynamically loaded class.
2073 kIsDynamicallyExtendableBit,
2074 // This class has a dynamically extendable subtype.
2075 kHasDynamicallyExtendableSubtypesBit,
2076 };
2077 class ConstBit : public BitField<uint32_t, bool, kConstBit, 1> {};
2078 class ImplementedBit : public BitField<uint32_t, bool, kImplementedBit, 1> {};
2079 class ClassFinalizedBits : public BitField<uint32_t,
2080 UntaggedClass::ClassFinalizedState,
2081 kClassFinalizedPos,
2082 kClassFinalizedSize> {};
2083 class ClassLoadingBits : public BitField<uint32_t,
2084 UntaggedClass::ClassLoadingState,
2085 kClassLoadingPos,
2086 kClassLoadingSize> {};
2087 class AbstractBit : public BitField<uint32_t, bool, kAbstractBit, 1> {};
2088 class SynthesizedClassBit
2089 : public BitField<uint32_t, bool, kSynthesizedClassBit, 1> {};
2090 class FieldsMarkedNullableBit
2091 : public BitField<uint32_t, bool, kFieldsMarkedNullableBit, 1> {};
2092 class EnumBit : public BitField<uint32_t, bool, kEnumBit, 1> {};
2093 class TransformedMixinApplicationBit
2094 : public BitField<uint32_t, bool, kTransformedMixinApplicationBit, 1> {};
2095 class IsAllocatedBit : public BitField<uint32_t, bool, kIsAllocatedBit, 1> {};
2096 class IsLoadedBit : public BitField<uint32_t, bool, kIsLoadedBit, 1> {};
2097 class HasPragmaBit : public BitField<uint32_t, bool, kHasPragmaBit, 1> {};
2098 class SealedBit : public BitField<uint32_t, bool, kSealedBit, 1> {};
2099 class MixinClassBit : public BitField<uint32_t, bool, kMixinClassBit, 1> {};
2100 class BaseClassBit : public BitField<uint32_t, bool, kBaseClassBit, 1> {};
2101 class InterfaceClassBit
2102 : public BitField<uint32_t, bool, kInterfaceClassBit, 1> {};
2103 class FinalBit : public BitField<uint32_t, bool, kFinalBit, 1> {};
2104 class IsIsolateUnsendableBit
2105 : public BitField<uint32_t, bool, kIsIsolateUnsendableBit, 1> {};
2106 class IsIsolateUnsendableDueToPragmaBit
2107 : public BitField<uint32_t, bool, kIsIsolateUnsendableDueToPragmaBit, 1> {
2108 };
2109 class IsDeeplyImmutableBit
2110 : public BitField<uint32_t, bool, kIsDeeplyImmutableBit, 1> {};
2111 class IsFutureSubtypeBit
2112 : public BitField<uint32_t, bool, kIsFutureSubtypeBit, 1> {};
2113 class CanBeFutureBit : public BitField<uint32_t, bool, kCanBeFutureBit, 1> {};
2114 class IsDynamicallyExtendableBit
2115 : public BitField<uint32_t, bool, kIsDynamicallyExtendableBit, 1> {};
2116 class HasDynamicallyExtendableSubtypesBit
2117 : public BitField<uint32_t,
2118 bool,
2119 kHasDynamicallyExtendableSubtypesBit,
2120 1> {};
2121
2122 void set_name(const String& value) const;
2123 void set_user_name(const String& value) const;
2124 const char* GenerateUserVisibleName() const;
2125 void set_state_bits(intptr_t bits) const;
2126 void set_implementor_cid(intptr_t value) const;
2127
2128 FunctionPtr CreateInvocationDispatcher(const String& target_name,
2129 const Array& args_desc,
2130 UntaggedFunction::Kind kind) const;
2131
2132 FunctionPtr CreateRecordFieldGetter(const String& getter_name) const;
2133
2134 // Returns the bitmap of unboxed fields
2135 UnboxedFieldBitmap CalculateFieldOffsets() const;
2136
2137 // functions_hash_table is in use iff there are at least this many functions.
2138 static constexpr intptr_t kFunctionLookupHashThreshold = 16;
2139
2140 // Initial value for the cached number of type arguments.
2141 static constexpr intptr_t kUnknownNumTypeArguments = -1;
2142
2143 int16_t num_type_arguments() const {
2144 return LoadNonPointer<int16_t, std::memory_order_relaxed>(
2145 &untag()->num_type_arguments_);
2146 }
2147
2148 uint32_t state_bits() const {
2149 // Ensure any following load instructions do not get performed before this
2150 // one.
2151 return LoadNonPointer<uint32_t, std::memory_order_acquire>(
2152 &untag()->state_bits_);
2153 }
2154
2155 public:
2156 void set_num_type_arguments(intptr_t value) const;
2157 void set_num_type_arguments_unsafe(intptr_t value) const;
2158
2159 bool has_pragma() const { return HasPragmaBit::decode(state_bits()); }
2160 void set_has_pragma(bool value) const;
2161
2162 void set_is_isolate_unsendable(bool value) const;
2164 ASSERT(is_finalized()); // This bit is initialized in class finalizer.
2165 return IsIsolateUnsendableBit::decode(state_bits());
2166 }
2167
2170 return IsIsolateUnsendableDueToPragmaBit::decode(state_bits());
2171 }
2172
2173 void set_is_deeply_immutable(bool value) const;
2174 bool is_deeply_immutable() const {
2175 return IsDeeplyImmutableBit::decode(state_bits());
2176 }
2177 static bool IsDeeplyImmutable(ClassPtr clazz) {
2178 return IsDeeplyImmutableBit::decode(clazz->untag()->state_bits_);
2179 }
2180
2181 void set_is_future_subtype(bool value) const;
2182 bool is_future_subtype() const {
2184 return IsFutureSubtypeBit::decode(state_bits());
2185 }
2186
2187 void set_can_be_future(bool value) const;
2188 bool can_be_future() const { return CanBeFutureBit::decode(state_bits()); }
2189
2190 void set_is_dynamically_extendable(bool value) const;
2192 return IsDynamicallyExtendableBit::decode(state_bits());
2193 }
2194
2198 }
2199
2200 private:
2201 void set_functions(const Array& value) const;
2202 void set_fields(const Array& value) const;
2203 void set_invocation_dispatcher_cache(const Array& cache) const;
2204
2205 ArrayPtr invocation_dispatcher_cache() const;
2206
2207 // Calculates number of type arguments of this class.
2208 // This includes type arguments of a superclass and takes overlapping
2209 // of type arguments into account.
2210 intptr_t ComputeNumTypeArguments() const;
2211
2212 // Assigns empty array to all raw class array fields.
2213 void InitEmptyFields() const;
2214
2215 static FunctionPtr CheckFunctionType(const Function& func, MemberKind kind);
2216 FunctionPtr LookupFunctionReadLocked(const String& name,
2217 MemberKind kind) const;
2218 FunctionPtr LookupFunctionAllowPrivate(const String& name,
2219 MemberKind kind) const;
2220 FieldPtr LookupField(const String& name, MemberKind kind) const;
2221
2222 FunctionPtr LookupAccessorFunction(const char* prefix,
2223 intptr_t prefix_length,
2224 const String& name) const;
2225
2226 // Allocate an instance class which has a VM implementation.
2227 template <class FakeInstance, class TargetFakeInstance>
2228 static ClassPtr New(intptr_t id,
2229 IsolateGroup* isolate_group,
2230 bool register_class = true,
2231 bool is_abstract = false);
2232
2233 // Helper that calls 'Class::New<Instance>(kIllegalCid)'.
2234 static ClassPtr NewInstanceClass();
2235
2236 FINAL_HEAP_OBJECT_IMPLEMENTATION(Class, Object);
2237 friend class AbstractType;
2238 friend class Instance;
2239 friend class Object;
2240 friend class Type;
2241 friend class Intrinsifier;
2242 friend class ProgramWalker;
2243 friend class Precompiler;
2244 friend class ClassFinalizer;
2245};
2246
2247// Classification of type genericity according to type parameter owners.
2249 kAny, // Consider type params of current class and functions.
2250 kCurrentClass, // Consider type params of current class only.
2251 kFunctions, // Consider type params of current and parent functions.
2252};
2253
2254// Wrapper of a [Class] with different [Script] and kernel binary.
2255//
2256// We use this as owner of [Field]/[Function] objects that were from a different
2257// script/kernel than the actual class object.
2258//
2259// * used for corelib patches that live in different .dart files than the
2260// library itself.
2261//
2262// * used for library parts that live in different .dart files than the library
2263// itself.
2264//
2265// * used in reload to make old [Function]/[Field] objects have the old script
2266// kernel data.
2267//
2268class PatchClass : public Object {
2269 public:
2270 ClassPtr wrapped_class() const { return untag()->wrapped_class(); }
2271 ScriptPtr script() const { return untag()->script(); }
2272
2273 intptr_t kernel_library_index() const {
2274#if !defined(DART_PRECOMPILED_RUNTIME)
2275 return untag()->kernel_library_index_;
2276#else
2277 return -1;
2278#endif
2279 }
2280 void set_kernel_library_index(intptr_t index) const {
2281 NOT_IN_PRECOMPILED(StoreNonPointer(&untag()->kernel_library_index_, index));
2282 }
2283
2284#if !defined(DART_PRECOMPILED_RUNTIME)
2285 KernelProgramInfoPtr kernel_program_info() const {
2286 return untag()->kernel_program_info();
2287 }
2289#endif
2290
2291 static intptr_t InstanceSize() {
2293 }
2294 static bool IsInFullSnapshot(PatchClassPtr cls) {
2295 NoSafepointScope no_safepoint;
2296 return Class::IsInFullSnapshot(cls->untag()->wrapped_class());
2297 }
2298
2299 static PatchClassPtr New(const Class& wrapped_class,
2300 const KernelProgramInfo& info,
2301 const Script& source);
2302
2303 private:
2304 void set_wrapped_class(const Class& value) const;
2305 void set_script(const Script& value) const;
2306
2307 static PatchClassPtr New();
2308
2309 FINAL_HEAP_OBJECT_IMPLEMENTATION(PatchClass, Object);
2310 friend class Class;
2311};
2312
2314 public:
2315 CodePtr target() const { return untag()->target(); }
2316 void set_target(const Code& target) const;
2317 static intptr_t target_offset() {
2318 return OFFSET_OF(UntaggedSingleTargetCache, target_);
2319 }
2320
2321#define DEFINE_NON_POINTER_FIELD_ACCESSORS(type, name) \
2322 type name() const { return untag()->name##_; } \
2323 void set_##name(type value) const { \
2324 StoreNonPointer(&untag()->name##_, value); \
2325 } \
2326 static intptr_t name##_offset() { \
2327 return OFFSET_OF(UntaggedSingleTargetCache, name##_); \
2328 }
2329
2333#undef DEFINE_NON_POINTER_FIELD_ACCESSORS
2334
2335 static intptr_t InstanceSize() {
2337 }
2338
2339 static SingleTargetCachePtr New();
2340
2341 private:
2342 FINAL_HEAP_OBJECT_IMPLEMENTATION(SingleTargetCache, Object);
2343 friend class Class;
2344};
2345
2347 public:
2348 classid_t expected_cid() const { return untag()->expected_cid_; }
2349
2350 static intptr_t InstanceSize() {
2352 }
2353
2354 static MonomorphicSmiableCallPtr New(classid_t expected_cid,
2355 const Code& target);
2356
2357 static intptr_t expected_cid_offset() {
2358 return OFFSET_OF(UntaggedMonomorphicSmiableCall, expected_cid_);
2359 }
2360
2361 static intptr_t entrypoint_offset() {
2362 return OFFSET_OF(UntaggedMonomorphicSmiableCall, entrypoint_);
2363 }
2364
2365 private:
2366 FINAL_HEAP_OBJECT_IMPLEMENTATION(MonomorphicSmiableCall, Object);
2367 friend class Class;
2368};
2369
2370class CallSiteData : public Object {
2371 public:
2372 StringPtr target_name() const { return untag()->target_name(); }
2373 ArrayPtr arguments_descriptor() const { return untag()->args_descriptor(); }
2374
2375 intptr_t TypeArgsLen() const;
2376
2377 intptr_t CountWithTypeArgs() const;
2378
2379 intptr_t CountWithoutTypeArgs() const;
2380
2381 intptr_t SizeWithoutTypeArgs() const;
2382
2383 intptr_t SizeWithTypeArgs() const;
2384
2385 static intptr_t target_name_offset() {
2386 return OFFSET_OF(UntaggedCallSiteData, target_name_);
2387 }
2388
2390 return OFFSET_OF(UntaggedCallSiteData, args_descriptor_);
2391 }
2392
2393 private:
2394 void set_target_name(const String& value) const;
2395 void set_arguments_descriptor(const Array& value) const;
2396
2398
2399 friend class ICData;
2400 friend class MegamorphicCache;
2401};
2402
2404 public:
2406 return untag()->can_patch_to_monomorphic_;
2407 }
2408
2409 static intptr_t InstanceSize() {
2411 }
2412
2413 uword Hash() const;
2414 bool Equals(const UnlinkedCall& other) const;
2415
2416 static UnlinkedCallPtr New();
2417
2418 private:
2419 friend class ICData; // For set_*() methods.
2420
2421 void set_can_patch_to_monomorphic(bool value) const;
2422
2424 friend class Class;
2425};
2426
2427// Object holding information about an IC: test classes and their
2428// corresponding targets. The owner of the ICData can be either the function
2429// or the original ICData object. In case of background compilation we
2430// copy the ICData in a child object, thus freezing it during background
2431// compilation. Code may contain only original ICData objects.
2432//
2433// ICData's backing store is an array that logically contains several valid
2434// entries followed by a sentinel entry.
2435//
2436// [<entry-0>, <...>, <entry-N>, <sentinel>]
2437//
2438// Each entry has the following form:
2439//
2440// [arg0?, arg1?, argN?, count, target-function/code, exactness?]
2441//
2442// The <entry-X> need to contain valid type feedback.
2443// The <sentinel> entry and must have kIllegalCid value for all
2444// members of the entry except for the last one (`exactness` if
2445// present, otherwise `target-function/code`) - which we use as a backref:
2446//
2447// * For empty ICData we use a cached/shared backing store. So there is no
2448// unique backref, we use kIllegalCid instead.
2449// * For non-empty ICData the backref in the backing store array will point to
2450// the ICData object.
2451//
2452// Updating the ICData happens under a lock to avoid phantom-reads. The backing
2453// is treated as an immutable Copy-on-Write data structure: Adding to the ICData
2454// makes a copy with length+1 which will be store-release'd so any reader can
2455// see it (and doesn't need to hold a lock).
2456class ICData : public CallSiteData {
2457 public:
2458 FunctionPtr Owner() const;
2459
2460 ICDataPtr Original() const;
2461
2462 void SetOriginal(const ICData& value) const;
2463
2464 bool IsOriginal() const { return Original() == this->ptr(); }
2465
2466 intptr_t NumArgsTested() const;
2467
2468 intptr_t deopt_id() const {
2469#if defined(DART_PRECOMPILED_RUNTIME)
2470 UNREACHABLE();
2471 return -1;
2472#else
2473 return untag()->deopt_id_;
2474#endif
2475 }
2476
2477 bool IsImmutable() const;
2478
2479#if !defined(DART_PRECOMPILED_RUNTIME)
2480 AbstractTypePtr receivers_static_type() const {
2481 return untag()->receivers_static_type();
2482 }
2484 return untag()->state_bits_.Read<TrackingExactnessBit>();
2485 }
2486#else
2487 bool is_tracking_exactness() const { return false; }
2488#endif
2489
2490// Note: only deopts with reasons before Unknown in this list are recorded in
2491// the ICData. All other reasons are used purely for informational messages
2492// printed during deoptimization itself.
2493#define DEOPT_REASONS(V) \
2494 V(BinarySmiOp) \
2495 V(BinaryInt64Op) \
2496 V(DoubleToSmi) \
2497 V(CheckSmi) \
2498 V(CheckClass) \
2499 V(Unknown) \
2500 V(PolymorphicInstanceCallTestFail) \
2501 V(UnaryInt64Op) \
2502 V(BinaryDoubleOp) \
2503 V(UnaryOp) \
2504 V(UnboxInteger) \
2505 V(Unbox) \
2506 V(CheckArrayBound) \
2507 V(AtCall) \
2508 V(GuardField) \
2509 V(TestCids) \
2510 V(NumReasons)
2511
2513#define DEFINE_ENUM_LIST(name) kDeopt##name,
2515#undef DEFINE_ENUM_LIST
2516 };
2517
2518 static constexpr intptr_t kLastRecordedDeoptReason = kDeoptUnknown - 1;
2519
2521 // Deoptimization is caused by an optimistically hoisted instruction.
2522 kHoisted = 1 << 0,
2523
2524 // Deoptimization is caused by an optimistically generalized bounds check.
2525 kGeneralized = 1 << 1
2527
2528 bool HasDeoptReasons() const { return DeoptReasons() != 0; }
2529 uint32_t DeoptReasons() const;
2530 void SetDeoptReasons(uint32_t reasons) const;
2531
2532 bool HasDeoptReason(ICData::DeoptReasonId reason) const;
2533 void AddDeoptReason(ICData::DeoptReasonId reason) const;
2534
2535 // Call site classification that is helpful for hot-reload. Call sites with
2536 // different `RebindRule` have to be rebound differently.
2537#define FOR_EACH_REBIND_RULE(V) \
2538 V(Instance) \
2539 V(NoRebind) \
2540 V(NSMDispatch) \
2541 V(Optimized) \
2542 V(Static) \
2543 V(Super)
2544
2546#define REBIND_ENUM_DEF(name) k##name,
2548#undef REBIND_ENUM_DEF
2550 };
2551 static const char* RebindRuleToCString(RebindRule r);
2552 static bool ParseRebindRule(const char* str, RebindRule* out);
2553 RebindRule rebind_rule() const;
2554
2555 void set_is_megamorphic(bool value) const {
2556 untag()->state_bits_.UpdateBool<MegamorphicBit, std::memory_order_release>(
2557 value);
2558 }
2559
2560 // The length of the array. This includes all sentinel entries including
2561 // the final one.
2562 intptr_t Length() const;
2563
2564 intptr_t NumberOfChecks() const;
2565
2566 // Discounts any checks with usage of zero.
2567 // Takes O(result)) time!
2568 intptr_t NumberOfUsedChecks() const;
2569
2570 bool NumberOfChecksIs(intptr_t n) const;
2571
2572 bool IsValidEntryIndex(intptr_t index) const {
2573 return 0 <= index && index < NumberOfChecks();
2574 }
2575
2576 static intptr_t InstanceSize() {
2577 return RoundedAllocationSize(sizeof(UntaggedICData));
2578 }
2579
2580 static intptr_t state_bits_offset() {
2581 return OFFSET_OF(UntaggedICData, state_bits_);
2582 }
2583
2584 static intptr_t NumArgsTestedShift() { return kNumArgsTestedPos; }
2585
2586 static intptr_t NumArgsTestedMask() {
2587 return ((1 << kNumArgsTestedSize) - 1) << kNumArgsTestedPos;
2588 }
2589
2590 static intptr_t entries_offset() {
2591 return OFFSET_OF(UntaggedICData, entries_);
2592 }
2593
2594 static intptr_t owner_offset() { return OFFSET_OF(UntaggedICData, owner_); }
2595
2596#if !defined(DART_PRECOMPILED_RUNTIME)
2598 return OFFSET_OF(UntaggedICData, receivers_static_type_);
2599 }
2600#endif
2601
2602 // NOTE: Can only be called during reload.
2603 void Clear(const CallSiteResetter& proof_of_reload) const {
2604 TruncateTo(0, proof_of_reload);
2605 }
2606
2607 // NOTE: Can only be called during reload.
2608 void TruncateTo(intptr_t num_checks,
2609 const CallSiteResetter& proof_of_reload) const;
2610
2611 // Clears the count for entry |index|.
2612 // NOTE: Can only be called during reload.
2613 void ClearCountAt(intptr_t index,
2614 const CallSiteResetter& proof_of_reload) const;
2615
2616 // Clear all entries with the sentinel value and reset the first entry
2617 // with the dummy target entry.
2618 // NOTE: Can only be called during reload.
2619 void ClearAndSetStaticTarget(const Function& func,
2620 const CallSiteResetter& proof_of_reload) const;
2621
2622 void DebugDump() const;
2623
2624 // Adding checks.
2625
2626 // Ensures there is a check for [class_ids].
2627 //
2628 // Calls [AddCheck] iff there is no existing check. Ensures test (and
2629 // potential update) will be performed under exclusive lock to guard against
2630 // multiple threads trying to add the same check.
2631 void EnsureHasCheck(const GrowableArray<intptr_t>& class_ids,
2632 const Function& target,
2633 intptr_t count = 1) const;
2634
2635 // Adds one more class test to ICData. Length of 'classes' must be equal to
2636 // the number of arguments tested. Use only for num_args_tested > 1.
2637 void AddCheck(const GrowableArray<intptr_t>& class_ids,
2638 const Function& target,
2639 intptr_t count = 1) const;
2640
2641 StaticTypeExactnessState GetExactnessAt(intptr_t count) const;
2642
2643 // Ensures there is a receiver check for [receiver_class_id].
2644 //
2645 // Calls [AddCheckReceiverCheck] iff there is no existing check. Ensures
2646 // test (and potential update) will be performed under exclusive lock to
2647 // guard against multiple threads trying to add the same check.
2648 void EnsureHasReceiverCheck(
2649 intptr_t receiver_class_id,
2650 const Function& target,
2651 intptr_t count = 1,
2652 StaticTypeExactnessState exactness =
2654
2655 // Adds sorted so that Smi is the first class-id. Use only for
2656 // num_args_tested == 1.
2657 void AddReceiverCheck(intptr_t receiver_class_id,
2658 const Function& target,
2659 intptr_t count = 1,
2660 StaticTypeExactnessState exactness =
2662
2663 // Retrieving checks.
2664
2665 void GetCheckAt(intptr_t index,
2666 GrowableArray<intptr_t>* class_ids,
2667 Function* target) const;
2668 void GetClassIdsAt(intptr_t index, GrowableArray<intptr_t>* class_ids) const;
2669
2670 // Only for 'num_args_checked == 1'.
2671 void GetOneClassCheckAt(intptr_t index,
2672 intptr_t* class_id,
2673 Function* target) const;
2674 // Only for 'num_args_checked == 1'.
2675 intptr_t GetCidAt(intptr_t index) const;
2676
2677 intptr_t GetReceiverClassIdAt(intptr_t index) const;
2678 intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;
2679
2680 FunctionPtr GetTargetAt(intptr_t index) const;
2681
2682 void IncrementCountAt(intptr_t index, intptr_t value) const;
2683 void SetCountAt(intptr_t index, intptr_t value) const;
2684 intptr_t GetCountAt(intptr_t index) const;
2685 intptr_t AggregateCount() const;
2686
2687 // Returns this->untag() if num_args_tested == 1 and arg_nr == 1, otherwise
2688 // returns a new ICData object containing only unique arg_nr checks.
2689 // Returns only used entries.
2690 ICDataPtr AsUnaryClassChecksForArgNr(intptr_t arg_nr) const;
2691 ICDataPtr AsUnaryClassChecks() const { return AsUnaryClassChecksForArgNr(0); }
2692
2693 // Returns ICData with aggregated receiver count, sorted by highest count.
2694 // Smi not first!! (the convention for ICData used in code generation is that
2695 // Smi check is first)
2696 // Used for printing and optimizations.
2697 ICDataPtr AsUnaryClassChecksSortedByCount() const;
2698
2699 UnlinkedCallPtr AsUnlinkedCall() const;
2700
2701 bool HasReceiverClassId(intptr_t class_id) const;
2702
2703 // Note: passing non-null receiver_type enables exactness tracking for
2704 // the receiver type. Receiver type is expected to be a fully
2705 // instantiated generic (but not a FutureOr).
2706 // See StaticTypeExactnessState for more information.
2707 static ICDataPtr New(
2708 const Function& owner,
2709 const String& target_name,
2711 intptr_t deopt_id,
2712 intptr_t num_args_tested,
2713 RebindRule rebind_rule,
2714 const AbstractType& receiver_type = Object::null_abstract_type());
2715
2716 // Similar to [New] makes the ICData have an initial (cids, target) entry.
2717 static ICDataPtr NewWithCheck(
2718 const Function& owner,
2719 const String& target_name,
2721 intptr_t deopt_id,
2722 intptr_t num_args_tested,
2723 RebindRule rebind_rule,
2725 const Function& target,
2726 const AbstractType& receiver_type = Object::null_abstract_type());
2727
2728 static ICDataPtr NewForStaticCall(const Function& owner,
2729 const Function& target,
2731 intptr_t deopt_id,
2732 intptr_t num_args_tested,
2733 RebindRule rebind_rule);
2734
2735 static ICDataPtr NewFrom(const ICData& from, intptr_t num_args_tested);
2736
2737 // Generates a new ICData with descriptor and data array copied (deep clone).
2738 static ICDataPtr Clone(const ICData& from);
2739
2740 // Gets the [ICData] from the [ICData::entries_] array (which stores a back
2741 // ref).
2742 //
2743 // May return `null` if the [ICData] is empty.
2744 static ICDataPtr ICDataOfEntriesArray(const Array& array);
2745
2746 static intptr_t TestEntryLengthFor(intptr_t num_args,
2747 bool tracking_exactness);
2748
2749 static intptr_t CountIndexFor(intptr_t num_args) { return num_args; }
2750 static intptr_t EntryPointIndexFor(intptr_t num_args) { return num_args; }
2751
2752 static intptr_t TargetIndexFor(intptr_t num_args) { return num_args + 1; }
2753 static intptr_t CodeIndexFor(intptr_t num_args) { return num_args + 1; }
2754
2755 static intptr_t ExactnessIndexFor(intptr_t num_args) { return num_args + 2; }
2756
2757 bool IsUsedAt(intptr_t i) const;
2758
2759 void PrintToJSONArray(const JSONArray& jsarray,
2760 TokenPosition token_pos) const;
2761
2762 // Initialize the preallocated empty ICData entry arrays.
2763 static void Init();
2764
2765 // Clear the preallocated empty ICData entry arrays.
2766 static void Cleanup();
2767
2768 // We cache ICData with 0, 1, 2 arguments tested without exactness
2769 // tracking and with 1 argument tested with exactness tracking.
2770 enum {
2771 kCachedICDataZeroArgTestedWithoutExactnessTrackingIdx = 0,
2772 kCachedICDataMaxArgsTestedWithoutExactnessTracking = 2,
2773 kCachedICDataOneArgWithExactnessTrackingIdx =
2774 kCachedICDataZeroArgTestedWithoutExactnessTrackingIdx +
2775 kCachedICDataMaxArgsTestedWithoutExactnessTracking + 1,
2776 kCachedICDataArrayCount = kCachedICDataOneArgWithExactnessTrackingIdx + 1,
2777 };
2778
2779 bool is_static_call() const;
2780
2781 intptr_t FindCheck(const GrowableArray<intptr_t>& cids) const;
2782
2783 ArrayPtr entries() const {
2784 return untag()->entries<std::memory_order_acquire>();
2785 }
2786
2788 return untag()->state_bits_.Read<ReceiverCannotBeSmiBit>();
2789 }
2790
2792 untag()->state_bits_.UpdateBool<ReceiverCannotBeSmiBit>(value);
2793 }
2794
2795 uword Hash() const;
2796
2797 private:
2798 static ICDataPtr New();
2799
2800 // Grows the array and also sets the argument to the index that should be used
2801 // for the new entry.
2802 ArrayPtr Grow(intptr_t* index) const;
2803
2804 void set_deopt_id(intptr_t value) const;
2805 void set_entries(const Array& value) const;
2806 void set_owner(const Function& value) const;
2807 void set_rebind_rule(uint32_t rebind_rule) const;
2808 void clear_state_bits() const;
2809 void set_tracking_exactness(bool value) const {
2810 untag()->state_bits_.UpdateBool<TrackingExactnessBit>(value);
2811 }
2812
2813 // Does entry |index| contain the sentinel value?
2814 void SetNumArgsTested(intptr_t value) const;
2815 void SetReceiversStaticType(const AbstractType& type) const;
2816 DEBUG_ONLY(void AssertInvariantsAreSatisfied() const;)
2817
2818 static void SetTargetAtPos(const Array& data,
2819 intptr_t data_pos,
2820 intptr_t num_args_tested,
2821 const Function& target);
2822 void AddCheckInternal(const GrowableArray<intptr_t>& class_ids,
2823 const Function& target,
2824 intptr_t count) const;
2825 void AddReceiverCheckInternal(intptr_t receiver_class_id,
2826 const Function& target,
2827 intptr_t count,
2828 StaticTypeExactnessState exactness) const;
2829
2830 // This bit is set when a call site becomes megamorphic and starts using a
2831 // MegamorphicCache instead of ICData. It means that the entries in the
2832 // ICData are incomplete and the MegamorphicCache needs to also be consulted
2833 // to list the call site's observed receiver classes and targets.
2834 // In the compiler, this should only be read once by CallTargets to avoid the
2835 // compiler seeing an unstable set of feedback.
2836 bool is_megamorphic() const {
2837 // Ensure any following load instructions do not get performed before this
2838 // one.
2839 return untag()
2840 ->state_bits_.Read<MegamorphicBit, std::memory_order_acquire>();
2841 }
2842
2843 bool ValidateInterceptor(const Function& target) const;
2844
2845 enum {
2846 kNumArgsTestedPos = 0,
2847 kNumArgsTestedSize = 2,
2848 kTrackingExactnessPos = kNumArgsTestedPos + kNumArgsTestedSize,
2849 kTrackingExactnessSize = 1,
2850 kDeoptReasonPos = kTrackingExactnessPos + kTrackingExactnessSize,
2851 kDeoptReasonSize = kLastRecordedDeoptReason + 1,
2852 kRebindRulePos = kDeoptReasonPos + kDeoptReasonSize,
2853 kRebindRuleSize = 3,
2854 kMegamorphicPos = kRebindRulePos + kRebindRuleSize,
2855 kMegamorphicSize = 1,
2856 kReceiverCannotBeSmiPos = kMegamorphicPos + kMegamorphicSize,
2857 kReceiverCannotBeSmiSize = 1,
2858 };
2859
2860 COMPILE_ASSERT(kReceiverCannotBeSmiPos + kReceiverCannotBeSmiSize <=
2861 sizeof(UntaggedICData::state_bits_) * kBitsPerWord);
2862 COMPILE_ASSERT(kNumRebindRules <= (1 << kRebindRuleSize));
2863
2864 class NumArgsTestedBits : public BitField<uint32_t,
2865 uint32_t,
2866 kNumArgsTestedPos,
2867 kNumArgsTestedSize> {};
2868 class TrackingExactnessBit : public BitField<uint32_t,
2869 bool,
2870 kTrackingExactnessPos,
2871 kTrackingExactnessSize> {};
2872 class DeoptReasonBits : public BitField<uint32_t,
2873 uint32_t,
2874 ICData::kDeoptReasonPos,
2875 ICData::kDeoptReasonSize> {};
2876 class RebindRuleBits : public BitField<uint32_t,
2877 uint32_t,
2878 ICData::kRebindRulePos,
2879 ICData::kRebindRuleSize> {};
2880 class MegamorphicBit
2881 : public BitField<uint32_t, bool, kMegamorphicPos, kMegamorphicSize> {};
2882
2883 class ReceiverCannotBeSmiBit : public BitField<uint32_t,
2884 bool,
2885 kReceiverCannotBeSmiPos,
2886 kReceiverCannotBeSmiSize> {};
2887
2888#if defined(DEBUG)
2889 // Used in asserts to verify that a check is not added twice.
2890 bool HasCheck(const GrowableArray<intptr_t>& cids) const;
2891#endif // DEBUG
2892
2893 intptr_t TestEntryLength() const;
2894 static ArrayPtr NewNonCachedEmptyICDataArray(intptr_t num_args_tested,
2895 bool tracking_exactness);
2896 static ArrayPtr CachedEmptyICDataArray(intptr_t num_args_tested,
2897 bool tracking_exactness);
2898 static bool IsCachedEmptyEntry(const Array& array);
2899 static ICDataPtr NewDescriptor(Zone* zone,
2900 const Function& owner,
2901 const String& target_name,
2902 const Array& arguments_descriptor,
2903 intptr_t deopt_id,
2904 intptr_t num_args_tested,
2905 RebindRule rebind_rule,
2906 const AbstractType& receiver_type);
2907
2908 static void WriteSentinel(const Array& data,
2909 intptr_t test_entry_length,
2910 const Object& back_ref);
2911
2912 // A cache of VM heap allocated preinitialized empty ic data entry arrays.
2913 static ArrayPtr cached_icdata_arrays_[kCachedICDataArrayCount];
2914
2916 friend class CallSiteResetter;
2917 friend class CallTargets;
2918 friend class Class;
2920 friend class ICDataTestTask;
2922};
2923
2924// Often used constants for number of free function type parameters.
2925enum {
2927
2928 // 'kCurrentAndEnclosingFree' is used when partially applying a signature
2929 // function to a set of type arguments. It indicates that the set of type
2930 // parameters declared by the current function and enclosing functions should
2931 // be considered free, and the current function type parameters should be
2932 // substituted as well.
2933 //
2934 // For instance, if the signature "<T>(T, R) => T" is instantiated with
2935 // function type arguments [int, String] and kCurrentAndEnclosingFree is
2936 // supplied, the result of the instantiation will be "(String, int) => int".
2938
2939 // Only parameters declared by enclosing functions are free.
2941};
2942
2943// Formatting configuration for Function::PrintName.
2947
2948 // By default function name includes the name of the enclosing class if any.
2949 // However in some contexts this information is redundant and class name
2950 // is already known. In this case setting |include_class_name| to false
2951 // allows you to exclude this information from the formatted name.
2952 bool include_class_name = true;
2953
2954 // By default function name includes the name of the enclosing function if
2955 // any. However in some contexts this information is redundant and
2956 // the name of the enclosing function is already known. In this case
2957 // setting |include_parent_name| to false allows to exclude this information
2958 // from the formatted name.
2959 bool include_parent_name = true;
2960
2962 Object::NameDisambiguation name_disambiguation =
2964 : name_visibility(visibility),
2965 disambiguate_names(name_disambiguation ==
2967
2969 Object::NameVisibility visibility) {
2971 params.include_class_name = false;
2972 return params;
2973 }
2974
2976 Object::NameVisibility visibility) {
2978 params.include_class_name = false;
2979 params.include_parent_name = false;
2980 return params;
2981 }
2982};
2983
2984enum class FfiCallbackKind : uint8_t {
2988};
2989
2990class Function : public Object {
2991 public:
2992 StringPtr name() const { return untag()->name(); }
2993 StringPtr UserVisibleName() const; // Same as scrubbed name.
2994 const char* UserVisibleNameCString() const;
2995
2996 const char* NameCString(NameVisibility name_visibility) const;
2997
2998 void PrintName(const NameFormattingParams& params,
2999 BaseTextBuffer* printer) const;
3000 StringPtr QualifiedScrubbedName() const;
3001 const char* QualifiedScrubbedNameCString() const;
3002 StringPtr QualifiedUserVisibleName() const;
3003 const char* QualifiedUserVisibleNameCString() const;
3004
3005 virtual StringPtr DictionaryName() const { return name(); }
3006
3007 StringPtr GetSource() const;
3008
3009 // Set the "C signature" for an FFI trampoline.
3010 // Can only be used on FFI trampolines.
3011 void SetFfiCSignature(const FunctionType& sig) const;
3012
3013 // Retrieves the "C signature" for an FFI trampoline or FFI native.
3014 FunctionTypePtr FfiCSignature() const;
3015
3016 bool FfiCSignatureContainsHandles() const;
3017 bool FfiCSignatureReturnsStruct() const;
3018
3019 // Can only be called on FFI trampolines.
3020 int32_t FfiCallbackId() const;
3021
3022 // Should be called when ffi trampoline function object is created.
3023 void AssignFfiCallbackId(int32_t callback_id) const;
3024
3025 // Can only be called on FFI natives and FFI call closures.
3026 bool FfiIsLeaf() const;
3027
3028 // Can only be called on FFI trampolines.
3029 FunctionPtr FfiCallbackTarget() const;
3030
3031 // Can only be called on FFI trampolines.
3032 void SetFfiCallbackTarget(const Function& target) const;
3033
3034 // Can only be called on FFI trampolines.
3035 InstancePtr FfiCallbackExceptionalReturn() const;
3036
3037 // Can only be called on FFI trampolines.
3038 void SetFfiCallbackExceptionalReturn(const Instance& value) const;
3039
3040 // Can only be called on FFI trampolines.
3041 FfiCallbackKind GetFfiCallbackKind() const;
3042
3043 // Can only be called on FFI trampolines.
3044 void SetFfiCallbackKind(FfiCallbackKind value) const;
3045
3046 // Return the signature of this function.
3048 void SetSignature(const FunctionType& value) const;
3049 static intptr_t signature_offset() {
3050 return OFFSET_OF(UntaggedFunction, signature_);
3051 }
3052
3053 // Build a string of the form '<T>(T, {B b, C c}) => R' representing the
3054 // internal signature of the given function. In this example, T is a type
3055 // parameter of this function and R is a type parameter of class C, the owner
3056 // of the function. B and C are not type parameters.
3057 StringPtr InternalSignature() const;
3058
3059 // Build a string of the form '<T>(T, {B b, C c}) => R' representing the
3060 // user visible signature of the given function. In this example, T is a type
3061 // parameter of this function and R is a type parameter of class C, the owner
3062 // of the function. B and C are not type parameters.
3063 // Implicit parameters are hidden.
3064 StringPtr UserVisibleSignature() const;
3065
3066 // Returns true if the signature of this function is instantiated, i.e. if it
3067 // does not involve generic parameter types or generic result type.
3068 // Note that function type parameters declared by this function do not make
3069 // its signature uninstantiated, only type parameters declared by parent
3070 // generic functions or class type parameters.
3071 bool HasInstantiatedSignature(
3072 Genericity genericity = kAny,
3073 intptr_t num_free_fun_type_params = kAllFree) const;
3074
3075 bool IsPrivate() const;
3076
3077 ClassPtr Owner() const;
3078 void set_owner(const Object& value) const;
3079 ScriptPtr script() const;
3080#if !defined(DART_PRECOMPILED_RUNTIME)
3081 KernelProgramInfoPtr KernelProgramInfo() const;
3082#endif
3083 ObjectPtr RawOwner() const { return untag()->owner(); }
3084
3085 RegExpPtr regexp() const;
3086 intptr_t string_specialization_cid() const;
3087 bool is_sticky_specialization() const;
3088 void SetRegExpData(const RegExp& regexp,
3089 intptr_t string_specialization_cid,
3090 bool sticky) const;
3091
3092 StringPtr native_name() const;
3093 void set_native_name(const String& name) const;
3094
3095 InstancePtr GetNativeAnnotation() const;
3096 bool is_ffi_native() const;
3097 bool is_old_native() const;
3098
3099 AbstractTypePtr result_type() const {
3100 return signature()->untag()->result_type();
3101 }
3102
3103 // The parameters, starting with NumImplicitParameters() parameters which are
3104 // only visible to the VM, but not to Dart users.
3105 // Note that type checks exclude implicit parameters.
3106 AbstractTypePtr ParameterTypeAt(intptr_t index) const;
3107 ArrayPtr parameter_types() const {
3108 return signature()->untag()->parameter_types();
3109 }
3110
3111 // Outside of the AOT runtime, functions store the names for their positional
3112 // parameters, and delegate storage of the names for named parameters to
3113 // their signature. These methods handle fetching the name from and
3114 // setting the name to the correct location.
3115 StringPtr ParameterNameAt(intptr_t index) const;
3116 // Only valid for positional parameter indexes, as this should be called
3117 // explicitly on the signature for named parameters.
3118 void SetParameterNameAt(intptr_t index, const String& value) const;
3119 // Creates an appropriately sized array in the function to hold positional
3120 // parameter names, using the positional parameter count in the signature.
3121 // Uses same default space as Function::New.
3122 void CreateNameArray(Heap::Space space = Heap::kOld) const;
3123
3124 // Delegates to the signature, which stores the named parameter flags.
3125 bool IsRequiredAt(intptr_t index) const;
3126
3127 // The formal type parameters, their bounds, and defaults, are specified as an
3128 // object of type TypeParameters stored in the signature.
3129 TypeParametersPtr type_parameters() const {
3130 return signature()->untag()->type_parameters();
3131 }
3132
3133 // Returns the number of local type arguments for this function.
3134 intptr_t NumTypeParameters() const;
3135 // Return the cumulative number of type arguments in all parent functions.
3136 intptr_t NumParentTypeArguments() const;
3137 // Return the cumulative number of type arguments for this function, including
3138 // type arguments for all parent functions.
3139 intptr_t NumTypeArguments() const;
3140 // Return whether this function declares local type arguments.
3141 bool IsGeneric() const;
3142 // Returns whether any parent function of this function is generic.
3143 bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
3144
3145 // Return the type parameter declared at index.
3146 TypeParameterPtr TypeParameterAt(
3147 intptr_t index,
3148 Nullability nullability = Nullability::kNonNullable) const;
3149
3150 // Not thread-safe; must be called in the main thread.
3151 // Sets function's code and code's function.
3152 void InstallOptimizedCode(const Code& code) const;
3153 void AttachCode(const Code& value) const;
3154 void SetInstructions(const Code& value) const;
3155 void SetInstructionsSafe(const Code& value) const;
3156 void ClearCode() const;
3157 void ClearCodeSafe() const;
3158
3159 // Disables optimized code and switches to unoptimized code.
3160 void SwitchToUnoptimizedCode() const;
3161
3162 // Ensures that the function has code. If there is no code it compiles the
3163 // unoptimized version of the code. If the code contains errors, it calls
3164 // Exceptions::PropagateError and does not return. Normally returns the
3165 // current code, whether it is optimized or unoptimized.
3166 CodePtr EnsureHasCode() const;
3167
3168 // Disables optimized code and switches to unoptimized code (or the lazy
3169 // compilation stub).
3170 void SwitchToLazyCompiledUnoptimizedCode() const;
3171
3172 // Compiles unoptimized code (if necessary) and attaches it to the function.
3173 void EnsureHasCompiledUnoptimizedCode() const;
3174
3175 // Return the most recently compiled and installed code for this function.
3176 // It is not the only Code object that points to this function.
3177 CodePtr CurrentCode() const { return CurrentCodeOf(ptr()); }
3178
3179 bool SafeToClosurize() const;
3180
3181 static CodePtr CurrentCodeOf(const FunctionPtr function) {
3182 return function->untag()->code<std::memory_order_acquire>();
3183 }
3184
3185 CodePtr unoptimized_code() const {
3186#if defined(DART_PRECOMPILED_RUNTIME)
3187 return static_cast<CodePtr>(Object::null());
3188#else
3189 return untag()->unoptimized_code();
3190#endif
3191 }
3192 void set_unoptimized_code(const Code& value) const;
3193 bool HasCode() const;
3194 static bool HasCode(FunctionPtr function);
3195
3196 static intptr_t code_offset() { return OFFSET_OF(UntaggedFunction, code_); }
3197
3198 uword entry_point() const { return EntryPointOf(ptr()); }
3199 static uword EntryPointOf(const FunctionPtr function) {
3200 return function->untag()->entry_point_;
3201 }
3202
3203 static intptr_t entry_point_offset(
3205 switch (entry_kind) {
3207 return OFFSET_OF(UntaggedFunction, entry_point_);
3209 return OFFSET_OF(UntaggedFunction, unchecked_entry_point_);
3210 default:
3211 UNREACHABLE();
3212 }
3213 }
3214
3216 return OFFSET_OF(UntaggedFunction, unchecked_entry_point_);
3217 }
3218
3219 virtual uword Hash() const;
3220
3221 // Returns true if there is at least one debugger breakpoint
3222 // set in this function.
3223 bool HasBreakpoint() const;
3224
3225 ContextScopePtr context_scope() const;
3226 void set_context_scope(const ContextScope& value) const;
3227
3229 // Context depth at which the `@pragma('vm:awaiter-link')` variable
3230 // is located.
3231 uint8_t depth = UntaggedClosureData::kNoAwaiterLinkDepth;
3232 // Context index at which the `@pragma('vm:awaiter-link')` variable
3233 // is located.
3234 uint8_t index = static_cast<uint8_t>(-1);
3235 };
3236
3237 AwaiterLink awaiter_link() const;
3238 void set_awaiter_link(AwaiterLink link) const;
3239 bool HasAwaiterLink() const {
3240 return IsClosureFunction() &&
3241 (awaiter_link().depth != UntaggedClosureData::kNoAwaiterLinkDepth);
3242 }
3243
3244 // Enclosing function of this local function.
3245 FunctionPtr parent_function() const;
3246
3247 // Returns a canonicalized vector of the type parameters instantiated
3248 // to bounds (e.g., the local type arguments that are used if no TAV is
3249 // provided when the function is invoked).
3250 //
3251 // If the function is owned by a generic class or has any generic parent
3252 // functions, then the returned vector may require instantiation, see
3253 // default_type_arguments_instantiation_mode() for Closure functions
3254 // or TypeArguments::GetInstantiationMode() otherwise.
3255 //
3256 // If non-generic, the empty type arguments vector is returned.
3257 TypeArgumentsPtr DefaultTypeArguments(Zone* zone) const;
3258
3259 // Only usable for closure functions.
3260 InstantiationMode default_type_arguments_instantiation_mode() const;
3261 void set_default_type_arguments_instantiation_mode(
3262 InstantiationMode value) const;
3263
3264 // Enclosing outermost function of this local function.
3265 FunctionPtr GetOutermostFunction() const;
3266
3267 void set_extracted_method_closure(const Function& function) const;
3268 FunctionPtr extracted_method_closure() const;
3269
3270 void set_saved_args_desc(const Array& array) const;
3271 ArrayPtr saved_args_desc() const;
3272
3274 return IsInvokeFieldDispatcher() || IsNoSuchMethodDispatcher();
3275 }
3276
3277 void set_accessor_field(const Field& value) const;
3278 FieldPtr accessor_field() const;
3279
3280 bool IsRegularFunction() const {
3281 return kind() == UntaggedFunction::kRegularFunction;
3282 }
3283
3284 bool IsMethodExtractor() const {
3285 return kind() == UntaggedFunction::kMethodExtractor;
3286 }
3287
3289 return kind() == UntaggedFunction::kNoSuchMethodDispatcher;
3290 }
3291
3292 bool IsRecordFieldGetter() const {
3293 return kind() == UntaggedFunction::kRecordFieldGetter;
3294 }
3295
3297 return kind() == UntaggedFunction::kInvokeFieldDispatcher;
3298 }
3299
3301 return IsInvokeFieldDispatcher() &&
3302 IsDynamicInvocationForwarderName(name());
3303 }
3304
3305 // Performs all the checks that don't require the current thread first, to
3306 // avoid retrieving it unless they all pass. If you have a handle on the
3307 // current thread, call the version that takes one instead.
3309 if (!IsDynamicInvokeFieldDispatcher()) return false;
3310 return IsDynamicClosureCallDispatcher(Thread::Current());
3311 }
3312 bool IsDynamicClosureCallDispatcher(Thread* thread) const;
3313
3315 return kind() == UntaggedFunction::kDynamicInvocationForwarder;
3316 }
3317
3319 return kind() == UntaggedFunction::kImplicitGetter ||
3320 kind() == UntaggedFunction::kImplicitSetter ||
3321 kind() == UntaggedFunction::kImplicitStaticGetter;
3322 }
3323
3324 // Returns true iff an implicit closure function has been created
3325 // for this function.
3327 return implicit_closure_function() != null();
3328 }
3329
3330 // Returns the closure function implicitly created for this function. If none
3331 // exists yet, create one and remember it. Implicit closure functions are
3332 // used in VM Closure instances that represent results of tear-off operations.
3333 FunctionPtr ImplicitClosureFunction() const;
3334 void DropUncompiledImplicitClosureFunction() const;
3335
3336 // Return the closure implicitly created for this function.
3337 // If none exists yet, create one and remember it.
3338 ClosurePtr ImplicitStaticClosure() const;
3339
3340 ClosurePtr ImplicitInstanceClosure(const Instance& receiver) const;
3341
3342 // Returns the target of the implicit closure or null if the target is now
3343 // invalid (e.g., mismatched argument shapes after a reload).
3344 FunctionPtr ImplicitClosureTarget(Zone* zone) const;
3345
3346 FunctionPtr ForwardingTarget() const;
3347 void SetForwardingTarget(const Function& target) const;
3348
3349 UntaggedFunction::Kind kind() const { return KindOf(ptr()); }
3350 static UntaggedFunction::Kind KindOf(FunctionPtr func) {
3351 return func->untag()->kind_tag_.Read<KindBits>();
3352 }
3353
3355 return untag()->kind_tag_.Read<ModifierBits>();
3356 }
3357
3358 static const char* KindToCString(UntaggedFunction::Kind kind);
3359
3360 bool IsConstructor() const {
3361 return kind() == UntaggedFunction::kConstructor;
3362 }
3364 return IsConstructor() && !is_static();
3365 }
3366 bool IsImplicitConstructor() const;
3367 bool IsFactory() const { return IsConstructor() && is_static(); }
3368
3369 bool HasThisParameter() const {
3370 return IsDynamicFunction(/*allow_abstract=*/true) ||
3371 IsGenerativeConstructor() || (IsFieldInitializer() && !is_static());
3372 }
3373
3374 bool IsDynamicFunction(bool allow_abstract = false) const {
3375 if (is_static() || (!allow_abstract && is_abstract())) {
3376 return false;
3377 }
3378 switch (kind()) {
3379 case UntaggedFunction::kRegularFunction:
3380 case UntaggedFunction::kGetterFunction:
3381 case UntaggedFunction::kSetterFunction:
3382 case UntaggedFunction::kImplicitGetter:
3383 case UntaggedFunction::kImplicitSetter:
3384 case UntaggedFunction::kMethodExtractor:
3385 case UntaggedFunction::kNoSuchMethodDispatcher:
3386 case UntaggedFunction::kInvokeFieldDispatcher:
3387 case UntaggedFunction::kDynamicInvocationForwarder:
3388 case UntaggedFunction::kRecordFieldGetter:
3389 return true;
3390 case UntaggedFunction::kClosureFunction:
3391 case UntaggedFunction::kImplicitClosureFunction:
3392 case UntaggedFunction::kConstructor:
3393 case UntaggedFunction::kImplicitStaticGetter:
3394 case UntaggedFunction::kFieldInitializer:
3395 case UntaggedFunction::kIrregexpFunction:
3396 return false;
3397 default:
3398 UNREACHABLE();
3399 return false;
3400 }
3401 }
3402 bool IsStaticFunction() const {
3403 if (!is_static()) {
3404 return false;
3405 }
3406 switch (kind()) {
3407 case UntaggedFunction::kRegularFunction:
3408 case UntaggedFunction::kGetterFunction:
3409 case UntaggedFunction::kSetterFunction:
3410 case UntaggedFunction::kImplicitGetter:
3411 case UntaggedFunction::kImplicitSetter:
3412 case UntaggedFunction::kImplicitStaticGetter:
3413 case UntaggedFunction::kFieldInitializer:
3414 case UntaggedFunction::kIrregexpFunction:
3415 return true;
3416 case UntaggedFunction::kClosureFunction:
3417 case UntaggedFunction::kImplicitClosureFunction:
3418 case UntaggedFunction::kConstructor:
3419 case UntaggedFunction::kMethodExtractor:
3420 case UntaggedFunction::kNoSuchMethodDispatcher:
3421 case UntaggedFunction::kInvokeFieldDispatcher:
3422 case UntaggedFunction::kDynamicInvocationForwarder:
3423 case UntaggedFunction::kFfiTrampoline:
3424 case UntaggedFunction::kRecordFieldGetter:
3425 return false;
3426 default:
3427 UNREACHABLE();
3428 return false;
3429 }
3430 }
3431
3433 return !(is_static() || (kind() == UntaggedFunction::kConstructor));
3434 }
3435
3437 return !(is_static() || (kind() == UntaggedFunction::kConstructor));
3438 }
3439
3440 bool NeedsMonomorphicCheckedEntry(Zone* zone) const;
3441 bool HasDynamicCallers(Zone* zone) const;
3442 bool PrologueNeedsArgumentsDescriptor() const;
3443
3444 bool MayHaveUncheckedEntryPoint() const;
3445
3447#if defined(DART_PRECOMPILED_RUNTIME)
3448 return TokenPosition::kNoSource;
3449#else
3450 return untag()->token_pos_;
3451#endif
3452 }
3453 void set_token_pos(TokenPosition value) const;
3454
3456#if defined(DART_PRECOMPILED_RUNTIME)
3457 return TokenPosition::kNoSource;
3458#else
3459 return untag()->end_token_pos_;
3460#endif
3461 }
3463#if defined(DART_PRECOMPILED_RUNTIME)
3464 UNREACHABLE();
3465#else
3466 StoreNonPointer(&untag()->end_token_pos_, value);
3467#endif
3468 }
3469
3470#if !defined(PRODUCT) && \
3471 (defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME))
3472 int32_t line() const { return untag()->token_pos_.Serialize(); }
3473
3474 void set_line(int32_t line) const {
3476 }
3477#endif
3478
3479 // Returns the size of the source for this function.
3480 intptr_t SourceSize() const;
3481
3482 uint32_t packed_fields() const {
3483#if defined(DART_PRECOMPILED_RUNTIME)
3484 UNREACHABLE();
3485#else
3486 return untag()->packed_fields_;
3487#endif
3488 }
3489 void set_packed_fields(uint32_t packed_fields) const;
3490
3491 // Returns the number of required positional parameters.
3492 intptr_t num_fixed_parameters() const;
3493 // Returns the number of optional parameters, whether positional or named.
3494 bool HasOptionalParameters() const;
3495 // Returns whether the function has optional named parameters.
3496 bool HasOptionalNamedParameters() const;
3497 // Returns whether the function has required named parameters.
3498 bool HasRequiredNamedParameters() const;
3499 // Returns whether the function has optional positional parameters.
3500 bool HasOptionalPositionalParameters() const;
3501 // Returns the number of optional parameters, or 0 if none.
3502 intptr_t NumOptionalParameters() const;
3503 // Returns the number of optional positional parameters, or 0 if none.
3504 intptr_t NumOptionalPositionalParameters() const;
3505 // Returns the number of optional named parameters, or 0 if none.
3506 intptr_t NumOptionalNamedParameters() const;
3507 // Returns the total number of both required and optional parameters.
3508 intptr_t NumParameters() const;
3509 // Returns the number of implicit parameters, e.g., this for instance methods.
3510 intptr_t NumImplicitParameters() const;
3511
3512 // Returns true if parameters of this function are copied into the frame
3513 // in the function prologue.
3515 return HasOptionalParameters() || IsSuspendableFunction();
3516 }
3517
3518#if !defined(DART_PRECOMPILED_RUNTIME)
3519 intptr_t MaxNumberOfParametersInRegisters(Zone* zone) const;
3520#endif // !defined(DART_PRECOMPILED_RUNTIME)
3521
3522#if defined(DART_PRECOMPILED_RUNTIME)
3523#define DEFINE_GETTERS_AND_SETTERS(return_type, type, name) \
3524 static intptr_t name##_offset() { \
3525 UNREACHABLE(); \
3526 return 0; \
3527 } \
3528 return_type name() const { return 0; } \
3529 \
3530 void set_##name(type value) const { UNREACHABLE(); }
3531#else
3532#define DEFINE_GETTERS_AND_SETTERS(return_type, type, name) \
3533 static intptr_t name##_offset() { \
3534 return OFFSET_OF(UntaggedFunction, name##_); \
3535 } \
3536 return_type name() const { \
3537 return LoadNonPointer<type, std::memory_order_relaxed>(&untag()->name##_); \
3538 } \
3539 \
3540 void set_##name(type value) const { \
3541 StoreNonPointer<type, type, std::memory_order_relaxed>(&untag()->name##_, \
3542 value); \
3543 }
3544#endif
3545
3547
3548#undef DEFINE_GETTERS_AND_SETTERS
3549
3550 intptr_t kernel_offset() const {
3551#if defined(DART_PRECOMPILED_RUNTIME)
3552 return 0;
3553#else
3554 return untag()->kernel_offset_;
3555#endif
3556 }
3557
3558 void set_kernel_offset(intptr_t value) const {
3559#if defined(DART_PRECOMPILED_RUNTIME)
3560 UNREACHABLE();
3561#else
3562 ASSERT(value >= 0);
3563 StoreNonPointer(&untag()->kernel_offset_, value);
3564#endif
3565 }
3566
3567 void InheritKernelOffsetFrom(const Function& src) const;
3568 void InheritKernelOffsetFrom(const Field& src) const;
3569
3570 static constexpr intptr_t kMaxInstructionCount = (1 << 16) - 1;
3571
3573 if (value > kMaxInstructionCount) value = kMaxInstructionCount;
3574 set_optimized_instruction_count(value);
3575 }
3576
3578 if (value > kMaxInstructionCount) value = kMaxInstructionCount;
3579 set_optimized_call_site_count(value);
3580 }
3581
3582 void SetKernelLibraryAndEvalScript(
3583 const Script& script,
3584 const class KernelProgramInfo& kernel_program_info,
3585 intptr_t index) const;
3586
3587 intptr_t KernelLibraryOffset() const;
3588 intptr_t KernelLibraryIndex() const;
3589
3590 TypedDataViewPtr KernelLibrary() const;
3591
3592 bool IsOptimizable() const;
3593 void SetIsOptimizable(bool value) const;
3594
3595 // Whether this function must be optimized immediately and cannot be compiled
3596 // with the unoptimizing compiler. Such a function must be sure to not
3597 // deoptimize, since we won't generate deoptimization info or register
3598 // dependencies. It will be compiled into optimized code immediately when it's
3599 // run.
3600 bool ForceOptimize() const;
3601
3602 // Whether this function should be inlined if at all possible.
3603 bool IsPreferInline() const;
3604
3605 // Whether this function is idempotent (i.e. calling it twice has the same
3606 // effect as calling it once - no visible side effects).
3607 //
3608 // If a function is idempotent VM may decide to abort halfway through one call
3609 // and retry it again.
3610 bool IsIdempotent() const;
3611
3612 bool IsCachableIdempotent() const;
3613
3614 // Whether this function's |recognized_kind| requires optimization.
3615 bool RecognizedKindForceOptimize() const;
3616
3617 bool CanBeInlined() const;
3618
3620 return untag()->kind_tag_.Read<RecognizedBits>();
3621 }
3622 void set_recognized_kind(MethodRecognizer::Kind value) const;
3623
3624 bool IsRecognized() const {
3625 return recognized_kind() != MethodRecognizer::kUnknown;
3626 }
3627
3628 bool HasOptimizedCode() const;
3629
3630 // Returns true if the argument counts are valid for calling this function.
3631 // Otherwise, it returns false and the reason (if error_message is not
3632 // nullptr).
3633 bool AreValidArgumentCounts(intptr_t num_type_arguments,
3634 intptr_t num_arguments,
3635 intptr_t num_named_arguments,
3636 String* error_message) const;
3637
3638 // Returns a TypeError if the provided arguments don't match the function
3639 // parameter types, null otherwise. Assumes AreValidArguments is called first.
3640 //
3641 // If the function has a non-null receiver in the arguments, the instantiator
3642 // type arguments are retrieved from the receiver, otherwise the null type
3643 // arguments vector is used.
3644 //
3645 // If the function is generic, the appropriate function type arguments are
3646 // retrieved either from the arguments array or the receiver (if a closure).
3647 // If no function type arguments are available in either location, the bounds
3648 // of the function type parameters are instantiated and used as the function
3649 // type arguments.
3650 //
3651 // The local function type arguments (_not_ parent function type arguments)
3652 // are also checked against the bounds of the corresponding parameters to
3653 // ensure they are appropriate subtypes if the function is generic.
3654 ObjectPtr DoArgumentTypesMatch(const Array& args,
3655 const ArgumentsDescriptor& arg_names) const;
3656
3657 // Returns a TypeError if the provided arguments don't match the function
3658 // parameter types, null otherwise. Assumes AreValidArguments is called first.
3659 //
3660 // If the function is generic, the appropriate function type arguments are
3661 // retrieved either from the arguments array or the receiver (if a closure).
3662 // If no function type arguments are available in either location, the bounds
3663 // of the function type parameters are instantiated and used as the function
3664 // type arguments.
3665 //
3666 // The local function type arguments (_not_ parent function type arguments)
3667 // are also checked against the bounds of the corresponding parameters to
3668 // ensure they are appropriate subtypes if the function is generic.
3669 ObjectPtr DoArgumentTypesMatch(
3670 const Array& args,
3671 const ArgumentsDescriptor& arg_names,
3672 const TypeArguments& instantiator_type_args) const;
3673
3674 // Returns a TypeError if the provided arguments don't match the function
3675 // parameter types, null otherwise. Assumes AreValidArguments is called first.
3676 //
3677 // The local function type arguments (_not_ parent function type arguments)
3678 // are also checked against the bounds of the corresponding parameters to
3679 // ensure they are appropriate subtypes if the function is generic.
3680 ObjectPtr DoArgumentTypesMatch(const Array& args,
3681 const ArgumentsDescriptor& arg_names,
3682 const TypeArguments& instantiator_type_args,
3683 const TypeArguments& function_type_args) const;
3684
3685 // Returns true if the type argument count, total argument count and the names
3686 // of optional arguments are valid for calling this function.
3687 // Otherwise, it returns false and the reason (if error_message is not
3688 // nullptr).
3689 bool AreValidArguments(intptr_t num_type_arguments,
3690 intptr_t num_arguments,
3691 const Array& argument_names,
3692 String* error_message) const;
3693 bool AreValidArguments(const ArgumentsDescriptor& args_desc,
3694 String* error_message) const;
3695
3696 // Fully qualified name uniquely identifying the function under gdb and during
3697 // ast printing. The special ':' character, if present, is replaced by '_'.
3698 const char* ToFullyQualifiedCString() const;
3699
3700 const char* ToLibNamePrefixedQualifiedCString() const;
3701
3702 const char* ToQualifiedCString() const;
3703
3704 static constexpr intptr_t maximum_unboxed_parameter_count() {
3705 // Subtracts one that represents the return value
3707 }
3708
3710#if !defined(DART_PRECOMPILED_RUNTIME)
3711 StoreNonPointer(&untag()->unboxed_parameters_info_,
3713#endif // !defined(DART_PRECOMPILED_RUNTIME)
3714 }
3715
3716 void set_unboxed_integer_parameter_at(intptr_t index) const {
3717#if !defined(DART_PRECOMPILED_RUNTIME)
3718 ASSERT(index >= 0 && index < maximum_unboxed_parameter_count());
3719 index++; // position 0 is reserved for the return value
3721 &untag()->unboxed_parameters_info_)
3722 ->SetUnboxedInteger(index);
3723#else
3724 UNREACHABLE();
3725#endif // !defined(DART_PRECOMPILED_RUNTIME)
3726 }
3727
3728 void set_unboxed_double_parameter_at(intptr_t index) const {
3729#if !defined(DART_PRECOMPILED_RUNTIME)
3730 ASSERT(index >= 0 && index < maximum_unboxed_parameter_count());
3731 index++; // position 0 is reserved for the return value
3733 &untag()->unboxed_parameters_info_)
3734 ->SetUnboxedDouble(index);
3735
3736#else
3737 UNREACHABLE();
3738#endif // !defined(DART_PRECOMPILED_RUNTIME)
3739 }
3740
3742#if !defined(DART_PRECOMPILED_RUNTIME)
3744 &untag()->unboxed_parameters_info_)
3745 ->SetUnboxedInteger(0);
3746#else
3747 UNREACHABLE();
3748#endif // !defined(DART_PRECOMPILED_RUNTIME)
3749 }
3750
3752#if !defined(DART_PRECOMPILED_RUNTIME)
3754 &untag()->unboxed_parameters_info_)
3755 ->SetUnboxedDouble(0);
3756
3757#else
3758 UNREACHABLE();
3759#endif // !defined(DART_PRECOMPILED_RUNTIME)
3760 }
3761
3763#if !defined(DART_PRECOMPILED_RUNTIME)
3765 &untag()->unboxed_parameters_info_)
3766 ->SetUnboxedRecord(0);
3767
3768#else
3769 UNREACHABLE();
3770#endif // !defined(DART_PRECOMPILED_RUNTIME)
3771 }
3772
3773 bool is_unboxed_parameter_at(intptr_t index) const {
3774#if !defined(DART_PRECOMPILED_RUNTIME)
3775 ASSERT(index >= 0);
3776 index++; // position 0 is reserved for the return value
3777 return untag()->unboxed_parameters_info_.IsUnboxed(index);
3778#else
3779 return false;
3780#endif // !defined(DART_PRECOMPILED_RUNTIME)
3781 }
3782
3783 bool is_unboxed_integer_parameter_at(intptr_t index) const {
3784#if !defined(DART_PRECOMPILED_RUNTIME)
3785 ASSERT(index >= 0);
3786 index++; // position 0 is reserved for the return value
3787 return untag()->unboxed_parameters_info_.IsUnboxedInteger(index);
3788#else
3789 return false;
3790#endif // !defined(DART_PRECOMPILED_RUNTIME)
3791 }
3792
3793 bool is_unboxed_double_parameter_at(intptr_t index) const {
3794#if !defined(DART_PRECOMPILED_RUNTIME)
3795 ASSERT(index >= 0);
3796 index++; // position 0 is reserved for the return value
3797 return untag()->unboxed_parameters_info_.IsUnboxedDouble(index);
3798#else
3799 return false;
3800#endif // !defined(DART_PRECOMPILED_RUNTIME)
3801 }
3802
3803 bool has_unboxed_return() const {
3804#if !defined(DART_PRECOMPILED_RUNTIME)
3805 return untag()->unboxed_parameters_info_.IsUnboxed(0);
3806#else
3807 return false;
3808#endif // !defined(DART_PRECOMPILED_RUNTIME)
3809 }
3810
3812#if !defined(DART_PRECOMPILED_RUNTIME)
3813 return untag()->unboxed_parameters_info_.IsUnboxedInteger(0);
3814#else
3815 return false;
3816#endif // !defined(DART_PRECOMPILED_RUNTIME)
3817 }
3818
3820#if !defined(DART_PRECOMPILED_RUNTIME)
3821 return untag()->unboxed_parameters_info_.IsUnboxedDouble(0);
3822#else
3823 return false;
3824#endif // !defined(DART_PRECOMPILED_RUNTIME)
3825 }
3826
3828#if !defined(DART_PRECOMPILED_RUNTIME)
3829 return untag()->unboxed_parameters_info_.IsUnboxedRecord(0);
3830#else
3831 return false;
3832#endif // !defined(DART_PRECOMPILED_RUNTIME)
3833 }
3834
3835#if !defined(DART_PRECOMPILED_RUNTIME)
3837 return untag()->unboxed_parameters_info_.HasUnboxedParameters();
3838 }
3839 bool HasUnboxedReturnValue() const { return has_unboxed_return(); }
3840#endif // !defined(DART_PRECOMPILED_RUNTIME)
3841
3843 switch (kind()) {
3844 case UntaggedFunction::kImplicitGetter:
3845 case UntaggedFunction::kImplicitSetter:
3846 case UntaggedFunction::kImplicitStaticGetter:
3847 case UntaggedFunction::kNoSuchMethodDispatcher:
3848 case UntaggedFunction::kInvokeFieldDispatcher:
3849 case UntaggedFunction::kDynamicInvocationForwarder:
3850 return true;
3851 default:
3852 return false;
3853 }
3854 }
3855
3856 // Returns true if this function represents an explicit getter function.
3857 bool IsGetterFunction() const {
3858 return kind() == UntaggedFunction::kGetterFunction;
3859 }
3860
3861 // Returns true if this function represents an implicit getter function.
3863 return kind() == UntaggedFunction::kImplicitGetter;
3864 }
3865
3866 // Returns true if this function represents an implicit static getter
3867 // function.
3869 return kind() == UntaggedFunction::kImplicitStaticGetter;
3870 }
3871
3872 // Returns true if this function represents an explicit setter function.
3873 bool IsSetterFunction() const {
3874 return kind() == UntaggedFunction::kSetterFunction;
3875 }
3876
3877 // Returns true if this function represents an implicit setter function.
3879 return kind() == UntaggedFunction::kImplicitSetter;
3880 }
3881
3882 // Returns true if this function represents an initializer for a static or
3883 // instance field. The function returns the initial value and the caller is
3884 // responsible for setting the field.
3885 bool IsFieldInitializer() const {
3886 return kind() == UntaggedFunction::kFieldInitializer;
3887 }
3888
3889 // Returns true if this function represents a (possibly implicit) closure
3890 // function.
3891 bool IsClosureFunction() const {
3892 UntaggedFunction::Kind k = kind();
3893 return (k == UntaggedFunction::kClosureFunction) ||
3894 (k == UntaggedFunction::kImplicitClosureFunction);
3895 }
3896
3897 // Returns true if this function represents a generated irregexp function.
3898 bool IsIrregexpFunction() const {
3899 return kind() == UntaggedFunction::kIrregexpFunction;
3900 }
3901
3902 // Returns true if this function represents an implicit closure function.
3904 return kind() == UntaggedFunction::kImplicitClosureFunction;
3905 }
3906 static bool IsImplicitClosureFunction(FunctionPtr func) {
3907 return KindOf(func) == UntaggedFunction::kImplicitClosureFunction;
3908 }
3909
3910 // Returns true if this function represents a non implicit closure function.
3912 return IsClosureFunction() && !IsImplicitClosureFunction();
3913 }
3914
3915 // Returns true if this function represents an implicit static closure
3916 // function.
3918 return IsImplicitClosureFunction() && is_static();
3919 }
3920 static bool IsImplicitStaticClosureFunction(FunctionPtr func);
3921
3922 // Returns true if this function represents an implicit instance closure
3923 // function.
3925 return IsImplicitClosureFunction() && !is_static();
3926 }
3927 static bool IsImplicitInstanceClosureFunction(FunctionPtr func);
3928
3929 // Returns true if this function has a parent function.
3930 bool HasParent() const { return parent_function() != Function::null(); }
3931
3932 // Returns true if this function is a local function.
3933 bool IsLocalFunction() const {
3934 return !IsImplicitClosureFunction() && HasParent();
3935 }
3936
3937 // Returns true if this function represents an ffi trampoline.
3939 return kind() == UntaggedFunction::kFfiTrampoline;
3940 }
3941 static bool IsFfiCallbackTrampoline(FunctionPtr function) {
3942 NoSafepointScope no_safepoint;
3943 return function->untag()->kind_tag_.Read<KindBits>() ==
3944 UntaggedFunction::kFfiTrampoline;
3945 }
3946
3947 // Returns true if this function is a closure function
3948 // used to represent ffi call.
3949 bool IsFfiCallClosure() const;
3950
3951 // Returns value of vm:ffi:call-closure pragma.
3952 InstancePtr GetFfiCallClosurePragmaValue() const;
3953
3954 // Returns true for functions which execution can be suspended
3955 // using Suspend/Resume stubs. Such functions have an artificial
3956 // :suspend_state local variable at the fixed location of the frame.
3958 return modifier() != UntaggedFunction::kNoModifier;
3959 }
3960
3961 // Returns true if this function is marked with 'async' modifier.
3962 bool IsAsyncFunction() const {
3963 return modifier() == UntaggedFunction::kAsync;
3964 }
3965
3966 // Returns true if this function is marked with 'sync*' modifier.
3967 bool IsSyncGenerator() const {
3968 return modifier() == UntaggedFunction::kSyncGen;
3969 }
3970
3971 // Returns true if this function is marked with 'async*' modifier.
3972 bool IsAsyncGenerator() const {
3973 return modifier() == UntaggedFunction::kAsyncGen;
3974 }
3975
3976 bool IsTypedDataViewFactory() const;
3977 bool IsUnmodifiableTypedDataViewFactory() const;
3978
3980 ErrorPtr VerifyCallEntryPoint() const;
3981
3983 ErrorPtr VerifyClosurizedEntryPoint() const;
3984
3985 static intptr_t InstanceSize() {
3987 }
3988
3989 static FunctionPtr New(const FunctionType& signature,
3990 const String& name,
3992 bool is_static,
3993 bool is_const,
3994 bool is_abstract,
3995 bool is_external,
3996 bool is_native,
3997 const Object& owner,
3998 TokenPosition token_pos,
3999 Heap::Space space = Heap::kOld);
4000
4001 // Allocates a new Function object representing a closure function
4002 // with given kind - kClosureFunction or kImplicitClosureFunction.
4003 static FunctionPtr NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
4004 const String& name,
4005 const Function& parent,
4006 bool is_static,
4007 TokenPosition token_pos,
4008 const Object& owner);
4009
4010 // Allocates a new Function object representing a closure function.
4011 static FunctionPtr NewClosureFunction(const String& name,
4012 const Function& parent,
4013 TokenPosition token_pos);
4014
4015 // Allocates a new Function object representing an implicit closure function.
4016 static FunctionPtr NewImplicitClosureFunction(const String& name,
4017 const Function& parent,
4018 TokenPosition token_pos);
4019
4020 FunctionPtr CreateMethodExtractor(const String& getter_name) const;
4021 FunctionPtr GetMethodExtractor(const String& getter_name) const;
4022
4023 static bool IsDynamicInvocationForwarderName(const String& name);
4024 static bool IsDynamicInvocationForwarderName(StringPtr name);
4025
4026 static StringPtr DemangleDynamicInvocationForwarderName(const String& name);
4027
4028 static StringPtr CreateDynamicInvocationForwarderName(const String& name);
4029
4030#if !defined(DART_PRECOMPILED_RUNTIME)
4031 FunctionPtr CreateDynamicInvocationForwarder(
4032 const String& mangled_name) const;
4033
4034 FunctionPtr GetDynamicInvocationForwarder(const String& mangled_name) const;
4035#endif
4036
4037 // Slow function, use in asserts to track changes in important library
4038 // functions.
4039 int32_t SourceFingerprint() const;
4040
4041 // Return false and report an error if the fingerprint does not match.
4042 bool CheckSourceFingerprint(int32_t fp, const char* kind = nullptr) const;
4043
4044 // Works with map [deopt-id] -> ICData.
4045 void SaveICDataMap(
4046 const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data,
4047 const Array& edge_counters_array,
4048 const Array& coverage_array) const;
4049 // Uses 'ic_data_array' to populate the table 'deopt_id_to_ic_data'. Clone
4050 // ic_data (array and descriptor) if 'clone_ic_data' is true.
4051 void RestoreICDataMap(ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
4052 bool clone_ic_data) const;
4053
4054 // ic_data_array attached to the function stores edge counters in the
4055 // first element, coverage data array in the second element and the rest
4056 // are ICData objects.
4058 static constexpr intptr_t kEdgeCounters = 0;
4059 static constexpr intptr_t kCoverageData = 1;
4060 static constexpr intptr_t kFirstICData = 2;
4061 };
4062
4063 ArrayPtr ic_data_array() const;
4064 void ClearICDataArray() const;
4065 ICDataPtr FindICData(intptr_t deopt_id) const;
4066
4067 // Coverage data array is a list of pairs:
4068 // element 2 * i + 0 is token position
4069 // element 2 * i + 1 is coverage hit (zero meaning code was not hit)
4070 ArrayPtr GetCoverageArray() const;
4071
4072 // Outputs this function's service ID to the provided JSON object.
4073 void AddFunctionServiceId(const JSONObject& obj) const;
4074
4075 // Sets deopt reason in all ICData-s with given deopt_id.
4076 void SetDeoptReasonForAll(intptr_t deopt_id, ICData::DeoptReasonId reason);
4077
4078 void set_modifier(UntaggedFunction::AsyncModifier value) const;
4079
4080// 'WasCompiled' is true if the function was compiled once in this
4081// VM instantiation. It is independent from presence of type feedback
4082// (ic_data_array) and code, which may be loaded from a snapshot.
4083// 'WasExecuted' is true if the usage counter has ever been positive.
4084// 'ProhibitsInstructionHoisting' is true if this function deoptimized before on
4085// a hoisted instruction.
4086// 'ProhibitsBoundsCheckGeneralization' is true if this function deoptimized
4087// before on a generalized bounds check.
4088// IsDynamicallyOverridden: This function can be overridden in a dynamically
4089// loaded class.
4090#define STATE_BITS_LIST(V) \
4091 V(WasCompiled) \
4092 V(WasExecutedBit) \
4093 V(ProhibitsInstructionHoisting) \
4094 V(ProhibitsBoundsCheckGeneralization) \
4095 V(IsDynamicallyOverridden)
4096
4098#define DECLARE_FLAG_POS(Name) k##Name##Pos,
4100#undef DECLARE_FLAG_POS
4101 };
4102#define DEFINE_FLAG_BIT(Name) \
4103 class Name##Bit : public BitField<uint8_t, bool, k##Name##Pos, 1> {};
4105#undef DEFINE_FLAG_BIT
4106
4107#define DEFINE_FLAG_ACCESSORS(Name) \
4108 void Set##Name(bool value) const { \
4109 set_state_bits(Name##Bit::update(value, state_bits())); \
4110 } \
4111 bool Name() const { return Name##Bit::decode(state_bits()); }
4113#undef DEFINE_FLAG_ACCESSORS
4114
4115 void SetUsageCounter(intptr_t value) const {
4116 if (usage_counter() > 0) {
4117 SetWasExecuted(true);
4118 }
4119 set_usage_counter(value);
4120 }
4121
4122 bool WasExecuted() const { return (usage_counter() > 0) || WasExecutedBit(); }
4123
4124 void SetWasExecuted(bool value) const { SetWasExecutedBit(value); }
4125
4126 static intptr_t data_offset() { return OFFSET_OF(UntaggedFunction, data_); }
4127
4128 static intptr_t kind_tag_offset() {
4129 return OFFSET_OF(UntaggedFunction, kind_tag_);
4130 }
4131
4132 // static: Considered during class-side or top-level resolution rather than
4133 // instance-side resolution.
4134 // const: Valid target of a const constructor call.
4135 // abstract: Skipped during instance-side resolution.
4136 // reflectable: Enumerated by mirrors, invocable by mirrors. False for private
4137 // functions of dart: libraries.
4138 // debuggable: Valid location of a breakpoint. Synthetic code is not
4139 // debuggable.
4140 // visible: Frame is included in stack traces. Synthetic code such as
4141 // dispatchers is not visible. Synthetic code that can trigger
4142 // exceptions such as the outer async functions that create Futures
4143 // is visible.
4144 // intrinsic: Has a hand-written assembly prologue.
4145 // inlinable: Candidate for inlining. False for functions with features we
4146 // don't support during inlining (e.g., optional parameters),
4147 // functions which are too big, etc.
4148 // native: Bridge to C/C++ code.
4149 // external: Just a declaration that expects to be defined in another patch
4150 // file.
4151 // polymorphic_target: A polymorphic method.
4152 // has_pragma: Has a @pragma decoration.
4153 // no_such_method_forwarder: A stub method that just calls noSuchMethod.
4154
4155// Bits that are set when function is created, don't have to worry about
4156// concurrent updates.
4157#define FOR_EACH_FUNCTION_KIND_BIT(V) \
4158 V(Static, is_static) \
4159 V(Const, is_const) \
4160 V(Abstract, is_abstract) \
4161 V(Reflectable, is_reflectable) \
4162 V(Visible, is_visible) \
4163 V(Debuggable, is_debuggable) \
4164 V(Intrinsic, is_intrinsic) \
4165 V(Native, is_native) \
4166 V(External, is_external) \
4167 V(PolymorphicTarget, is_polymorphic_target) \
4168 V(HasPragma, has_pragma) \
4169 V(IsSynthetic, is_synthetic) \
4170 V(IsExtensionMember, is_extension_member) \
4171 V(IsExtensionTypeMember, is_extension_type_member) \
4172 V(IsRedirectingFactory, is_redirecting_factory)
4173// Bit that is updated after function is constructed, has to be updated in
4174// concurrent-safe manner.
4175#define FOR_EACH_FUNCTION_VOLATILE_KIND_BIT(V) V(Inlinable, is_inlinable)
4176
4177#define DEFINE_ACCESSORS(name, accessor_name) \
4178 void set_##accessor_name(bool value) const { \
4179 untag()->kind_tag_.UpdateUnsynchronized<name##Bit>(value); \
4180 } \
4181 bool accessor_name() const { return untag()->kind_tag_.Read<name##Bit>(); }
4183#undef DEFINE_ACCESSORS
4184
4185 static bool is_visible(FunctionPtr f) {
4186 return f.untag()->kind_tag_.Read<VisibleBit>();
4187 }
4188
4189#define DEFINE_ACCESSORS(name, accessor_name) \
4190 void set_##accessor_name(bool value) const { \
4191 untag()->kind_tag_.UpdateBool<name##Bit>(value); \
4192 } \
4193 bool accessor_name() const { return untag()->kind_tag_.Read<name##Bit>(); }
4195#undef DEFINE_ACCESSORS
4196
4197 // optimizable: Candidate for going through the optimizing compiler. False for
4198 // some functions known to be execute infrequently and functions
4199 // which have been de-optimized too many times.
4200 bool is_optimizable() const {
4201#if defined(DART_PRECOMPILED_RUNTIME)
4202 return false;
4203#else
4204 return untag()->packed_fields_.Read<UntaggedFunction::PackedOptimizable>();
4205#endif
4206 }
4207 void set_is_optimizable(bool value) const {
4208#if defined(DART_PRECOMPILED_RUNTIME)
4209 UNREACHABLE();
4210#else
4211 untag()->packed_fields_.UpdateBool<UntaggedFunction::PackedOptimizable>(
4212 value);
4213#endif
4214 }
4215
4217 kKindTagPos = 0,
4218 kKindTagSize = 5,
4219 kRecognizedTagPos = kKindTagPos + kKindTagSize,
4220 kRecognizedTagSize = 9,
4221 kModifierPos = kRecognizedTagPos + kRecognizedTagSize,
4222 kModifierSize = 2,
4223 kLastModifierBitPos = kModifierPos + (kModifierSize - 1),
4224// Single bit sized fields start here.
4225#define DECLARE_BIT(name, _) k##name##Bit,
4228#undef DECLARE_BIT
4229 kNumTagBits
4231
4233 (1 << kRecognizedTagSize));
4234 COMPILE_ASSERT(kNumTagBits <=
4235 (kBitsPerByte *
4236 sizeof(decltype(UntaggedFunction::kind_tag_))));
4237
4238#define ASSERT_FUNCTION_KIND_IN_RANGE(Name) \
4239 COMPILE_ASSERT(UntaggedFunction::k##Name < (1 << kKindTagSize));
4241#undef ASSERT_FUNCTION_KIND_IN_RANGE
4242
4243 class KindBits : public BitField<uint32_t,
4244 UntaggedFunction::Kind,
4245 kKindTagPos,
4246 kKindTagSize> {};
4247
4248 class RecognizedBits : public BitField<uint32_t,
4249 MethodRecognizer::Kind,
4250 kRecognizedTagPos,
4251 kRecognizedTagSize> {};
4252 class ModifierBits : public BitField<uint32_t,
4253 UntaggedFunction::AsyncModifier,
4254 kModifierPos,
4255 kModifierSize> {};
4256
4257#define DEFINE_BIT(name, _) \
4258 class name##Bit : public BitField<uint32_t, bool, k##name##Bit, 1> {};
4261#undef DEFINE_BIT
4262
4263 private:
4264 enum class EvalFunctionData {
4265 kScript,
4266 kKernelProgramInfo,
4267 kKernelLibraryIndex,
4268 kLength,
4269 };
4270 enum NativeFunctionData {
4271 kNativeName,
4272 kTearOff,
4273 kLength,
4274 };
4275
4276 void set_ic_data_array(const Array& value) const;
4277 void set_name(const String& value) const;
4278 void set_kind(UntaggedFunction::Kind value) const;
4279 void set_parent_function(const Function& value) const;
4280 FunctionPtr implicit_closure_function() const;
4281 void set_implicit_closure_function(const Function& value) const;
4282 ClosurePtr implicit_static_closure() const;
4283 void set_implicit_static_closure(const Closure& closure) const;
4284 ScriptPtr eval_script() const;
4285 void set_eval_script(const Script& value) const;
4286 void set_num_optional_parameters(intptr_t value) const; // Encoded value.
4287 void set_kind_tag(uint32_t value) const;
4288 bool is_eval_function() const;
4289
4290#if !defined(DART_PRECOMPILED_RUNTIME)
4291 ArrayPtr positional_parameter_names() const {
4292 return untag()->positional_parameter_names();
4293 }
4294 void set_positional_parameter_names(const Array& value) const;
4295#endif
4296
4297 ObjectPtr data() const { return untag()->data<std::memory_order_acquire>(); }
4298 void set_data(const Object& value) const;
4299
4300 static FunctionPtr New(Heap::Space space = Heap::kOld);
4301
4303 friend class Class;
4304 friend class Parser; // For set_eval_script.
4305 // UntaggedFunction::VisitFunctionPointers accesses the private constructor of
4306 // Function.
4307 friend class UntaggedFunction;
4308 friend class ClassFinalizer; // To reset parent_function.
4309 friend class Type; // To adjust parent_function.
4310 friend class Precompiler; // To access closure data.
4311 friend class ProgramVisitor; // For set_parameter_types/names.
4312};
4313
4314class ClosureData : public Object {
4315 public:
4316 static intptr_t InstanceSize() {
4318 }
4319
4320 static intptr_t packed_fields_offset() {
4321 return OFFSET_OF(UntaggedClosureData, packed_fields_);
4322 }
4323
4325
4326 static constexpr uint8_t kNoAwaiterLinkDepth =
4327 UntaggedClosureData::kNoAwaiterLinkDepth;
4328
4329 private:
4330 ContextScopePtr context_scope() const { return untag()->context_scope(); }
4331 void set_context_scope(const ContextScope& value) const;
4332
4333 void set_packed_fields(uint32_t value) const {
4334 untag()->packed_fields_ = value;
4335 }
4336
4337 Function::AwaiterLink awaiter_link() const;
4338 void set_awaiter_link(Function::AwaiterLink link) const;
4339
4340 // Enclosing function of this local function.
4341 PRECOMPILER_WSR_FIELD_DECLARATION(Function, parent_function)
4342
4343 ClosurePtr implicit_static_closure() const {
4344 return untag()->closure<std::memory_order_acquire>();
4345 }
4346 void set_implicit_static_closure(const Closure& closure) const;
4347
4348 static InstantiationMode DefaultTypeArgumentsInstantiationMode(
4349 ClosureDataPtr ptr) {
4350 return ptr->untag()->packed_fields_.Read<PackedInstantiationMode>();
4351 }
4352 InstantiationMode default_type_arguments_instantiation_mode() const {
4353 return DefaultTypeArgumentsInstantiationMode(ptr());
4354 }
4355 void set_default_type_arguments_instantiation_mode(
4356 InstantiationMode value) const;
4357
4358 static ClosureDataPtr New();
4359
4361 friend class Class;
4362 friend class Function;
4363 friend class Precompiler; // To wrap parent functions in WSRs.
4364};
4365
4367 kAlways,
4368 kNever,
4371 kCallOnly
4372};
4373
4375 public:
4376 static intptr_t InstanceSize() {
4378 }
4379
4380 private:
4381 FunctionTypePtr c_signature() const { return untag()->c_signature(); }
4382 void set_c_signature(const FunctionType& value) const;
4383
4384 FunctionPtr callback_target() const { return untag()->callback_target(); }
4385 void set_callback_target(const Function& value) const;
4386
4387 InstancePtr callback_exceptional_return() const {
4388 return untag()->callback_exceptional_return();
4389 }
4390 void set_callback_exceptional_return(const Instance& value) const;
4391
4392 FfiCallbackKind ffi_function_kind() const {
4393 return static_cast<FfiCallbackKind>(untag()->ffi_function_kind_);
4394 }
4395 void set_ffi_function_kind(FfiCallbackKind kind) const;
4396
4397 int32_t callback_id() const { return untag()->callback_id_; }
4398 void set_callback_id(int32_t value) const;
4399
4400 static FfiTrampolineDataPtr New();
4401
4402 FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
4403 friend class Class;
4404 friend class Function;
4405};
4406
4407class Field : public Object {
4408 public:
4409 // The field that this field was cloned from, or this field itself if it isn't
4410 // a clone. The purpose of cloning is that the fields the background compiler
4411 // sees are consistent.
4412 FieldPtr Original() const;
4413
4414 // Set the original field that this field was cloned from.
4415 void SetOriginal(const Field& value) const;
4416
4417 // Returns whether this field is an original or a clone.
4418 bool IsOriginal() const {
4419 if (IsNull()) {
4420 return true;
4421 }
4422 NoSafepointScope no_safepoint;
4423 return !untag()->owner()->IsField();
4424 }
4425
4426 // Returns a field cloned from 'this'. 'this' is set as the
4427 // original field of result.
4428 FieldPtr CloneFromOriginal() const;
4429
4430 StringPtr name() const { return untag()->name(); }
4431 StringPtr UserVisibleName() const; // Same as scrubbed name.
4432 const char* UserVisibleNameCString() const;
4433 virtual StringPtr DictionaryName() const { return name(); }
4434
4435 uint16_t kind_bits() const {
4436 return LoadNonPointer<uint16_t, std::memory_order_acquire>(
4437 &untag()->kind_bits_);
4438 }
4439
4440 bool is_static() const { return StaticBit::decode(kind_bits()); }
4441 bool is_instance() const { return !is_static(); }
4442 bool is_final() const { return FinalBit::decode(kind_bits()); }
4443 bool is_const() const { return ConstBit::decode(kind_bits()); }
4444 bool is_late() const { return IsLateBit::decode(kind_bits()); }
4445 bool is_extension_member() const {
4446 return IsExtensionMemberBit::decode(kind_bits());
4447 }
4449 return IsExtensionTypeMemberBit::decode(kind_bits());
4450 }
4451 bool needs_load_guard() const {
4452 return NeedsLoadGuardBit::decode(kind_bits());
4453 }
4454 bool is_reflectable() const { return ReflectableBit::decode(kind_bits()); }
4455 void set_is_reflectable(bool value) const {
4456 ASSERT(IsOriginal());
4457 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4458 set_kind_bits(ReflectableBit::update(value, untag()->kind_bits_));
4459 }
4460
4463 }
4465 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4466 set_kind_bits(InitializerChangedAfterInitializationBit::update(
4467 value, untag()->kind_bits_));
4468 }
4469
4470 bool has_pragma() const { return HasPragmaBit::decode(kind_bits()); }
4471 void set_has_pragma(bool value) const {
4472 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4473 set_kind_bits(HasPragmaBit::update(value, untag()->kind_bits_));
4474 }
4475
4476 bool is_covariant() const { return CovariantBit::decode(kind_bits()); }
4477 void set_is_covariant(bool value) const {
4478 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4479 set_kind_bits(CovariantBit::update(value, untag()->kind_bits_));
4480 }
4481
4483 return GenericCovariantImplBit::decode(kind_bits());
4484 }
4486 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4487 set_kind_bits(GenericCovariantImplBit::update(value, untag()->kind_bits_));
4488 }
4489
4490 void set_is_shared(bool value) const {
4491 set_kind_bits(SharedBit::update(value, untag()->kind_bits_));
4492 }
4493 bool is_shared() const { return SharedBit::decode(kind_bits()); }
4494
4495 intptr_t kernel_offset() const {
4496#if defined(DART_PRECOMPILED_RUNTIME)
4497 return 0;
4498#else
4499 return untag()->kernel_offset_;
4500#endif
4501 }
4502
4503 void set_kernel_offset(intptr_t value) const {
4504#if defined(DART_PRECOMPILED_RUNTIME)
4505 UNREACHABLE();
4506#else
4507 ASSERT(value >= 0);
4508 StoreNonPointer(&untag()->kernel_offset_, value);
4509#endif
4510 }
4511
4512 void InheritKernelOffsetFrom(const Field& src) const;
4513
4514 TypedDataViewPtr KernelLibrary() const;
4515 intptr_t KernelLibraryOffset() const;
4516 intptr_t KernelLibraryIndex() const;
4517
4518 // Called during class finalization.
4519 inline void SetOffset(intptr_t host_offset_in_bytes,
4520 intptr_t target_offset_in_bytes) const;
4521
4522 inline intptr_t HostOffset() const;
4524 return OFFSET_OF(UntaggedField, host_offset_or_field_id_);
4525 }
4526
4527 inline intptr_t TargetOffset() const;
4528 static inline intptr_t TargetOffsetOf(FieldPtr field);
4529
4530 ObjectPtr StaticConstFieldValue() const;
4531 void SetStaticConstFieldValue(const Instance& value,
4532 bool assert_initializing_store = true) const;
4533
4534 inline ObjectPtr StaticValue() const;
4535 void SetStaticValue(const Object& value) const;
4536
4537 inline intptr_t field_id() const;
4538 inline void set_field_id(intptr_t field_id) const;
4539 inline void set_field_id_unsafe(intptr_t field_id) const;
4540
4541 ClassPtr Owner() const;
4542 ScriptPtr Script() const;
4543#if !defined(DART_PRECOMPILED_RUNTIME)
4544 KernelProgramInfoPtr KernelProgramInfo() const;
4545#endif
4546 ObjectPtr RawOwner() const;
4547
4548 uint32_t Hash() const;
4549
4550 AbstractTypePtr type() const { return untag()->type(); }
4551 // Used by class finalizer, otherwise initialized in constructor.
4552 void SetFieldType(const AbstractType& value) const;
4553 void SetFieldTypeSafe(const AbstractType& value) const;
4554
4556 ErrorPtr VerifyEntryPoint(EntryPointPragma kind) const;
4557
4558 static intptr_t InstanceSize() {
4559 return RoundedAllocationSize(sizeof(UntaggedField));
4560 }
4561
4562 static FieldPtr New(const String& name,
4563 bool is_static,
4564 bool is_final,
4565 bool is_const,
4566 bool is_reflectable,
4567 bool is_late,
4568 const Object& owner,
4569 const AbstractType& type,
4570 TokenPosition token_pos,
4571 TokenPosition end_token_pos);
4572
4573 static FieldPtr NewTopLevel(const String& name,
4574 bool is_final,
4575 bool is_const,
4576 bool is_late,
4577 const Object& owner,
4578 TokenPosition token_pos,
4579 TokenPosition end_token_pos);
4580
4581 // Allocate new field object, clone values from this field. The
4582 // original is specified.
4583 FieldPtr Clone(const Field& original) const;
4584
4585 static intptr_t kind_bits_offset() {
4586 return OFFSET_OF(UntaggedField, kind_bits_);
4587 }
4588
4589 TokenPosition token_pos() const { return untag()->token_pos_; }
4590 TokenPosition end_token_pos() const { return untag()->end_token_pos_; }
4591
4592 int32_t SourceFingerprint() const;
4593
4594 StringPtr InitializingExpression() const;
4595
4597 return HasNontrivialInitializerBit::decode(kind_bits());
4598 }
4599 // Called by parser after allocating field.
4601 bool has_nontrivial_initializer) const {
4602 ASSERT(IsOriginal());
4603 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4604 set_kind_bits(HasNontrivialInitializerBit::update(
4605 has_nontrivial_initializer, untag()->kind_bits_));
4606 }
4607 void set_has_nontrivial_initializer(bool has_nontrivial_initializer) const {
4609 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4610 set_has_nontrivial_initializer_unsafe(has_nontrivial_initializer);
4611 }
4612
4613 bool has_initializer() const {
4614 return HasInitializerBit::decode(kind_bits());
4615 }
4616 // Called by parser after allocating field.
4617 void set_has_initializer_unsafe(bool has_initializer) const {
4618 ASSERT(IsOriginal());
4619 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4620 set_kind_bits(
4621 HasInitializerBit::update(has_initializer, untag()->kind_bits_));
4622 }
4623 void set_has_initializer(bool has_initializer) const {
4625 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4626 set_has_initializer_unsafe(has_initializer);
4627 }
4628
4630 return has_initializer() && !has_nontrivial_initializer();
4631 }
4632
4635 LoadNonPointer<int8_t, std::memory_order_relaxed>(
4636 &untag()->static_type_exactness_state_));
4637 }
4638
4641 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4642 set_static_type_exactness_state_unsafe(state);
4643 }
4644
4647 StoreNonPointer<int8_t, int8_t, std::memory_order_relaxed>(
4648 &untag()->static_type_exactness_state_, state.Encode());
4649 }
4650
4652 return OFFSET_OF(UntaggedField, static_type_exactness_state_);
4653 }
4654
4655 // Return class id that any non-null value read from this field is guaranteed
4656 // to have or kDynamicCid if such class id is not known.
4657 // Stores to this field must update this information hence the name.
4658 intptr_t guarded_cid() const;
4659
4660 void set_guarded_cid(intptr_t cid) const {
4662 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4663 set_guarded_cid_unsafe(cid);
4664 }
4665 void set_guarded_cid_unsafe(intptr_t cid) const {
4666 StoreNonPointer<ClassIdTagType, ClassIdTagType, std::memory_order_relaxed>(
4667 &untag()->guarded_cid_, cid);
4668 }
4669 static intptr_t guarded_cid_offset() {
4670 return OFFSET_OF(UntaggedField, guarded_cid_);
4671 }
4672 // Return the list length that any list stored in this field is guaranteed
4673 // to have. If length is kUnknownFixedLength the length has not
4674 // been determined. If length is kNoFixedLength this field has multiple
4675 // list lengths associated with it and cannot be predicted.
4676 intptr_t guarded_list_length() const;
4677 void set_guarded_list_length_unsafe(intptr_t list_length) const;
4678 void set_guarded_list_length(intptr_t list_length) const {
4680 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4681 set_guarded_list_length_unsafe(list_length);
4682 }
4683 static intptr_t guarded_list_length_offset() {
4684 return OFFSET_OF(UntaggedField, guarded_list_length_);
4685 }
4686 intptr_t guarded_list_length_in_object_offset() const;
4687 void set_guarded_list_length_in_object_offset_unsafe(intptr_t offset) const;
4690 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4691 set_guarded_list_length_in_object_offset_unsafe(offset);
4692 }
4694 return OFFSET_OF(UntaggedField, guarded_list_length_in_object_offset_);
4695 }
4696
4697 bool needs_length_check() const {
4698 const bool r = guarded_list_length() >= Field::kUnknownFixedLength;
4699 ASSERT(!r || is_final());
4700 return r;
4701 }
4702
4703 bool NeedsSetter() const;
4704 bool NeedsGetter() const;
4705
4707 return needs_load_guard() || (is_late() && !has_trivial_initializer());
4708 }
4709
4710 const char* GuardedPropertiesAsCString() const;
4711
4712 bool is_unboxed() const { return UnboxedBit::decode(kind_bits()); }
4713
4714 // Field unboxing decisions are based either on static types (JIT) or
4715 // inferred types (AOT). See the callers of this function.
4716 void set_is_unboxed_unsafe(bool b) const {
4717 set_kind_bits(UnboxedBit::update(b, untag()->kind_bits_));
4718 }
4719
4720 void set_is_unboxed(bool b) const {
4722 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4723 set_is_unboxed_unsafe(b);
4724 }
4725
4726 enum {
4727 kUnknownLengthOffset = -1,
4728 kUnknownFixedLength = -1,
4729 kNoFixedLength = -2,
4730 };
4731 void set_is_late(bool value) const {
4732 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4733 set_kind_bits(IsLateBit::update(value, untag()->kind_bits_));
4734 }
4736 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4737 set_kind_bits(IsExtensionMemberBit::update(value, untag()->kind_bits_));
4738 }
4740 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4741 set_kind_bits(IsExtensionTypeMemberBit::update(value, untag()->kind_bits_));
4742 }
4743 void set_needs_load_guard(bool value) const {
4744 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4745 set_kind_bits(NeedsLoadGuardBit::update(value, untag()->kind_bits_));
4746 }
4747 // Returns false if any value read from this field is guaranteed to be
4748 // not null.
4749 // Internally we is_nullable_ field contains either kNullCid (nullable) or
4750 // kIllegalCid (non-nullable) instead of boolean. This is done to simplify
4751 // guarding sequence in the generated code.
4752 bool is_nullable() const;
4753 void set_is_nullable(bool val) const {
4755 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4756 set_is_nullable_unsafe(val);
4757 }
4758 bool is_nullable_unsafe() const {
4759 return LoadNonPointer<ClassIdTagType, std::memory_order_relaxed>(
4760 &untag()->is_nullable_) == kNullCid;
4761 }
4762 void set_is_nullable_unsafe(bool val) const {
4763 StoreNonPointer<ClassIdTagType, ClassIdTagType, std::memory_order_relaxed>(
4764 &untag()->is_nullable_, val ? kNullCid : kIllegalCid);
4765 }
4766 static intptr_t is_nullable_offset() {
4767 return OFFSET_OF(UntaggedField, is_nullable_);
4768 }
4769
4770 // Record store of the given value into this field. May trigger
4771 // deoptimization of dependent optimized code.
4772 void RecordStore(const Object& value) const;
4773
4774 void InitializeGuardedListLengthInObjectOffset(bool unsafe = false) const;
4775
4776 // Return the list of optimized code objects that were optimized under
4777 // assumptions about guarded class id and nullability of this field.
4778 // These code objects must be deoptimized when field's properties change.
4779 // Code objects are held weakly via an indirection through WeakProperty.
4780 WeakArrayPtr dependent_code() const;
4781 void set_dependent_code(const WeakArray& array) const;
4782
4783 // Add the given code object to the list of dependent ones.
4784 void RegisterDependentCode(const Code& code) const;
4785
4786 // Deoptimize all dependent code objects.
4787 void DeoptimizeDependentCode(bool are_mutators_stopped = false) const;
4788
4789 // Used by background compiler to check consistency of field copy with its
4790 // original.
4791 bool IsConsistentWith(const Field& field) const;
4792
4793 bool IsUninitialized() const;
4794
4795 // Run initializer and set field value.
4797 InitializeInstance(const Instance& instance) const;
4798 DART_WARN_UNUSED_RESULT ErrorPtr InitializeStatic() const;
4799
4800 // Run initializer only.
4801 DART_WARN_UNUSED_RESULT ObjectPtr EvaluateInitializer() const;
4802
4803 FunctionPtr EnsureInitializerFunction() const;
4804 FunctionPtr InitializerFunction() const {
4805 return untag()->initializer_function<std::memory_order_acquire>();
4806 }
4807 void SetInitializerFunction(const Function& initializer) const;
4808 bool HasInitializerFunction() const;
4810 return OFFSET_OF(UntaggedField, initializer_function_);
4811 }
4812
4813 // For static fields only. Constructs a closure that gets/sets the
4814 // field value.
4815 InstancePtr GetterClosure() const;
4816 InstancePtr SetterClosure() const;
4817 InstancePtr AccessorClosure(bool make_setter) const;
4818
4819 // Constructs getter and setter names for fields and vice versa.
4820 static StringPtr GetterName(const String& field_name);
4821 static StringPtr GetterSymbol(const String& field_name);
4822 // Returns String::null() if getter symbol does not exist.
4823 static StringPtr LookupGetterSymbol(const String& field_name);
4824 static StringPtr SetterName(const String& field_name);
4825 static StringPtr SetterSymbol(const String& field_name);
4826 // Returns String::null() if setter symbol does not exist.
4827 static StringPtr LookupSetterSymbol(const String& field_name);
4828 static StringPtr NameFromGetter(const String& getter_name);
4829 static StringPtr NameFromSetter(const String& setter_name);
4830 static StringPtr NameFromInit(const String& init_name);
4831 static bool IsGetterName(const String& function_name);
4832 static bool IsSetterName(const String& function_name);
4833 static bool IsInitName(const String& function_name);
4834
4835 private:
4836 static void InitializeNew(const Field& result,
4837 const String& name,
4838 bool is_static,
4839 bool is_final,
4840 bool is_const,
4841 bool is_reflectable,
4842 bool is_late,
4843 const Object& owner,
4844 TokenPosition token_pos,
4845 TokenPosition end_token_pos);
4846 friend class StoreFieldInstr; // Generated code access to bit field.
4847
4848 enum {
4849 kConstBit = 0,
4850 kStaticBit,
4851 kFinalBit,
4852 kHasNontrivialInitializerBit,
4853 kUnboxedBit,
4854 kReflectableBit,
4855 kInitializerChangedAfterInitializationBit,
4856 kHasPragmaBit,
4857 kCovariantBit,
4858 kGenericCovariantImplBit,
4859 kIsLateBit,
4860 kIsExtensionMemberBit,
4861 kIsExtensionTypeMemberBit,
4862 kNeedsLoadGuardBit,
4863 kHasInitializerBit,
4864 kSharedBit,
4865 };
4866 class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
4867 class StaticBit : public BitField<uint16_t, bool, kStaticBit, 1> {};
4868 class FinalBit : public BitField<uint16_t, bool, kFinalBit, 1> {};
4869 class HasNontrivialInitializerBit
4870 : public BitField<uint16_t, bool, kHasNontrivialInitializerBit, 1> {};
4871 class UnboxedBit : public BitField<uint16_t, bool, kUnboxedBit, 1> {};
4872 class ReflectableBit : public BitField<uint16_t, bool, kReflectableBit, 1> {};
4873 class InitializerChangedAfterInitializationBit
4874 : public BitField<uint16_t,
4875 bool,
4876 kInitializerChangedAfterInitializationBit,
4877 1> {};
4878 class HasPragmaBit : public BitField<uint16_t, bool, kHasPragmaBit, 1> {};
4879 class CovariantBit : public BitField<uint16_t, bool, kCovariantBit, 1> {};
4880 class GenericCovariantImplBit
4881 : public BitField<uint16_t, bool, kGenericCovariantImplBit, 1> {};
4882 class IsLateBit : public BitField<uint16_t, bool, kIsLateBit, 1> {};
4883 class IsExtensionMemberBit
4884 : public BitField<uint16_t, bool, kIsExtensionMemberBit, 1> {};
4885 class IsExtensionTypeMemberBit
4886 : public BitField<uint16_t, bool, kIsExtensionTypeMemberBit, 1> {};
4887 class NeedsLoadGuardBit
4888 : public BitField<uint16_t, bool, kNeedsLoadGuardBit, 1> {};
4889 class HasInitializerBit
4890 : public BitField<uint16_t, bool, kHasInitializerBit, 1> {};
4891 class SharedBit : public BitField<uint16_t, bool, kSharedBit, 1> {};
4892
4893 // Force this field's guard to be dynamic and deoptimize dependent code.
4894 void ForceDynamicGuardedCidAndLength() const;
4895
4896 void set_name(const String& value) const;
4897 void set_is_static(bool is_static) const {
4898 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4899 set_kind_bits(StaticBit::update(is_static, untag()->kind_bits_));
4900 }
4901 void set_is_final(bool is_final) const {
4902 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4903 set_kind_bits(FinalBit::update(is_final, untag()->kind_bits_));
4904 }
4905 void set_is_const(bool value) const {
4906 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4907 set_kind_bits(ConstBit::update(value, untag()->kind_bits_));
4908 }
4909 void set_owner(const Object& value) const { untag()->set_owner(value.ptr()); }
4910 void set_token_pos(TokenPosition token_pos) const {
4911 StoreNonPointer(&untag()->token_pos_, token_pos);
4912 }
4913 void set_end_token_pos(TokenPosition token_pos) const {
4914 StoreNonPointer(&untag()->end_token_pos_, token_pos);
4915 }
4916 void set_kind_bits(uint16_t value) const {
4917 StoreNonPointer<uint16_t, uint16_t, std::memory_order_release>(
4918 &untag()->kind_bits_, value);
4919 }
4920
4921 static FieldPtr New();
4922
4924 friend class Class;
4925 friend class UntaggedField;
4928};
4929
4930class Script : public Object {
4931 public:
4932 StringPtr url() const { return untag()->url(); }
4933 void set_url(const String& value) const;
4934
4935 // The actual url which was loaded from disk, if provided by the embedder.
4936 StringPtr resolved_url() const;
4937 bool HasSource() const;
4938 StringPtr Source() const;
4939 bool IsPartOfDartColonLibrary() const;
4940
4941 GrowableObjectArrayPtr GenerateLineNumberArray() const;
4942
4943 intptr_t line_offset() const { return 0; }
4944 intptr_t col_offset() const { return 0; }
4945 // Returns the max real token position for this script, or kNoSource
4946 // if there is no line starts information.
4947 TokenPosition MaxPosition() const;
4948
4949 // The load time in milliseconds since epoch.
4950 int64_t load_timestamp() const { return untag()->load_timestamp_; }
4951
4952#if !defined(DART_PRECOMPILED_RUNTIME)
4953 // Initializes thie script object from a kernel file.
4954 void InitializeFromKernel(const KernelProgramInfo& info,
4955 intptr_t script_index,
4956 const TypedData& line_starts,
4957 const TypedDataView& constant_coverage) const;
4958#endif
4959
4960 // The index of this script into the [KernelProgramInfo] object's source
4961 // table.
4962 intptr_t kernel_script_index() const { return untag()->kernel_script_index_; }
4963
4964 static intptr_t line_starts_offset() {
4965 return OFFSET_OF(UntaggedScript, line_starts_);
4966 }
4967
4968 TypedDataPtr line_starts() const;
4969
4970#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
4971 TypedDataViewPtr constant_coverage() const;
4972#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
4973
4974 LibraryPtr FindLibrary() const;
4975 StringPtr GetLine(intptr_t line_number, Heap::Space space = Heap::kNew) const;
4976 StringPtr GetSnippet(intptr_t from_line,
4977 intptr_t from_column,
4978 intptr_t to_line,
4979 intptr_t to_column) const;
4980
4981 // For real token positions when line starts are available, returns whether or
4982 // not a GetTokenLocation call would succeed. Returns true for non-real token
4983 // positions or if there is no line starts information.
4984 bool IsValidTokenPosition(TokenPosition token_pos) const;
4985
4986 // Returns whether a line and column could be computed for the given token
4987 // position and, if so, sets *line and *column (if not nullptr).
4988 bool GetTokenLocation(const TokenPosition& token_pos,
4989 intptr_t* line,
4990 intptr_t* column = nullptr) const;
4991
4992 // Returns the length of the token at the given position. If the length cannot
4993 // be determined, returns a negative value.
4994 intptr_t GetTokenLength(const TokenPosition& token_pos) const;
4995
4996 // Returns whether any tokens were found for the given line. When found,
4997 // *first_token_index and *last_token_index are set to the first and
4998 // last token on the line, respectively.
4999 bool TokenRangeAtLine(intptr_t line_number,
5000 TokenPosition* first_token_index,
5001 TokenPosition* last_token_index) const;
5002
5003 static intptr_t InstanceSize() {
5004 return RoundedAllocationSize(sizeof(UntaggedScript));
5005 }
5006
5007 static ScriptPtr New(const String& url, const String& source);
5008
5009 static ScriptPtr New(const String& url,
5010 const String& resolved_url,
5011 const String& source);
5012
5013#if !defined(DART_PRECOMPILED_RUNTIME)
5014 void LoadSourceFromKernel(const uint8_t* kernel_buffer,
5015 intptr_t kernel_buffer_len) const;
5016#endif // !defined(DART_PRECOMPILED_RUNTIME)
5017
5018 void CollectTokenPositionsFor() const;
5019 ArrayPtr CollectConstConstructorCoverageFrom() const;
5020
5021 private:
5022 KernelProgramInfoPtr kernel_program_info() const {
5023 return untag()->kernel_program_info();
5024 }
5025
5026 void set_debug_positions(const Array& value) const;
5027
5028#if !defined(DART_PRECOMPILED_RUNTIME)
5029 bool HasCachedMaxPosition() const;
5030
5031 void SetHasCachedMaxPosition(bool value) const;
5032 void SetCachedMaxPosition(intptr_t value) const;
5033#endif // !defined(DART_PRECOMPILED_RUNTIME)
5034
5035 void set_resolved_url(const String& value) const;
5036 void set_source(const String& value) const;
5037 void set_load_timestamp(int64_t value) const;
5038 ArrayPtr debug_positions() const;
5039
5041 friend class Class;
5042 friend class Precompiler;
5043};
5044
5046 public:
5047 explicit DictionaryIterator(const Library& library);
5048
5049 bool HasNext() const { return next_ix_ < size_; }
5050
5051 // Returns next non-null raw object.
5052 ObjectPtr GetNext();
5053
5054 private:
5055 void MoveToNextObject();
5056
5057 const Array& array_;
5058 const int size_; // Number of elements to iterate over.
5059 int next_ix_; // Index of next element.
5060
5063};
5064
5066 public:
5068 // TODO(hausner): fix call sites that use kIteratePrivate. There is only
5069 // one top-level class per library left, not an array to iterate over.
5071 kNoIteratePrivate
5073
5074 ClassDictionaryIterator(const Library& library,
5075 IterationKind kind = kNoIteratePrivate);
5076
5077 bool HasNext() const {
5078 return (next_ix_ < size_) || !toplevel_class_.IsNull();
5079 }
5080
5081 // Returns a non-null raw class.
5082 ClassPtr GetNextClass();
5083
5084 private:
5085 void MoveToNextClass();
5086
5087 Class& toplevel_class_;
5088
5090};
5091
5092class Library : public Object {
5093 public:
5094 StringPtr name() const { return untag()->name(); }
5095 void SetName(const String& name) const;
5096
5097 StringPtr url() const { return untag()->url(); }
5098 static StringPtr UrlOf(LibraryPtr lib) { return lib->untag()->url(); }
5099 StringPtr private_key() const { return untag()->private_key(); }
5100 bool LoadNotStarted() const {
5101 return untag()->load_state_ == UntaggedLibrary::kAllocated;
5102 }
5103 bool LoadRequested() const {
5104 return untag()->load_state_ == UntaggedLibrary::kLoadRequested;
5105 }
5106 bool LoadInProgress() const {
5107 return untag()->load_state_ == UntaggedLibrary::kLoadInProgress;
5108 }
5109 void SetLoadRequested() const;
5110 void SetLoadInProgress() const;
5111 bool Loaded() const {
5112 return untag()->load_state_ == UntaggedLibrary::kLoaded;
5113 }
5114 void SetLoaded() const;
5115
5116 LoadingUnitPtr loading_unit() const { return untag()->loading_unit(); }
5117 void set_loading_unit(const LoadingUnit& value) const;
5118
5119 static intptr_t InstanceSize() {
5120 return RoundedAllocationSize(sizeof(UntaggedLibrary));
5121 }
5122
5123 static LibraryPtr New(const String& url);
5124
5125 ObjectPtr Invoke(const String& selector,
5126 const Array& arguments,
5127 const Array& argument_names,
5128 bool respect_reflectable = true,
5129 bool check_is_entrypoint = false) const;
5130 ObjectPtr InvokeGetter(const String& selector,
5131 bool throw_nsm_if_absent,
5132 bool respect_reflectable = true,
5133 bool check_is_entrypoint = false) const;
5134 ObjectPtr InvokeSetter(const String& selector,
5135 const Instance& argument,
5136 bool respect_reflectable = true,
5137 bool check_is_entrypoint = false) const;
5138
5139 // Evaluate the given expression as if it appeared in an top-level method of
5140 // this library and return the resulting value, or an error object if
5141 // evaluating the expression fails. The method has the formal (type)
5142 // parameters given in (type_)param_names, and is invoked with the (type)
5143 // argument values given in (type_)param_values.
5145 const ExternalTypedData& kernel_buffer,
5146 const Array& type_definitions,
5147 const Array& param_values,
5148 const TypeArguments& type_param_values) const;
5149
5150 // Library scope name dictionary.
5151 //
5152 // TODO(turnidge): The Lookup functions are not consistent in how
5153 // they deal with private names. Go through and make them a bit
5154 // more regular.
5155 void AddClass(const Class& cls) const;
5156 void AddObject(const Object& obj, const String& name) const;
5157 ObjectPtr LookupReExport(
5158 const String& name,
5159 ZoneGrowableArray<intptr_t>* visited = nullptr) const;
5160 ObjectPtr LookupLocalOrReExportObject(const String& name) const;
5161 LibraryPrefixPtr LookupLocalLibraryPrefix(const String& name) const;
5162
5163 // These lookups are local within the library.
5164 ClassPtr LookupClass(const String& name) const;
5165 ClassPtr LookupClassAllowPrivate(const String& name) const;
5166 FieldPtr LookupFieldAllowPrivate(const String& name) const;
5167 FunctionPtr LookupFunctionAllowPrivate(const String& name) const;
5168
5169 // Look up a Script based on a url. If 'useResolvedUri' is not provided or is
5170 // false, 'url' should have a 'dart:' scheme for Dart core libraries,
5171 // a 'package:' scheme for packages, and 'file:' scheme otherwise.
5172 //
5173 // If 'useResolvedUri' is true, 'url' should have a 'org-dartlang-sdk:' scheme
5174 // for Dart core libraries and a 'file:' scheme otherwise.
5175 ScriptPtr LookupScript(const String& url, bool useResolvedUri = false) const;
5176 ArrayPtr LoadedScripts() const;
5177
5178 void AddExport(const Namespace& ns) const;
5179
5180 void AddMetadata(const Object& declaration, intptr_t kernel_offset) const;
5181 ObjectPtr GetMetadata(const Object& declaration) const;
5182
5183#if !defined(DART_PRECOMPILED_RUNTIME)
5184 void EvaluatePragmas();
5185 void CopyPragmas(const Library& old_lib);
5186#endif
5187
5188 // Tries to finds a @pragma annotation on [object].
5189 //
5190 // If successful returns `true`. If an error happens during constant
5191 // evaluation, returns `false.
5192 //
5193 // If [only_core] is true, then the annotations on the object will only
5194 // be inspected if it is part of a core library.
5195 //
5196 // If [multiple] is true, then sets [options] to an GrowableObjectArray
5197 // containing all results and [options] may not be nullptr.
5198 //
5199 // WARNING: If the isolate received an [UnwindError] this function will not
5200 // return and rather unwinds until the enclosing setjmp() handler.
5201 static bool FindPragma(Thread* T,
5202 bool only_core,
5203 const Object& object,
5204 const String& pragma_name,
5205 bool multiple = false,
5206 Object* options = nullptr);
5207
5208 ClassPtr toplevel_class() const { return untag()->toplevel_class(); }
5209 void set_toplevel_class(const Class& value) const;
5210
5211 GrowableObjectArrayPtr used_scripts() const {
5212 return untag()->used_scripts();
5213 }
5214
5215 // Library imports.
5216 ArrayPtr imports() const { return untag()->imports(); }
5217 ArrayPtr exports() const { return untag()->exports(); }
5218 void AddImport(const Namespace& ns) const;
5219 intptr_t num_imports() const { return untag()->num_imports_; }
5220 NamespacePtr ImportAt(intptr_t index) const;
5221 LibraryPtr ImportLibraryAt(intptr_t index) const;
5222
5223 ArrayPtr dependencies() const { return untag()->dependencies(); }
5224 void set_dependencies(const Array& deps) const;
5225
5226 void DropDependenciesAndCaches() const;
5227
5228 // Resolving native methods for script loaded in the library.
5230 return LoadNonPointer<Dart_NativeEntryResolver, std::memory_order_relaxed>(
5231 &untag()->native_entry_resolver_);
5232 }
5235 std::memory_order_relaxed>(&untag()->native_entry_resolver_,
5236 value);
5237 }
5239 return LoadNonPointer<Dart_NativeEntrySymbol, std::memory_order_relaxed>(
5240 &untag()->native_entry_symbol_resolver_);
5241 }
5243 Dart_NativeEntrySymbol native_symbol_resolver) const {
5245 std::memory_order_relaxed>(
5246 &untag()->native_entry_symbol_resolver_, native_symbol_resolver);
5247 }
5248
5249 // Resolver for FFI native function pointers.
5251 return LoadNonPointer<Dart_FfiNativeResolver, std::memory_order_relaxed>(
5252 &untag()->ffi_native_resolver_);
5253 }
5256 std::memory_order_relaxed>(&untag()->ffi_native_resolver_,
5257 value);
5258 }
5259
5260 bool is_in_fullsnapshot() const {
5262 }
5264 set_flags(
5265 UntaggedLibrary::InFullSnapshotBit::update(value, untag()->flags_));
5266 }
5267
5268 StringPtr PrivateName(const String& name) const;
5269
5270 intptr_t index() const { return untag()->index_; }
5271 void set_index(intptr_t value) const {
5272 ASSERT((value == -1) ||
5274 StoreNonPointer(&untag()->index_, value);
5275 }
5276
5277 void Register(Thread* thread) const;
5278 static void RegisterLibraries(Thread* thread,
5279 const GrowableObjectArray& libs);
5280
5281 bool IsDebuggable() const {
5283 }
5284 void set_debuggable(bool value) const {
5285 set_flags(UntaggedLibrary::DebuggableBit::update(value, untag()->flags_));
5286 }
5287
5288 bool is_dart_scheme() const {
5290 }
5291 void set_is_dart_scheme(bool value) const {
5292 set_flags(UntaggedLibrary::DartSchemeBit::update(value, untag()->flags_));
5293 }
5294
5295 // Includes 'dart:async', 'dart:typed_data', etc.
5296 bool IsAnyCoreLibrary() const;
5297
5298 inline intptr_t UrlHash() const;
5299
5300#if !defined(DART_PRECOMPILED_RUNTIME)
5301 KernelProgramInfoPtr kernel_program_info() const {
5302 return untag()->kernel_program_info();
5303 }
5304 void set_kernel_program_info(const KernelProgramInfo& info) const;
5305 TypedDataViewPtr KernelLibrary() const;
5306 intptr_t KernelLibraryOffset() const;
5307#endif
5308
5309 intptr_t kernel_library_index() const {
5310#if defined(DART_PRECOMPILED_RUNTIME)
5311 return 0;
5312#else
5313 return untag()->kernel_library_index_;
5314#endif
5315 }
5316
5317 void set_kernel_library_index(intptr_t value) const {
5318#if defined(DART_PRECOMPILED_RUNTIME)
5319 UNREACHABLE();
5320#else
5321 ASSERT(value >= 0);
5322 StoreNonPointer(&untag()->kernel_library_index_, value);
5323#endif
5324 }
5325
5326 static LibraryPtr LookupLibrary(Thread* thread, const String& url);
5327 static LibraryPtr GetLibrary(intptr_t index);
5328
5329 static void InitCoreLibrary(IsolateGroup* isolate_group);
5330 static void InitNativeWrappersLibrary(IsolateGroup* isolate_group,
5331 bool is_kernel_file);
5332
5333 static LibraryPtr AsyncLibrary();
5334 static LibraryPtr ConvertLibrary();
5335 static LibraryPtr CoreLibrary();
5336 static LibraryPtr CollectionLibrary();
5337 static LibraryPtr DeveloperLibrary();
5338 static LibraryPtr FfiLibrary();
5339 static LibraryPtr InternalLibrary();
5340 static LibraryPtr IsolateLibrary();
5341 static LibraryPtr MathLibrary();
5342#if !defined(DART_PRECOMPILED_RUNTIME)
5343 static LibraryPtr MirrorsLibrary();
5344#endif
5345 static LibraryPtr NativeWrappersLibrary();
5346 static LibraryPtr TypedDataLibrary();
5347 static LibraryPtr VMServiceLibrary();
5348
5349 // Eagerly compile all classes and functions in the library.
5350 static ErrorPtr CompileAll(bool ignore_error = false);
5351#if !defined(DART_PRECOMPILED_RUNTIME)
5352 // Finalize all classes in all libraries.
5353 static ErrorPtr FinalizeAllClasses();
5354#endif
5355
5356#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
5357 // Checks function fingerprints. Prints mismatches and aborts if
5358 // mismatch found.
5359 static void CheckFunctionFingerprints();
5360#endif // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
5361
5362 static bool IsPrivate(const String& name);
5363
5364 // Construct the full name of a corelib member.
5365 static const String& PrivateCoreLibName(const String& member);
5366
5367 // Returns true if [name] matches full name of corelib [member].
5368 static bool IsPrivateCoreLibName(const String& name, const String& member);
5369
5370 // Lookup class in the core lib which also contains various VM
5371 // helper methods and classes. Allow look up of private classes.
5372 static ClassPtr LookupCoreClass(const String& class_name);
5373
5374 // Return Function::null() if function does not exist in libs.
5375 static FunctionPtr GetFunction(const GrowableArray<Library*>& libs,
5376 const char* class_name,
5377 const char* function_name);
5378
5379 // Character used to indicate a private identifier.
5380 static const char kPrivateIdentifierStart = '_';
5381
5382 // Character used to separate private identifiers from
5383 // the library-specific key.
5384 static const char kPrivateKeySeparator = '@';
5385
5386 void CheckReload(const Library& replacement,
5387 ProgramReloadContext* context) const;
5388
5389 // Returns a closure of top level function 'name' in the exported namespace
5390 // of this library. If a top level function 'name' does not exist we look
5391 // for a top level getter 'name' that returns a closure.
5392 ObjectPtr GetFunctionClosure(const String& name) const;
5393
5394 // Ensures that all top-level functions and variables (fields) are loaded.
5395 void EnsureTopLevelClassIsFinalized() const;
5396
5397 private:
5398 static constexpr int kInitialImportsCapacity = 4;
5399 static constexpr int kImportsCapacityIncrement = 8;
5400
5401 static LibraryPtr New();
5402
5403 // These methods are only used by the Precompiler to obfuscate
5404 // the name and url.
5405 void set_name(const String& name) const;
5406 void set_url(const String& url) const;
5407 void set_private_key(const String& key) const;
5408
5409 void set_num_imports(intptr_t value) const;
5410 void set_flags(uint8_t flags) const;
5411 bool HasExports() const;
5412 ArrayPtr loaded_scripts() const { return untag()->loaded_scripts(); }
5413 ArrayPtr metadata() const {
5415 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
5416 return untag()->metadata();
5417 }
5418 void set_metadata(const Array& value) const;
5419 ArrayPtr dictionary() const { return untag()->dictionary(); }
5420 void InitClassDictionary() const;
5421
5422 void InitImportList() const;
5423 void RehashDictionary(const Array& old_dict, intptr_t new_dict_size) const;
5424 static LibraryPtr NewLibraryHelper(const String& url, bool import_core_lib);
5425 ObjectPtr LookupEntry(const String& name, intptr_t* index) const;
5426 ObjectPtr LookupLocalObject(const String& name) const;
5427 ObjectPtr LookupLocalObjectAllowPrivate(const String& name) const;
5428
5429 void AllocatePrivateKey() const;
5430
5432
5433 friend class Bootstrap;
5434 friend class Class;
5435 friend class Debugger;
5437 friend class Isolate;
5439 friend class Namespace;
5440 friend class Object;
5441 friend class Precompiler;
5442};
5443
5444// A Namespace contains the names in a library dictionary, filtered by
5445// the show/hide combinators.
5446class Namespace : public Object {
5447 public:
5448 LibraryPtr target() const { return untag()->target(); }
5449 ArrayPtr show_names() const { return untag()->show_names(); }
5450 ArrayPtr hide_names() const { return untag()->hide_names(); }
5451 LibraryPtr owner() const { return untag()->owner(); }
5452
5453 static intptr_t InstanceSize() {
5455 }
5456
5457 bool HidesName(const String& name) const;
5458 ObjectPtr Lookup(const String& name,
5459 ZoneGrowableArray<intptr_t>* trail = nullptr) const;
5460
5461 static NamespacePtr New(const Library& library,
5462 const Array& show_names,
5463 const Array& hide_names,
5464 const Library& owner);
5465
5466 private:
5467 static NamespacePtr New();
5468
5470 friend class Class;
5471 friend class Precompiler;
5472};
5473
5475 public:
5476 static KernelProgramInfoPtr New(const TypedDataBase& kernel_component,
5477 const TypedDataView& string_data,
5478 const TypedDataView& metadata_payload,
5479 const TypedDataView& metadata_mappings,
5480 const TypedDataView& constants_table,
5481 const TypedData& string_offsets,
5482 const TypedData& canonical_names,
5483 const Array& scripts,
5484 const Array& libraries_cache,
5485 const Array& classes_cache);
5486
5487 static intptr_t InstanceSize() {
5489 }
5490
5491 TypedDataPtr string_offsets() const { return untag()->string_offsets(); }
5492
5493 TypedDataBasePtr kernel_component() const {
5494 return untag()->kernel_component();
5495 }
5496 TypedDataViewPtr string_data() const { return untag()->string_data(); }
5497
5498 TypedDataPtr canonical_names() const { return untag()->canonical_names(); }
5499
5500 TypedDataViewPtr metadata_payloads() const {
5501 return untag()->metadata_payloads();
5502 }
5503
5504 TypedDataViewPtr metadata_mappings() const {
5505 return untag()->metadata_mappings();
5506 }
5507
5508 intptr_t KernelLibraryStartOffset(intptr_t library_index) const;
5509 intptr_t KernelLibraryEndOffset(intptr_t library_index) const;
5510 TypedDataViewPtr KernelLibrary(intptr_t library_index) const;
5511
5512 TypedDataViewPtr constants_table() const {
5513 return untag()->constants_table();
5514 }
5515
5516 void set_constants_table(const TypedDataView& value) const;
5517
5518 ArrayPtr scripts() const { return untag()->scripts(); }
5519 void set_scripts(const Array& scripts) const;
5520
5521 ArrayPtr constants() const { return untag()->constants(); }
5522 void set_constants(const Array& constants) const;
5523
5524 ScriptPtr ScriptAt(intptr_t index) const;
5525
5526 ArrayPtr libraries_cache() const { return untag()->libraries_cache(); }
5527 void set_libraries_cache(const Array& cache) const;
5528 LibraryPtr LookupLibrary(Thread* thread, const Smi& name_index) const;
5529 LibraryPtr InsertLibrary(Thread* thread,
5530 const Smi& name_index,
5531 const Library& lib) const;
5532
5533 ArrayPtr classes_cache() const { return untag()->classes_cache(); }
5534 void set_classes_cache(const Array& cache) const;
5535 ClassPtr LookupClass(Thread* thread, const Smi& name_index) const;
5536 ClassPtr InsertClass(Thread* thread,
5537 const Smi& name_index,
5538 const Class& klass) const;
5539
5540 private:
5541 static KernelProgramInfoPtr New();
5542
5544 friend class Class;
5545};
5546
5547// ObjectPool contains constants, immediates and addresses referenced by
5548// generated code and deoptimization infos. Each entry has an type associated
5549// with it which is stored in-inline after all the entries.
5550class ObjectPool : public Object {
5551 public:
5559
5560 struct Entry {
5561 Entry() : raw_value_(), type_() {}
5562 explicit Entry(const Object* obj)
5563 : obj_(obj), type_(EntryType::kTaggedObject) {}
5564 Entry(uword value, EntryType info) : raw_value_(value), type_(info) {}
5565 union {
5566 const Object* obj_;
5568 };
5570 };
5571
5572 intptr_t Length() const { return untag()->length_; }
5573 void SetLength(intptr_t value) const {
5574 StoreNonPointer(&untag()->length_, value);
5575 }
5576
5577 static intptr_t length_offset() {
5578 return OFFSET_OF(UntaggedObjectPool, length_);
5579 }
5580 static intptr_t data_offset() {
5582 }
5583 static intptr_t element_offset(intptr_t index) {
5585 sizeof(UntaggedObjectPool::Entry) * index;
5586 }
5587
5589 static intptr_t elements_start_offset() {
5590 return ObjectPool::data_offset();
5591 }
5592
5593 static constexpr intptr_t kElementSize = sizeof(UntaggedObjectPool::Entry);
5594 };
5595
5596 EntryType TypeAt(intptr_t index) const {
5597 ASSERT((index >= 0) && (index <= Length()));
5598 return TypeBits::decode(untag()->entry_bits()[index]);
5599 }
5600
5601 Patchability PatchableAt(intptr_t index) const {
5602 ASSERT((index >= 0) && (index <= Length()));
5603 return PatchableBit::decode(untag()->entry_bits()[index]);
5604 }
5605
5606 SnapshotBehavior SnapshotBehaviorAt(intptr_t index) const {
5607 ASSERT((index >= 0) && (index <= Length()));
5608 return SnapshotBehaviorBits::decode(untag()->entry_bits()[index]);
5609 }
5610
5611 static uint8_t EncodeBits(EntryType type,
5612 Patchability patchable,
5613 SnapshotBehavior snapshot_behavior) {
5614 return PatchableBit::encode(patchable) | TypeBits::encode(type) |
5615 SnapshotBehaviorBits::encode(snapshot_behavior);
5616 }
5617
5618 void SetTypeAt(intptr_t index,
5620 Patchability patchable,
5621 SnapshotBehavior snapshot_behavior) const {
5622 ASSERT(index >= 0 && index <= Length());
5623 const uint8_t bits = EncodeBits(type, patchable, snapshot_behavior);
5624 StoreNonPointer(&untag()->entry_bits()[index], bits);
5625 }
5626
5627 template <std::memory_order order = std::memory_order_relaxed>
5628 ObjectPtr ObjectAt(intptr_t index) const {
5629 ASSERT(TypeAt(index) == EntryType::kTaggedObject);
5630 return LoadPointer<ObjectPtr, order>(&(EntryAddr(index)->raw_obj_));
5631 }
5632
5633 template <std::memory_order order = std::memory_order_relaxed>
5634 void SetObjectAt(intptr_t index, const Object& obj) const {
5635 ASSERT((TypeAt(index) == EntryType::kTaggedObject) ||
5636 (TypeAt(index) == EntryType::kImmediate && obj.IsSmi()));
5637 StorePointer<ObjectPtr, order>(&EntryAddr(index)->raw_obj_, obj.ptr());
5638 }
5639
5640 uword RawValueAt(intptr_t index) const {
5641 ASSERT(TypeAt(index) != EntryType::kTaggedObject);
5642 return EntryAddr(index)->raw_value_;
5643 }
5644 void SetRawValueAt(intptr_t index, uword raw_value) const {
5645 ASSERT(TypeAt(index) != EntryType::kTaggedObject);
5646 StoreNonPointer(&EntryAddr(index)->raw_value_, raw_value);
5647 }
5648
5649 static intptr_t InstanceSize() {
5650 ASSERT(sizeof(UntaggedObjectPool) ==
5652 return 0;
5653 }
5654
5655 static constexpr intptr_t kBytesPerElement =
5656 sizeof(UntaggedObjectPool::Entry) + sizeof(uint8_t);
5657 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
5658
5659 static intptr_t InstanceSize(intptr_t len) {
5660 // Ensure that variable length data is not adding to the object length.
5661 ASSERT(sizeof(UntaggedObjectPool) ==
5662 (sizeof(UntaggedObject) + (1 * kWordSize)));
5663 ASSERT(0 <= len && len <= kMaxElements);
5665 (len * kBytesPerElement));
5666 }
5667
5668 static ObjectPoolPtr NewFromBuilder(
5670 static ObjectPoolPtr New(intptr_t len);
5671
5672 void CopyInto(compiler::ObjectPoolBuilder* builder) const;
5673
5674 // Returns the pool index from the offset relative to a tagged ObjectPoolPtr,
5675 // adjusting for the tag-bit.
5676 static intptr_t IndexFromOffset(intptr_t offset) {
5677 ASSERT(
5679#if defined(DART_PRECOMPILER)
5680 return (offset + kHeapObjectTag -
5683#else
5684 return (offset + kHeapObjectTag - element_offset(0)) / kWordSize;
5685#endif
5686 }
5687
5688 static intptr_t OffsetFromIndex(intptr_t index) {
5689 return element_offset(index) - kHeapObjectTag;
5690 }
5691
5692 void DebugPrint() const;
5693
5694 private:
5695 UntaggedObjectPool::Entry const* EntryAddr(intptr_t index) const {
5696 ASSERT((index >= 0) && (index < Length()));
5697 return &untag()->data()[index];
5698 }
5699
5701 friend class Class;
5702 friend class Object;
5704};
5705
5706class Instructions : public Object {
5707 public:
5708 enum {
5709 kSizePos = 0,
5710 kSizeSize = 30,
5711 kFlagsPos = kSizePos + kSizeSize,
5712 kFlagsSize = kBitsPerInt32 - kSizeSize,
5713 };
5714
5715#define INSTRUCTIONS_FLAGS_LIST(V) \
5716 V(HasMonomorphicEntry) \
5717 V(ShouldBeAligned)
5718
5719 enum {
5720#define DEFINE_INSTRUCTIONS_FLAG(Name) k##Name##Index,
5722#undef DEFINE_INSTRUCTIONS_FLAG
5723 };
5724
5725 class SizeBits : public BitField<uint32_t, uint32_t, kSizePos, kSizeSize> {};
5726
5727#define DEFINE_INSTRUCTIONS_FLAG_HANDLING(Name) \
5728 class Name##Bit \
5729 : public BitField<uint32_t, bool, kFlagsPos + k##Name##Index, 1> {}; \
5730 bool Name() const { return Name##Bit::decode(untag()->size_and_flags_); } \
5731 static bool Name(const InstructionsPtr instr) { \
5732 return Name##Bit::decode(instr->untag()->size_and_flags_); \
5733 }
5734
5736
5737#undef DEFINE_INSTRUCTIONS_FLAG_HANDLING
5738
5739 // Excludes HeaderSize().
5740 intptr_t Size() const { return SizeBits::decode(untag()->size_and_flags_); }
5741 static intptr_t Size(const InstructionsPtr instr) {
5742 return SizeBits::decode(instr->untag()->size_and_flags_);
5743 }
5744
5745 uword PayloadStart() const { return PayloadStart(ptr()); }
5747 uword EntryPoint() const { return EntryPoint(ptr()); }
5748 static uword PayloadStart(const InstructionsPtr instr) {
5749 return reinterpret_cast<uword>(instr->untag()) + HeaderSize();
5750 }
5751
5752// Note: We keep the checked entrypoint offsets even (emitting NOPs if
5753// necessary) to allow them to be seen as Smis by the GC.
5754#if defined(TARGET_ARCH_IA32)
5755 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 6;
5756 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 36;
5757 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 0;
5758 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 0;
5759#elif defined(TARGET_ARCH_X64)
5760 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 8;
5761 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 42;
5762 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 8;
5763 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 22;
5764#elif defined(TARGET_ARCH_ARM)
5765 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 0;
5766 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 44;
5767 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 0;
5768 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 16;
5769#elif defined(TARGET_ARCH_ARM64)
5770 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 8;
5771 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 52;
5772 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 8;
5773 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 24;
5774#elif defined(TARGET_ARCH_RISCV32)
5775 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 6;
5776 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 44;
5777 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 6;
5778 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 18;
5779#elif defined(TARGET_ARCH_RISCV64)
5780 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 6;
5781 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 44;
5782 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 6;
5783 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 18;
5784#else
5785#error Missing entry offsets for current architecture
5786#endif
5787
5788 static uword MonomorphicEntryPoint(const InstructionsPtr instr) {
5789 uword entry = PayloadStart(instr);
5790 if (HasMonomorphicEntry(instr)) {
5791 entry += !FLAG_precompiled_mode ? kMonomorphicEntryOffsetJIT
5792 : kMonomorphicEntryOffsetAOT;
5793 }
5794 return entry;
5795 }
5796
5797 static uword EntryPoint(const InstructionsPtr instr) {
5798 uword entry = PayloadStart(instr);
5799 if (HasMonomorphicEntry(instr)) {
5800 entry += !FLAG_precompiled_mode ? kPolymorphicEntryOffsetJIT
5801 : kPolymorphicEntryOffsetAOT;
5802 }
5803 return entry;
5804 }
5805
5806 static constexpr intptr_t kMaxElements =
5807 (kMaxInt32 - (sizeof(UntaggedInstructions) + sizeof(UntaggedObject) +
5808 (2 * kObjectStartAlignment)));
5809
5810 // Currently, we align bare instruction payloads on 4 byte boundaries.
5811 //
5812 // If we later decide to align on larger boundaries to put entries at the
5813 // start of cache lines, make sure to account for entry points that are
5814 // _not_ at the start of the payload.
5815 static constexpr intptr_t kBarePayloadAlignment = 4;
5816
5817 // When instructions reside in the heap we align the payloads on word
5818 // boundaries.
5819 static constexpr intptr_t kNonBarePayloadAlignment = kWordSize;
5820
5821 // In the precompiled runtime when running in bare instructions mode,
5822 // Instructions objects don't exist, just their bare payloads, so we
5823 // mark them as unreachable in that case.
5824
5825 static intptr_t HeaderSize() {
5826#if defined(DART_PRECOMPILED_RUNTIME)
5827 UNREACHABLE();
5828#endif
5829 return Utils::RoundUp(sizeof(UntaggedInstructions),
5830 kNonBarePayloadAlignment);
5831 }
5832
5833 static intptr_t InstanceSize() {
5836 return 0;
5837 }
5838
5839 static intptr_t InstanceSize(intptr_t size) {
5840#if defined(DART_PRECOMPILED_RUNTIME)
5841 UNREACHABLE();
5842#endif
5844 }
5845
5846 static InstructionsPtr FromPayloadStart(uword payload_start) {
5847#if defined(DART_PRECOMPILED_RUNTIME)
5848 UNREACHABLE();
5849#endif
5850 return static_cast<InstructionsPtr>(payload_start - HeaderSize() +
5852 }
5853
5854 bool Equals(const Instructions& other) const {
5855 return Equals(ptr(), other.ptr());
5856 }
5857
5858 static bool Equals(InstructionsPtr a, InstructionsPtr b) {
5859 // This method should only be called on non-null Instructions objects.
5860 ASSERT_EQUAL(a->GetClassId(), kInstructionsCid);
5861 ASSERT_EQUAL(b->GetClassId(), kInstructionsCid);
5862 // Don't include the object header tags wholesale in the comparison,
5863 // because the GC tags may differ in JIT mode. In fact, we can skip checking
5864 // the object header entirely, as we're guaranteed that the cids match,
5865 // because there are no subclasses for the Instructions class, and the sizes
5866 // should match if the content size encoded in size_and_flags_ matches.
5867 if (a->untag()->size_and_flags_ != b->untag()->size_and_flags_) {
5868 return false;
5869 }
5870 NoSafepointScope no_safepoint;
5871 return memcmp(a->untag()->data(), b->untag()->data(), Size(a)) == 0;
5872 }
5873
5874 uint32_t Hash() const { return Hash(ptr()); }
5875
5876 static uint32_t Hash(const InstructionsPtr instr) {
5877 return HashBytes(reinterpret_cast<const uint8_t*>(PayloadStart(instr)),
5878 Size(instr));
5879 }
5880
5881 CodeStatistics* stats() const;
5882 void set_stats(CodeStatistics* stats) const;
5883
5884 private:
5885 friend struct RelocatorTestHelper;
5886
5887 void SetSize(intptr_t value) const {
5888 ASSERT(value >= 0);
5889 StoreNonPointer(&untag()->size_and_flags_,
5890 SizeBits::update(value, untag()->size_and_flags_));
5891 }
5892
5893#define DEFINE_INSTRUCTIONS_FLAG_HANDLING(Name) \
5894 void Set##Name(bool value) const { \
5895 StoreNonPointer(&untag()->size_and_flags_, \
5896 Name##Bit::update(value, untag()->size_and_flags_)); \
5897 }
5898
5900
5901#undef DEFINE_INSTRUCTIONS_FLAG_HANDLING
5902
5903 // New is a private method as RawInstruction and RawCode objects should
5904 // only be created using the Code::FinalizeCode method. This method creates
5905 // the RawInstruction and RawCode objects, sets up the pointer offsets
5906 // and links the two in a GC safe manner.
5907 static InstructionsPtr New(intptr_t size,
5908 bool has_monomorphic_entry,
5909 bool should_be_aligned);
5910
5912 friend class Class;
5913 friend class Code;
5914 friend class AssemblyImageWriter;
5915 friend class BlobImageWriter;
5916 friend class ImageWriter;
5917};
5918
5919// An InstructionsSection contains extra information about serialized AOT
5920// snapshots.
5921//
5922// To avoid changing the embedder to return more information about an AOT
5923// snapshot and possibly disturbing existing clients of that interface, we
5924// serialize a single InstructionsSection object at the start of any text
5925// segments. In bare instructions mode, it also has the benefit of providing
5926// memory accounting for the instructions payloads and avoiding special casing
5927// Images with bare instructions payloads in the GC. Otherwise, it is empty
5928// and the Instructions objects come after it in the Image.
5930 public:
5931 // Excludes HeaderSize().
5932 static intptr_t Size(const InstructionsSectionPtr instr) {
5933 return instr->untag()->payload_length_;
5934 }
5935 static intptr_t InstanceSize() {
5938 return 0;
5939 }
5940
5941 static intptr_t InstanceSize(intptr_t size) {
5943 }
5944
5945 static constexpr intptr_t kPayloadAlignment = 32;
5946 static_assert(kPreferredLoopAlignment <= kPayloadAlignment);
5947 static_assert(Instructions::kBarePayloadAlignment <= kPayloadAlignment);
5948
5949 static intptr_t HeaderSize() {
5951 kPayloadAlignment);
5952 }
5953
5954 // There are no public instance methods for the InstructionsSection class, as
5955 // all access to the contents is handled by methods on the Image class.
5956
5957 private:
5958 // Note there are no New() methods for InstructionsSection. Instead, the
5959 // serializer writes the UntaggedInstructionsSection object manually at the
5960 // start of instructions Images in precompiled snapshots.
5961
5963 friend class Class;
5964};
5965
5966// Table which maps ranges of machine code to [Code] or
5967// [CompressedStackMaps] objects.
5968// Used in AOT in bare instructions mode.
5970 public:
5971 static intptr_t InstanceSize() { return sizeof(UntaggedInstructionsTable); }
5972
5973 static InstructionsTablePtr New(intptr_t length,
5974 uword start_pc,
5975 uword end_pc,
5976 uword rodata);
5977
5978 void SetCodeAt(intptr_t index, CodePtr code) const;
5979
5980 bool ContainsPc(uword pc) const { return ContainsPc(ptr(), pc); }
5981 static bool ContainsPc(InstructionsTablePtr table, uword pc);
5982
5983 static CodePtr FindCode(InstructionsTablePtr table, uword pc);
5984
5986 FindStackMap(InstructionsTablePtr table, uword pc, uword* start_pc);
5987
5988 static const UntaggedCompressedStackMaps::Payload* GetCanonicalStackMap(
5989 InstructionsTablePtr table);
5990
5992 return ptr()->untag()->rodata_;
5993 }
5994
5995 // Returns start address of the instructions entry with given index.
5996 uword PayloadStartAt(intptr_t index) const {
5997 return InstructionsTable::PayloadStartAt(this->ptr(), index);
5998 }
5999 static uword PayloadStartAt(InstructionsTablePtr table, intptr_t index);
6000
6001 // Returns entry point of the instructions with given index.
6002 uword EntryPointAt(intptr_t index) const;
6003
6004 private:
6005 uword start_pc() const { return InstructionsTable::start_pc(this->ptr()); }
6006 static uword start_pc(InstructionsTablePtr table) {
6007 return table->untag()->start_pc_;
6008 }
6009
6010 uword end_pc() const { return InstructionsTable::end_pc(this->ptr()); }
6011 static uword end_pc(InstructionsTablePtr table) {
6012 return table->untag()->end_pc_;
6013 }
6014
6015 ArrayPtr code_objects() const { return untag()->code_objects_; }
6016
6017 void set_length(intptr_t value) const;
6018 void set_start_pc(uword value) const;
6019 void set_end_pc(uword value) const;
6020 void set_code_objects(const Array& value) const;
6021 void set_rodata(uword rodata) const;
6022
6023 uint32_t ConvertPcToOffset(uword pc) const {
6024 return InstructionsTable::ConvertPcToOffset(this->ptr(), pc);
6025 }
6026 static uint32_t ConvertPcToOffset(InstructionsTablePtr table, uword pc);
6027
6028 static intptr_t FindEntry(InstructionsTablePtr table,
6029 uword pc,
6030 intptr_t start_index = 0);
6031
6032 FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsTable, Object);
6033 friend class Class;
6034 friend class Deserializer;
6035};
6036
6038 public:
6039 intptr_t Length() const;
6040
6041 StringPtr GetName(intptr_t var_index) const;
6042
6043 void SetVar(intptr_t var_index,
6044 const String& name,
6046
6047 void GetInfo(intptr_t var_index,
6049
6050 static constexpr intptr_t kBytesPerElement =
6052 static constexpr intptr_t kMaxElements =
6054
6055 static intptr_t InstanceSize() {
6058 return 0;
6059 }
6060 static intptr_t InstanceSize(intptr_t len) {
6061 ASSERT(0 <= len && len <= kMaxElements);
6062 return RoundedAllocationSize(
6064 (len * kWordSize) // RawStrings for names.
6066 }
6067
6068 static LocalVarDescriptorsPtr New(intptr_t num_variables);
6069
6070 static const char* KindToCString(
6072
6073 private:
6075 friend class Class;
6076 friend class Object;
6077};
6078
6079class PcDescriptors : public Object {
6080 public:
6081 static constexpr intptr_t kBytesPerElement = 1;
6082 static constexpr intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
6083
6084 static intptr_t HeaderSize() { return sizeof(UntaggedPcDescriptors); }
6085 static intptr_t UnroundedSize(PcDescriptorsPtr desc) {
6086 return UnroundedSize(desc->untag()->length_);
6087 }
6088 static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
6089 static intptr_t InstanceSize() {
6092 return 0;
6093 }
6094 static intptr_t InstanceSize(intptr_t len) {
6095 ASSERT(0 <= len && len <= kMaxElements);
6096 return RoundedAllocationSize(UnroundedSize(len));
6097 }
6098
6099 static PcDescriptorsPtr New(const void* delta_encoded_data, intptr_t size);
6100
6101 // Verify (assert) assumptions about pc descriptors in debug mode.
6102 void Verify(const Function& function) const;
6103
6104 void PrintToJSONObject(JSONObject* jsobj, bool ref) const;
6105
6106 // We would have a VisitPointers function here to traverse the
6107 // pc descriptors table to visit objects if any in the table.
6108 // Note: never return a reference to a UntaggedPcDescriptors::PcDescriptorRec
6109 // as the object can move.
6110 class Iterator : public ValueObject {
6111 public:
6112 Iterator(const PcDescriptors& descriptors, intptr_t kind_mask)
6113 : descriptors_(descriptors),
6114 kind_mask_(kind_mask),
6115 byte_index_(0),
6116 cur_pc_offset_(0),
6117 cur_kind_(0),
6118 cur_deopt_id_(0),
6119 cur_token_pos_(0),
6120 cur_try_index_(0),
6121 cur_yield_index_(UntaggedPcDescriptors::kInvalidYieldIndex) {}
6122
6123 bool MoveNext() {
6124 NoSafepointScope scope;
6125 ReadStream stream(descriptors_.untag()->data(), descriptors_.Length(),
6126 byte_index_);
6127 // Moves to record that matches kind_mask_.
6128 while (byte_index_ < descriptors_.Length()) {
6129 const int32_t kind_and_metadata = stream.ReadSLEB128<int32_t>();
6131 kind_and_metadata);
6133 kind_and_metadata);
6134 cur_yield_index_ =
6136 kind_and_metadata);
6137
6138 cur_pc_offset_ += stream.ReadSLEB128();
6139
6140 if (!FLAG_precompiled_mode) {
6141 cur_deopt_id_ += stream.ReadSLEB128();
6142 cur_token_pos_ = Utils::AddWithWrapAround(
6143 cur_token_pos_, stream.ReadSLEB128<int32_t>());
6144 }
6145 byte_index_ = stream.Position();
6146
6147 if ((cur_kind_ & kind_mask_) != 0) {
6148 return true; // Current is valid.
6149 }
6150 }
6151 return false;
6152 }
6153
6154 uword PcOffset() const { return cur_pc_offset_; }
6155 intptr_t DeoptId() const { return cur_deopt_id_; }
6157 return TokenPosition::Deserialize(cur_token_pos_);
6158 }
6159 intptr_t TryIndex() const { return cur_try_index_; }
6160 intptr_t YieldIndex() const { return cur_yield_index_; }
6162 return static_cast<UntaggedPcDescriptors::Kind>(cur_kind_);
6163 }
6164
6165 private:
6166 friend class PcDescriptors;
6167
6168 // For nested iterations, starting at element after.
6169 explicit Iterator(const Iterator& iter)
6170 : ValueObject(),
6171 descriptors_(iter.descriptors_),
6172 kind_mask_(iter.kind_mask_),
6173 byte_index_(iter.byte_index_),
6174 cur_pc_offset_(iter.cur_pc_offset_),
6175 cur_kind_(iter.cur_kind_),
6176 cur_deopt_id_(iter.cur_deopt_id_),
6177 cur_token_pos_(iter.cur_token_pos_),
6178 cur_try_index_(iter.cur_try_index_),
6179 cur_yield_index_(iter.cur_yield_index_) {}
6180
6181 const PcDescriptors& descriptors_;
6182 const intptr_t kind_mask_;
6183 intptr_t byte_index_;
6184
6185 intptr_t cur_pc_offset_;
6186 intptr_t cur_kind_;
6187 intptr_t cur_deopt_id_;
6188 int32_t cur_token_pos_;
6189 intptr_t cur_try_index_;
6190 intptr_t cur_yield_index_;
6191 };
6192
6193 intptr_t Length() const;
6194 bool Equals(const PcDescriptors& other) const {
6195 if (Length() != other.Length()) {
6196 return false;
6197 }
6198 NoSafepointScope no_safepoint;
6199 return memcmp(untag()->data(), other.untag()->data(), Length()) == 0;
6200 }
6201
6202 // Writes the contents of the PcDescriptors object to the given buffer.
6203 // The base argument is added to the PC offset for each entry.
6204 void WriteToBuffer(BaseTextBuffer* buffer, uword base) const;
6205
6206 private:
6207 static const char* KindAsStr(UntaggedPcDescriptors::Kind kind);
6208
6209 static PcDescriptorsPtr New(intptr_t length);
6210
6211 void SetLength(intptr_t value) const;
6212 void CopyData(const void* bytes, intptr_t size);
6213
6215 friend class Class;
6216 friend class Object;
6217};
6218
6219class CodeSourceMap : public Object {
6220 public:
6221 static constexpr intptr_t kBytesPerElement = 1;
6222 static constexpr intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
6223
6224 static intptr_t HeaderSize() { return sizeof(UntaggedCodeSourceMap); }
6225 static intptr_t UnroundedSize(CodeSourceMapPtr map) {
6226 return UnroundedSize(map->untag()->length_);
6227 }
6228 static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
6229 static intptr_t InstanceSize() {
6232 return 0;
6233 }
6234 static intptr_t InstanceSize(intptr_t len) {
6235 ASSERT(0 <= len && len <= kMaxElements);
6236 return RoundedAllocationSize(UnroundedSize(len));
6237 }
6238
6239 static CodeSourceMapPtr New(intptr_t length);
6240
6241 intptr_t Length() const { return untag()->length_; }
6242 uint8_t* Data() const { return UnsafeMutableNonPointer(&untag()->data()[0]); }
6243
6244 bool Equals(const CodeSourceMap& other) const {
6245 if (Length() != other.Length()) {
6246 return false;
6247 }
6248 NoSafepointScope no_safepoint;
6249 return memcmp(untag()->data(), other.untag()->data(), Length()) == 0;
6250 }
6251
6252 uint32_t Hash() const {
6253 NoSafepointScope no_safepoint;
6254 return HashBytes(Data(), Length());
6255 }
6256
6257 void PrintToJSONObject(JSONObject* jsobj, bool ref) const;
6258
6259 private:
6260 void SetLength(intptr_t value) const;
6261
6263 friend class Class;
6264 friend class Object;
6265};
6266
6268 public:
6269 uintptr_t payload_size() const { return PayloadSizeOf(ptr()); }
6270 static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw) {
6272 raw->untag()->payload()->flags_and_size());
6273 }
6274
6275 const uint8_t* data() const { return ptr()->untag()->payload()->data(); }
6276
6277 // Methods to allow use with PointerKeyValueTrait to create sets of CSMs.
6278 bool Equals(const CompressedStackMaps& other) const {
6279 // All of the table flags and payload size must match.
6280 if (untag()->payload()->flags_and_size() !=
6281 other.untag()->payload()->flags_and_size()) {
6282 return false;
6283 }
6284 NoSafepointScope no_safepoint;
6285 return memcmp(data(), other.data(), payload_size()) == 0;
6286 }
6287 uword Hash() const;
6288
6289 static intptr_t HeaderSize() {
6290 return sizeof(UntaggedCompressedStackMaps) +
6292 }
6293 static intptr_t UnroundedSize(CompressedStackMapsPtr maps) {
6294 return UnroundedSize(CompressedStackMaps::PayloadSizeOf(maps));
6295 }
6296 static intptr_t UnroundedSize(intptr_t length) {
6297 return HeaderSize() + length;
6298 }
6299 static intptr_t InstanceSize() { return 0; }
6300 static intptr_t InstanceSize(intptr_t length) {
6301 return RoundedAllocationSize(UnroundedSize(length));
6302 }
6303
6304 bool UsesGlobalTable() const { return UsesGlobalTable(ptr()); }
6305 static bool UsesGlobalTable(const CompressedStackMapsPtr raw) {
6307 raw->untag()->payload()->flags_and_size());
6308 }
6309
6310 bool IsGlobalTable() const { return IsGlobalTable(ptr()); }
6311 static bool IsGlobalTable(const CompressedStackMapsPtr raw) {
6313 raw->untag()->payload()->flags_and_size());
6314 }
6315
6316 static CompressedStackMapsPtr NewInlined(const void* payload, intptr_t size) {
6317 return New(payload, size, /*is_global_table=*/false,
6318 /*uses_global_table=*/false);
6319 }
6320 static CompressedStackMapsPtr NewUsingTable(const void* payload,
6321 intptr_t size) {
6322 return New(payload, size, /*is_global_table=*/false,
6323 /*uses_global_table=*/true);
6324 }
6325
6326 static CompressedStackMapsPtr NewGlobalTable(const void* payload,
6327 intptr_t size) {
6328 return New(payload, size, /*is_global_table=*/true,
6329 /*uses_global_table=*/false);
6330 }
6331
6333 public:
6337
6339 return payload_;
6340 }
6341 bool IsNull() const { return payload_ == nullptr; }
6342
6344 const UntaggedCompressedStackMaps::Payload* payload) {
6345 payload_ = payload;
6346 return *this;
6347 }
6348
6350 ASSERT(!maps.IsNull());
6351 payload_ = maps.untag()->payload();
6352 return *this;
6353 }
6354
6355 RawPayloadHandle& operator=(CompressedStackMapsPtr maps) {
6357 payload_ = maps.untag()->payload();
6358 return *this;
6359 }
6360
6361 uintptr_t payload_size() const {
6363 payload()->flags_and_size());
6364 }
6365 const uint8_t* data() const { return payload()->data(); }
6366
6367 bool UsesGlobalTable() const {
6369 payload()->flags_and_size());
6370 }
6371
6372 bool IsGlobalTable() const {
6374 payload()->flags_and_size());
6375 }
6376
6377 private:
6378 const UntaggedCompressedStackMaps::Payload* payload_ = nullptr;
6379 };
6380
6381 template <typename PayloadHandle>
6382 class Iterator {
6383 public:
6384 Iterator(const PayloadHandle& maps, const PayloadHandle& global_table)
6385 : maps_(maps),
6386 bits_container_(maps.UsesGlobalTable() ? global_table : maps) {
6387 ASSERT(!maps_.IsNull());
6388 ASSERT(!bits_container_.IsNull());
6389 ASSERT(!maps_.IsGlobalTable());
6390 ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
6391 }
6392
6394 : maps_(it.maps_),
6395 bits_container_(it.bits_container_),
6396 next_offset_(it.next_offset_),
6397 current_pc_offset_(it.current_pc_offset_),
6398 current_global_table_offset_(it.current_global_table_offset_),
6399 current_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
6400 current_non_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
6401 current_bits_offset_(it.current_bits_offset_) {}
6402
6403 // Loads the next entry from [maps_], if any. If [maps_] is the null value,
6404 // this always returns false.
6405 bool MoveNext() {
6406 if (next_offset_ >= maps_.payload_size()) {
6407 return false;
6408 }
6409
6410 NoSafepointScope scope;
6411 ReadStream stream(maps_.data(), maps_.payload_size(), next_offset_);
6412
6413 auto const pc_delta = stream.ReadLEB128();
6414 ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
6415 current_pc_offset_ += pc_delta;
6416
6417 // Table-using CSMs have a table offset after the PC offset delta, whereas
6418 // the post-delta part of inlined entries has the same information as
6419 // global table entries.
6420 // See comments in UntaggedCompressedStackMaps for description of
6421 // encoding.
6422 if (maps_.UsesGlobalTable()) {
6423 current_global_table_offset_ = stream.ReadLEB128();
6424 ASSERT(current_global_table_offset_ < bits_container_.payload_size());
6425
6426 // Since generally we only use entries in the GC and the GC only needs
6427 // the rest of the entry information if the PC offset matches, we lazily
6428 // load and cache the information stored in the global object when it is
6429 // actually requested.
6430 current_spill_slot_bit_count_ = -1;
6431 current_non_spill_slot_bit_count_ = -1;
6432 current_bits_offset_ = -1;
6433
6434 next_offset_ = stream.Position();
6435 } else {
6436 current_spill_slot_bit_count_ = stream.ReadLEB128();
6437 ASSERT(current_spill_slot_bit_count_ >= 0);
6438
6439 current_non_spill_slot_bit_count_ = stream.ReadLEB128();
6440 ASSERT(current_non_spill_slot_bit_count_ >= 0);
6441
6442 const auto stackmap_bits =
6443 current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
6444 const uintptr_t stackmap_size =
6445 Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
6446 ASSERT(stackmap_size <= (maps_.payload_size() - stream.Position()));
6447
6448 current_bits_offset_ = stream.Position();
6449 next_offset_ = current_bits_offset_ + stackmap_size;
6450 }
6451
6452 return true;
6453 }
6454
6455 // Finds the entry with the given PC offset starting at the current position
6456 // of the iterator. If [maps_] is the null value, this always returns false.
6457 bool Find(uint32_t pc_offset) {
6458 // We should never have an entry with a PC offset of 0 inside an
6459 // non-empty CSM, so fail.
6460 if (pc_offset == 0) return false;
6461 do {
6462 if (current_pc_offset_ >= pc_offset) break;
6463 } while (MoveNext());
6464 return current_pc_offset_ == pc_offset;
6465 }
6466
6467 // Methods for accessing parts of an entry should not be called until
6468 // a successful MoveNext() or Find() call has been made.
6469
6470 // Returns the PC offset of the loaded entry.
6471 uint32_t pc_offset() const {
6472 ASSERT(HasLoadedEntry());
6473 return current_pc_offset_;
6474 }
6475
6476 // Returns the bit length of the loaded entry.
6477 intptr_t Length() const {
6478 EnsureFullyLoadedEntry();
6479 return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
6480 }
6481 // Returns the number of spill slot bits of the loaded entry.
6482 intptr_t SpillSlotBitCount() const {
6483 EnsureFullyLoadedEntry();
6484 return current_spill_slot_bit_count_;
6485 }
6486 // Returns whether the stack entry represented by the offset contains
6487 // a tagged object.
6488 bool IsObject(intptr_t bit_index) const {
6489 EnsureFullyLoadedEntry();
6490 ASSERT(bit_index >= 0 && bit_index < Length());
6491 const intptr_t byte_index = bit_index >> kBitsPerByteLog2;
6492 const intptr_t bit_remainder = bit_index & (kBitsPerByte - 1);
6493 uint8_t byte_mask = 1U << bit_remainder;
6494 const intptr_t byte_offset = current_bits_offset_ + byte_index;
6495 NoSafepointScope scope;
6496 return (bits_container_.data()[byte_offset] & byte_mask) != 0;
6497 }
6498
6499 private:
6500 bool HasLoadedEntry() const { return next_offset_ > 0; }
6501
6502 // Caches the corresponding values from the global table in the mutable
6503 // fields. We lazily load these as some clients only need the PC offset.
6504 void LazyLoadGlobalTableEntry() const {
6505 ASSERT(maps_.UsesGlobalTable());
6506 ASSERT(HasLoadedEntry());
6507 ASSERT(current_global_table_offset_ < bits_container_.payload_size());
6508
6509 NoSafepointScope scope;
6510 ReadStream stream(bits_container_.data(), bits_container_.payload_size(),
6511 current_global_table_offset_);
6512
6513 current_spill_slot_bit_count_ = stream.ReadLEB128();
6514 ASSERT(current_spill_slot_bit_count_ >= 0);
6515
6516 current_non_spill_slot_bit_count_ = stream.ReadLEB128();
6517 ASSERT(current_non_spill_slot_bit_count_ >= 0);
6518
6519 const auto stackmap_bits = Length();
6520 const uintptr_t stackmap_size =
6521 Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
6522 ASSERT(stackmap_size <=
6523 (bits_container_.payload_size() - stream.Position()));
6524
6525 current_bits_offset_ = stream.Position();
6526 }
6527
6528 void EnsureFullyLoadedEntry() const {
6529 ASSERT(HasLoadedEntry());
6530 if (current_spill_slot_bit_count_ < 0) {
6531 LazyLoadGlobalTableEntry();
6532 ASSERT(current_spill_slot_bit_count_ >= 0);
6533 }
6534 }
6535
6536 const PayloadHandle& maps_;
6537 const PayloadHandle& bits_container_;
6538
6539 uintptr_t next_offset_ = 0;
6540 uint32_t current_pc_offset_ = 0;
6541 // Only used when looking up non-PC information in the global table.
6542 uintptr_t current_global_table_offset_ = 0;
6543 // Marked as mutable as these fields may be updated with lazily loaded
6544 // values from the global table when their associated accessor is called,
6545 // but those values will never change for a given entry once loaded..
6546 mutable intptr_t current_spill_slot_bit_count_ = -1;
6547 mutable intptr_t current_non_spill_slot_bit_count_ = -1;
6548 mutable intptr_t current_bits_offset_ = -1;
6549
6550 friend class StackMapEntry;
6551 };
6552
6553 Iterator<CompressedStackMaps> iterator(Thread* thread) const;
6554
6555 // Writes the contents of the CompressedStackMaps object to the given buffer.
6556 // The base argument is added to the PC offset for each entry, and the
6557 // separator string is inserted between each entry.
6558 void WriteToBuffer(BaseTextBuffer* buffer,
6559 uword base,
6560 const char* separator) const;
6561
6562 private:
6563 static CompressedStackMapsPtr New(const void* payload,
6564 intptr_t size,
6565 bool is_global_table,
6566 bool uses_global_table);
6567
6569 friend class Class;
6570};
6571
6573 public:
6574 static constexpr intptr_t kInvalidPcOffset = 0;
6575
6576 intptr_t num_entries() const;
6577
6578 bool has_async_handler() const;
6579 void set_has_async_handler(bool value) const;
6580
6581 void GetHandlerInfo(intptr_t try_index, ExceptionHandlerInfo* info) const;
6582
6583 uword HandlerPCOffset(intptr_t try_index) const;
6584 intptr_t OuterTryIndex(intptr_t try_index) const;
6585 bool NeedsStackTrace(intptr_t try_index) const;
6586 bool IsGenerated(intptr_t try_index) const;
6587
6588 void SetHandlerInfo(intptr_t try_index,
6589 intptr_t outer_try_index,
6590 uword handler_pc_offset,
6591 bool needs_stacktrace,
6592 bool has_catch_all,
6593 bool is_generated) const;
6594
6595 ArrayPtr GetHandledTypes(intptr_t try_index) const;
6596 void SetHandledTypes(intptr_t try_index, const Array& handled_types) const;
6597 bool HasCatchAll(intptr_t try_index) const;
6598
6600 static intptr_t elements_start_offset() {
6601 return sizeof(UntaggedExceptionHandlers);
6602 }
6603 static constexpr intptr_t kElementSize = sizeof(ExceptionHandlerInfo);
6604 };
6605
6606 static intptr_t InstanceSize() {
6609 return 0;
6610 }
6611 static intptr_t InstanceSize(intptr_t len) {
6613 (len * sizeof(ExceptionHandlerInfo)));
6614 }
6615
6616 static ExceptionHandlersPtr New(intptr_t num_handlers);
6617 static ExceptionHandlersPtr New(const Array& handled_types_data);
6618
6619 // We would have a VisitPointers function here to traverse the
6620 // exception handler table to visit objects if any in the table.
6621
6622 // Writes the contents of the ExceptionHandlers object to the given buffer.
6623 // The base argument is added to the PC offset for each entry.
6624 void WriteToBuffer(BaseTextBuffer* buffer, uword base) const;
6625
6626 private:
6627 // Pick somewhat arbitrary maximum number of exception handlers
6628 // for a function. This value is used to catch potentially
6629 // malicious code.
6630 static constexpr intptr_t kMaxHandlers = 1024 * 1024;
6631
6632 void set_handled_types_data(const Array& value) const;
6633
6635 friend class Class;
6636 friend class Object;
6637};
6638
6639// A WeakSerializationReference (WSR) denotes a type of weak reference to a
6640// target object. In particular, objects that can only be reached from roots via
6641// WSR edges during serialization of AOT snapshots should not be serialized, but
6642// instead references to these objects should be replaced with a reference to
6643// the provided replacement object.
6644//
6645// Of course, the target object may still be serialized if there are paths to
6646// the object from the roots that do not go through one of these objects. In
6647// this case, references through WSRs are serialized as direct references to
6648// the target.
6649//
6650// Unfortunately a WSR is not a proxy for the original object, so WSRs may
6651// only currently be used with ObjectPtr fields. To ease this situation for
6652// fields that are normally a non-ObjectPtr type outside of the precompiler,
6653// use the following macros, which avoid the need to adjust other code to
6654// handle the WSR case:
6655//
6656// * WSR_*POINTER_FIELD() in raw_object.h (i.e., just append WSR_ to the
6657// original field declaration).
6658// * PRECOMPILER_WSR_FIELD_DECLARATION() in object.h
6659// * PRECOMPILER_WSR_FIELD_DEFINITION() in object.cc
6661 public:
6662 ObjectPtr target() const { return TargetOf(ptr()); }
6663 static ObjectPtr TargetOf(const WeakSerializationReferencePtr obj) {
6664 return obj->untag()->target();
6665 }
6666
6668#if defined(DART_PRECOMPILER)
6669 if (obj->IsHeapObject() && obj->IsWeakSerializationReference()) {
6670 return TargetOf(static_cast<WeakSerializationReferencePtr>(obj));
6671 }
6672#endif
6673 return obj;
6674 }
6675 static ObjectPtr Unwrap(const Object& obj) { return Unwrap(obj.ptr()); }
6676 static ObjectPtr UnwrapIfTarget(ObjectPtr obj) { return Unwrap(obj); }
6677 static ObjectPtr UnwrapIfTarget(const Object& obj) { return Unwrap(obj); }
6678
6679 static intptr_t InstanceSize() {
6681 }
6682
6683 // Returns an ObjectPtr as the target may not need wrapping (e.g., it
6684 // is guaranteed to be serialized).
6685 static ObjectPtr New(const Object& target, const Object& replacement);
6686
6687 private:
6689
6690 ObjectPtr replacement() const { return untag()->replacement(); }
6691
6692 friend class Class;
6693};
6694
6695class WeakArray : public Object {
6696 public:
6697 intptr_t Length() const { return LengthOf(ptr()); }
6698 static inline intptr_t LengthOf(const WeakArrayPtr array);
6699
6700 static intptr_t length_offset() {
6701 return OFFSET_OF(UntaggedWeakArray, length_);
6702 }
6703 static intptr_t data_offset() {
6705 }
6706 static intptr_t element_offset(intptr_t index) {
6708 kBytesPerElement * index;
6709 }
6710 static intptr_t index_at_offset(intptr_t offset_in_bytes) {
6711 intptr_t index = (offset_in_bytes - data_offset()) / kBytesPerElement;
6712 ASSERT(index >= 0);
6713 return index;
6714 }
6715
6717 static intptr_t elements_start_offset() { return WeakArray::data_offset(); }
6718
6719 static constexpr intptr_t kElementSize = kCompressedWordSize;
6720 };
6721
6722 ObjectPtr At(intptr_t index) const { return untag()->element(index); }
6723 void SetAt(intptr_t index, const Object& value) const {
6724 untag()->set_element(index, value.ptr());
6725 }
6726
6727 // Access to the array with acquire release semantics.
6728 ObjectPtr AtAcquire(intptr_t index) const {
6729 return untag()->element<std::memory_order_acquire>(index);
6730 }
6731 void SetAtRelease(intptr_t index, const Object& value) const {
6732 untag()->set_element<std::memory_order_release>(index, value.ptr());
6733 }
6734
6735 static constexpr intptr_t kBytesPerElement = kCompressedWordSize;
6736 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
6737
6738 static constexpr bool IsValidLength(intptr_t length) {
6739 return 0 <= length && length <= kMaxElements;
6740 }
6741
6742 static intptr_t InstanceSize() {
6743 ASSERT(sizeof(UntaggedWeakArray) ==
6745 return 0;
6746 }
6747
6748 static constexpr intptr_t InstanceSize(intptr_t len) {
6750 (len * kBytesPerElement));
6751 }
6752
6753 static WeakArrayPtr New(intptr_t length, Heap::Space space = Heap::kNew);
6754
6755 private:
6757 friend class Class;
6758 friend class Object;
6759};
6760
6761class Code : public Object {
6762 public:
6763 // When dual mapping, this returns the executable view.
6764 InstructionsPtr active_instructions() const {
6765#if defined(DART_PRECOMPILED_RUNTIME)
6766 UNREACHABLE();
6767 return nullptr;
6768#else
6769 return untag()->active_instructions();
6770#endif
6771 }
6772
6773 // When dual mapping, these return the executable view.
6774 InstructionsPtr instructions() const { return untag()->instructions(); }
6775 static InstructionsPtr InstructionsOf(const CodePtr code) {
6776 return code->untag()->instructions();
6777 }
6778
6779 static intptr_t instructions_offset() {
6780 return OFFSET_OF(UntaggedCode, instructions_);
6781 }
6782#if !defined(DART_PRECOMPILED_RUNTIME)
6783 static intptr_t active_instructions_offset() {
6784 return OFFSET_OF(UntaggedCode, active_instructions_);
6785 }
6786#endif
6787
6789
6790 static const char* EntryKindToCString(EntryKind kind);
6791 static bool ParseEntryKind(const char* str, EntryKind* out);
6792
6794 switch (kind) {
6795 case EntryKind::kNormal:
6796 return OFFSET_OF(UntaggedCode, entry_point_);
6797 case EntryKind::kUnchecked:
6798 return OFFSET_OF(UntaggedCode, unchecked_entry_point_);
6799 case EntryKind::kMonomorphic:
6800 return OFFSET_OF(UntaggedCode, monomorphic_entry_point_);
6801 case EntryKind::kMonomorphicUnchecked:
6802 return OFFSET_OF(UntaggedCode, monomorphic_unchecked_entry_point_);
6803 default:
6804 UNREACHABLE();
6805 }
6806 }
6807
6808 ObjectPoolPtr object_pool() const { return untag()->object_pool(); }
6809 static intptr_t object_pool_offset() {
6810 return OFFSET_OF(UntaggedCode, object_pool_);
6811 }
6812
6813 intptr_t pointer_offsets_length() const {
6814 return PtrOffBits::decode(untag()->state_bits_);
6815 }
6816
6817 bool is_optimized() const {
6818 return OptimizedBit::decode(untag()->state_bits_);
6819 }
6820 void set_is_optimized(bool value) const;
6821 static bool IsOptimized(CodePtr code) {
6822 return Code::OptimizedBit::decode(code->untag()->state_bits_);
6823 }
6824
6825 bool is_force_optimized() const {
6826 return ForceOptimizedBit::decode(untag()->state_bits_);
6827 }
6828 void set_is_force_optimized(bool value) const;
6829
6830 bool is_alive() const { return AliveBit::decode(untag()->state_bits_); }
6831 void set_is_alive(bool value) const;
6832
6833 bool is_discarded() const { return IsDiscarded(ptr()); }
6834 static bool IsDiscarded(const CodePtr code) {
6835 return DiscardedBit::decode(code->untag()->state_bits_);
6836 }
6837 void set_is_discarded(bool value) const;
6838
6839 bool HasMonomorphicEntry() const { return HasMonomorphicEntry(ptr()); }
6840 static bool HasMonomorphicEntry(const CodePtr code) {
6841#if defined(DART_PRECOMPILED_RUNTIME)
6842 return code->untag()->entry_point_ !=
6843 code->untag()->monomorphic_entry_point_;
6844#else
6845 return Instructions::HasMonomorphicEntry(InstructionsOf(code));
6846#endif
6847 }
6848
6849 // Returns the payload start of [instructions()].
6850 uword PayloadStart() const { return PayloadStartOf(ptr()); }
6851 static uword PayloadStartOf(const CodePtr code) {
6852#if defined(DART_PRECOMPILED_RUNTIME)
6853 if (IsUnknownDartCode(code)) return 0;
6854 const uword entry_offset = HasMonomorphicEntry(code)
6855 ? Instructions::kPolymorphicEntryOffsetAOT
6856 : 0;
6857 return EntryPointOf(code) - entry_offset;
6858#else
6859 return Instructions::PayloadStart(InstructionsOf(code));
6860#endif
6861 }
6862
6863 // Returns the entry point of [instructions()].
6864 uword EntryPoint() const { return EntryPointOf(ptr()); }
6865 static uword EntryPointOf(const CodePtr code) {
6866#if defined(DART_PRECOMPILED_RUNTIME)
6867 return code->untag()->entry_point_;
6868#else
6869 return Instructions::EntryPoint(InstructionsOf(code));
6870#endif
6871 }
6872
6873 static uword UncheckedEntryPointOf(const CodePtr code) {
6874 return code->untag()->unchecked_entry_point_;
6875 }
6876
6877 // Returns the unchecked entry point of [instructions()].
6879#if defined(DART_PRECOMPILED_RUNTIME)
6880 return untag()->unchecked_entry_point_;
6881#else
6882 return EntryPoint() + untag()->unchecked_offset_;
6883#endif
6884 }
6885 // Returns the monomorphic entry point of [instructions()].
6887#if defined(DART_PRECOMPILED_RUNTIME)
6888 return untag()->monomorphic_entry_point_;
6889#else
6890 return Instructions::MonomorphicEntryPoint(instructions());
6891#endif
6892 }
6893 // Returns the unchecked monomorphic entry point of [instructions()].
6895#if defined(DART_PRECOMPILED_RUNTIME)
6896 return untag()->monomorphic_unchecked_entry_point_;
6897#else
6898 return MonomorphicEntryPoint() + untag()->unchecked_offset_;
6899#endif
6900 }
6901
6902 // Returns the size of [instructions()].
6903 uword Size() const { return PayloadSizeOf(ptr()); }
6904 static uword PayloadSizeOf(const CodePtr code) {
6905#if defined(DART_PRECOMPILED_RUNTIME)
6906 if (IsUnknownDartCode(code)) return kUwordMax;
6907 return code->untag()->instructions_length_;
6908#else
6909 return Instructions::Size(InstructionsOf(code));
6910#endif
6911 }
6912
6913 ObjectPoolPtr GetObjectPool() const;
6914 // Returns whether the given PC address is in [instructions()].
6916 return ContainsInstructionAt(ptr(), addr);
6917 }
6918
6919 // Returns whether the given PC address is in [InstructionsOf(code)].
6920 static bool ContainsInstructionAt(const CodePtr code, uword pc) {
6921 return UntaggedCode::ContainsPC(code, pc);
6922 }
6923
6924 // Returns true if there is a debugger breakpoint set in this code object.
6925 bool HasBreakpoint() const;
6926
6927 PcDescriptorsPtr pc_descriptors() const { return untag()->pc_descriptors(); }
6928 void set_pc_descriptors(const PcDescriptors& descriptors) const {
6929 ASSERT(descriptors.IsOld());
6930 untag()->set_pc_descriptors(descriptors.ptr());
6931 }
6932
6933 CodeSourceMapPtr code_source_map() const {
6934 return untag()->code_source_map();
6935 }
6936
6937 void set_code_source_map(const CodeSourceMap& code_source_map) const {
6938 ASSERT(code_source_map.IsOld());
6939 untag()->set_code_source_map(code_source_map.ptr());
6940 }
6941
6942 // Array of DeoptInfo objects.
6943 ArrayPtr deopt_info_array() const {
6944#if defined(DART_PRECOMPILED_RUNTIME)
6945 UNREACHABLE();
6946 return nullptr;
6947#else
6948 return untag()->deopt_info_array();
6949#endif
6950 }
6951 void set_deopt_info_array(const Array& array) const;
6952
6953#if !defined(DART_PRECOMPILED_RUNTIME)
6954 intptr_t num_variables() const;
6955 void set_num_variables(intptr_t num_variables) const;
6956#endif
6957
6958#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
6959 TypedDataPtr catch_entry_moves_maps() const;
6960 void set_catch_entry_moves_maps(const TypedData& maps) const;
6961#endif
6962
6963 CompressedStackMapsPtr compressed_stackmaps() const {
6964 return untag()->compressed_stackmaps();
6965 }
6966 void set_compressed_stackmaps(const CompressedStackMaps& maps) const;
6967
6969 kPcRelativeCall = 1,
6970 kPcRelativeTTSCall = 2,
6971 kPcRelativeTailCall = 3,
6972 kCallViaCode = 4,
6973 };
6974
6978 };
6979
6981 kSCallTableKindAndOffset = 0,
6982 kSCallTableCodeOrTypeTarget = 1,
6983 kSCallTableFunctionTarget = 2,
6984 kSCallTableEntryLength = 3,
6985 };
6986
6987 enum class PoolAttachment {
6988 kAttachPool,
6989 kNotAttachPool,
6990 };
6991
6992 class KindField : public BitField<intptr_t, CallKind, 0, 3> {};
6994 : public BitField<intptr_t, CallEntryPoint, KindField::kNextBit, 1> {};
6996 : public BitField<intptr_t, intptr_t, EntryPointField::kNextBit, 26> {};
6997
6998 void set_static_calls_target_table(const Array& value) const;
6999 ArrayPtr static_calls_target_table() const {
7000#if defined(DART_PRECOMPILED_RUNTIME)
7001 UNREACHABLE();
7002 return nullptr;
7003#else
7004 return untag()->static_calls_target_table();
7005#endif
7006 }
7007
7008 TypedDataPtr GetDeoptInfoAtPc(uword pc,
7009 ICData::DeoptReasonId* deopt_reason,
7010 uint32_t* deopt_flags) const;
7011
7012 // Returns null if there is no static call at 'pc'.
7013 FunctionPtr GetStaticCallTargetFunctionAt(uword pc) const;
7014 // Aborts if there is no static call at 'pc'.
7015 void SetStaticCallTargetCodeAt(uword pc, const Code& code) const;
7016 void SetStubCallTargetCodeAt(uword pc, const Code& code) const;
7017
7018 void Disassemble(DisassemblyFormatter* formatter = nullptr) const;
7019
7020#if defined(INCLUDE_IL_PRINTER)
7021 class Comments : public ZoneAllocated, public CodeComments {
7022 public:
7023 static Comments& New(intptr_t count);
7024
7025 intptr_t Length() const override;
7026
7027 void SetPCOffsetAt(intptr_t idx, intptr_t pc_offset);
7028 void SetCommentAt(intptr_t idx, const String& comment);
7029
7030 intptr_t PCOffsetAt(intptr_t idx) const override;
7031 const char* CommentAt(intptr_t idx) const override;
7032
7033 private:
7034 explicit Comments(const Array& comments);
7035
7036 // Layout of entries describing comments.
7037 enum {
7038 kPCOffsetEntry = 0, // PC offset to a comment as a Smi.
7039 kCommentEntry, // Comment text as a String.
7040 kNumberOfEntries
7041 };
7042
7043 const Array& comments_;
7044 String& string_;
7045
7046 friend class Code;
7047
7048 DISALLOW_COPY_AND_ASSIGN(Comments);
7049 };
7050
7051 const CodeComments& comments() const;
7052 void set_comments(const CodeComments& comments) const;
7053#endif // defined(INCLUDE_IL_PRINTER)
7054
7056#if defined(PRODUCT)
7057 UNREACHABLE();
7058 return nullptr;
7059#else
7060 return untag()->return_address_metadata();
7061#endif
7062 }
7063 // Sets |return_address_metadata|.
7064 void SetPrologueOffset(intptr_t offset) const;
7065 // Returns -1 if no prologue offset is available.
7066 intptr_t GetPrologueOffset() const;
7067
7068 ArrayPtr inlined_id_to_function() const;
7069 void set_inlined_id_to_function(const Array& value) const;
7070
7071 // Provides the call stack at the given pc offset, with the top-of-stack in
7072 // the last element and the root function (this) as the first element, along
7073 // with the corresponding source positions. Note the token position for each
7074 // function except the top-of-stack is the position of the call to the next
7075 // function. The stack will be empty if we lack the metadata to produce it,
7076 // which happens for stub code.
7077 // The pc offset is interpreted as an instruction address (as needed by the
7078 // disassembler or the top frame of a profiler sample).
7079 void GetInlinedFunctionsAtInstruction(
7080 intptr_t pc_offset,
7082 GrowableArray<TokenPosition>* token_positions) const;
7083 // Same as above, except the pc is interpreted as a return address (as needed
7084 // for a stack trace or the bottom frames of a profiler sample).
7086 intptr_t pc_offset,
7088 GrowableArray<TokenPosition>* token_positions) const {
7089 GetInlinedFunctionsAtInstruction(pc_offset - 1, functions, token_positions);
7090 }
7091
7092 NOT_IN_PRODUCT(void PrintJSONInlineIntervals(JSONObject* object) const);
7093 void DumpInlineIntervals() const;
7094 void DumpSourcePositions(bool relative_addresses = false) const;
7095
7096 LocalVarDescriptorsPtr var_descriptors() const {
7097#if defined(PRODUCT)
7098 UNREACHABLE();
7099 return nullptr;
7100#else
7101 return untag()->var_descriptors();
7102#endif
7103 }
7105#if defined(PRODUCT)
7106 UNREACHABLE();
7107#else
7108 ASSERT(value.IsOld());
7109 untag()->set_var_descriptors(value.ptr());
7110#endif
7111 }
7112
7113 // Will compute local var descriptors if necessary.
7114 LocalVarDescriptorsPtr GetLocalVarDescriptors() const;
7115
7116 ExceptionHandlersPtr exception_handlers() const {
7117 return untag()->exception_handlers();
7118 }
7119 void set_exception_handlers(const ExceptionHandlers& handlers) const {
7120 ASSERT(handlers.IsOld());
7121 untag()->set_exception_handlers(handlers.ptr());
7122 }
7123
7124 // WARNING: function() returns the owner which is not guaranteed to be
7125 // a Function. It is up to the caller to guarantee it isn't a stub, class,
7126 // or something else.
7127 // TODO(turnidge): Consider dropping this function and making
7128 // everybody use owner(). Currently this function is misused - even
7129 // while generating the snapshot.
7130 FunctionPtr function() const {
7131 ASSERT(IsFunctionCode());
7132 return Function::RawCast(owner());
7133 }
7134
7136 return WeakSerializationReference::Unwrap(untag()->owner());
7137 }
7138 void set_owner(const Object& owner) const;
7139
7140 classid_t OwnerClassId() const { return OwnerClassIdOf(ptr()); }
7141 static classid_t OwnerClassIdOf(CodePtr raw) {
7142 ObjectPtr owner = WeakSerializationReference::Unwrap(raw->untag()->owner());
7143 if (!owner->IsHeapObject()) {
7144 return RawSmiValue(static_cast<SmiPtr>(owner));
7145 }
7146 return owner->GetClassId();
7147 }
7148
7149 static intptr_t owner_offset() { return OFFSET_OF(UntaggedCode, owner_); }
7150
7151 // We would have a VisitPointers function here to traverse all the
7152 // embedded objects in the instructions using pointer_offsets.
7153
7154 static constexpr intptr_t kBytesPerElement =
7155 sizeof(reinterpret_cast<UntaggedCode*>(kOffsetOfPtr)->data()[0]);
7156 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
7157
7159 static intptr_t elements_start_offset() { return sizeof(UntaggedCode); }
7160 static constexpr intptr_t kElementSize = kBytesPerElement;
7161 };
7162
7163 static intptr_t InstanceSize() {
7164 ASSERT(sizeof(UntaggedCode) ==
7166 return 0;
7167 }
7168 static intptr_t InstanceSize(intptr_t len) {
7169 ASSERT(0 <= len && len <= kMaxElements);
7170 return RoundedAllocationSize(sizeof(UntaggedCode) +
7171 (len * kBytesPerElement));
7172 }
7173#if !defined(DART_PRECOMPILED_RUNTIME)
7174 // Finalizes the generated code, by generating various kinds of metadata (e.g.
7175 // stack maps, pc descriptors, ...) and attach them to a newly generated
7176 // [Code] object.
7177 //
7178 // If Code::PoolAttachment::kAttachPool is specified for [pool_attachment]
7179 // then a new [ObjectPool] will be attached to the code object as well.
7180 // Otherwise the caller is responsible for doing this via
7181 // `Object::set_object_pool()`.
7182 static CodePtr FinalizeCode(FlowGraphCompiler* compiler,
7183 compiler::Assembler* assembler,
7184 PoolAttachment pool_attachment,
7185 bool optimized,
7187
7188 // Notifies all active [CodeObserver]s.
7189 static void NotifyCodeObservers(const Code& code, bool optimized);
7190 static void NotifyCodeObservers(const Function& function,
7191 const Code& code,
7192 bool optimized);
7193 static void NotifyCodeObservers(const char* name,
7194 const Code& code,
7195 bool optimized);
7196
7197 // Calls [FinalizeCode] and also notifies [CodeObserver]s.
7198 static CodePtr FinalizeCodeAndNotify(const Function& function,
7200 compiler::Assembler* assembler,
7201 PoolAttachment pool_attachment,
7202 bool optimized = false,
7203 CodeStatistics* stats = nullptr);
7204 static CodePtr FinalizeCodeAndNotify(const char* name,
7206 compiler::Assembler* assembler,
7207 PoolAttachment pool_attachment,
7208 bool optimized = false,
7209 CodeStatistics* stats = nullptr);
7210
7211#endif
7212 static CodePtr FindCode(uword pc, int64_t timestamp);
7213 static CodePtr FindCodeUnsafe(uword pc);
7214
7215 int32_t GetPointerOffsetAt(int index) const {
7216 NoSafepointScope no_safepoint;
7217 return *PointerOffsetAddrAt(index);
7218 }
7219 TokenPosition GetTokenIndexOfPC(uword pc) const;
7220
7221 // Find pc, return 0 if not found.
7222 uword GetPcForDeoptId(intptr_t deopt_id,
7223 UntaggedPcDescriptors::Kind kind) const;
7224 intptr_t GetDeoptIdForOsr(uword pc) const;
7225
7226 uint32_t Hash() const;
7227 const char* Name() const;
7228 const char* QualifiedName(const NameFormattingParams& params) const;
7229
7230 int64_t compile_timestamp() const {
7231#if defined(PRODUCT)
7232 return 0;
7233#else
7234 return untag()->compile_timestamp_;
7235#endif
7236 }
7237
7238 bool IsStubCode() const;
7239 bool IsAllocationStubCode() const;
7240 bool IsTypeTestStubCode() const;
7241 bool IsFunctionCode() const;
7242
7243 // Returns true if this Code object represents
7244 // Dart function code without any additional information.
7245 bool IsUnknownDartCode() const { return IsUnknownDartCode(ptr()); }
7246 static bool IsUnknownDartCode(CodePtr code);
7247
7248 void DisableDartCode() const;
7249
7250 void DisableStubCode(bool is_cls_parameterized) const;
7251
7252 void Enable() const {
7253 if (!IsDisabled()) return;
7254 ResetActiveInstructions();
7255 }
7256
7257 bool IsDisabled() const { return IsDisabled(ptr()); }
7258 static bool IsDisabled(CodePtr code) {
7259#if defined(DART_PRECOMPILED_RUNTIME)
7260 UNREACHABLE();
7261 return false;
7262#else
7263 return code->untag()->instructions() !=
7264 code->untag()->active_instructions();
7265#endif
7266 }
7267
7268 void set_object_pool(ObjectPoolPtr object_pool) const {
7269 untag()->set_object_pool(object_pool);
7270 }
7271
7272 private:
7273 void set_state_bits(intptr_t bits) const;
7274
7275 friend class UntaggedObject; // For UntaggedObject::SizeFromClass().
7276 friend class UntaggedCode;
7277 friend struct RelocatorTestHelper;
7278
7279 enum {
7280 kOptimizedBit = 0,
7281 kForceOptimizedBit = 1,
7282 kAliveBit = 2,
7283 kDiscardedBit = 3,
7284 kPtrOffBit = 4,
7285 kPtrOffSize = kBitsPerInt32 - kPtrOffBit,
7286 };
7287
7288 class OptimizedBit : public BitField<int32_t, bool, kOptimizedBit, 1> {};
7289
7290 // Force-optimized is true if the Code was generated for a function with
7291 // Function::ForceOptimize().
7292 class ForceOptimizedBit
7293 : public BitField<int32_t, bool, kForceOptimizedBit, 1> {};
7294
7295 class AliveBit : public BitField<int32_t, bool, kAliveBit, 1> {};
7296
7297 // Set by precompiler if this Code object doesn't contain
7298 // useful information besides instructions and compressed stack map.
7299 // Such objects are serialized in a shorter form and replaced with
7300 // StubCode::UnknownDartCode() during snapshot deserialization.
7301 class DiscardedBit : public BitField<int32_t, bool, kDiscardedBit, 1> {};
7302
7303 class PtrOffBits
7304 : public BitField<int32_t, intptr_t, kPtrOffBit, kPtrOffSize> {};
7305
7306 static constexpr intptr_t kEntrySize = sizeof(int32_t); // NOLINT
7307
7308 void set_compile_timestamp(int64_t timestamp) const {
7309#if defined(PRODUCT)
7310 UNREACHABLE();
7311#else
7312 StoreNonPointer(&untag()->compile_timestamp_, timestamp);
7313#endif
7314 }
7315
7316 // Initializes the cached entrypoint addresses in [code] as calculated
7317 // from [instructions] and [unchecked_offset].
7318 static void InitializeCachedEntryPointsFrom(CodePtr code,
7319 InstructionsPtr instructions,
7320 uint32_t unchecked_offset);
7321
7322 // Sets [active_instructions_] to [instructions] and updates the cached
7323 // entry point addresses.
7324 void SetActiveInstructions(const Instructions& instructions,
7325 uint32_t unchecked_offset) const;
7326 void SetActiveInstructionsSafe(const Instructions& instructions,
7327 uint32_t unchecked_offset) const;
7328
7329 // Resets [active_instructions_] to its original value of [instructions_] and
7330 // updates the cached entry point addresses to match.
7331 void ResetActiveInstructions() const;
7332
7333 void set_instructions(const Instructions& instructions) const {
7334 ASSERT(Thread::Current()->IsDartMutatorThread() || !is_alive());
7335 untag()->set_instructions(instructions.ptr());
7336 }
7337#if !defined(DART_PRECOMPILED_RUNTIME)
7338 void set_unchecked_offset(uword offset) const {
7339 StoreNonPointer(&untag()->unchecked_offset_, offset);
7340 }
7341#endif
7342
7343 // Returns the unchecked entry point offset for [instructions_].
7344 uint32_t UncheckedEntryPointOffset() const {
7345 return UncheckedEntryPointOffsetOf(ptr());
7346 }
7347 static uint32_t UncheckedEntryPointOffsetOf(CodePtr code) {
7348#if defined(DART_PRECOMPILED_RUNTIME)
7349 UNREACHABLE();
7350#else
7351 return code->untag()->unchecked_offset_;
7352#endif
7353 }
7354
7355 void set_pointer_offsets_length(intptr_t value) {
7356 // The number of fixups is limited to 1-billion.
7358 set_state_bits(PtrOffBits::update(value, untag()->state_bits_));
7359 }
7360 int32_t* PointerOffsetAddrAt(int index) const {
7361 ASSERT(index >= 0);
7362 ASSERT(index < pointer_offsets_length());
7363 // TODO(iposva): Unit test is missing for this functionality.
7364 return &UnsafeMutableNonPointer(untag()->data())[index];
7365 }
7366 void SetPointerOffsetAt(int index, int32_t offset_in_instructions) {
7367 NoSafepointScope no_safepoint;
7368 *PointerOffsetAddrAt(index) = offset_in_instructions;
7369 }
7370
7371 intptr_t BinarySearchInSCallTable(uword pc) const;
7372 static CodePtr LookupCodeInIsolateGroup(IsolateGroup* isolate_group,
7373 uword pc);
7374
7375 // New is a private method as RawInstruction and RawCode objects should
7376 // only be created using the Code::FinalizeCode method. This method creates
7377 // the RawInstruction and RawCode objects, sets up the pointer offsets
7378 // and links the two in a GC safe manner.
7379 static CodePtr New(intptr_t pointer_offsets_length);
7380
7382 friend class Class;
7383 friend class CodeTestHelper;
7384 friend class StubCode; // for set_object_pool
7385 friend class Precompiler; // for set_object_pool
7389 friend class Deserializer; // for InitializeCachedEntryPointsFrom
7390 friend class StubCode; // for set_object_pool
7391 friend class MegamorphicCacheTable; // for set_object_pool
7392 friend class CodePatcher; // for set_instructions
7393 friend class ProgramVisitor; // for set_instructions
7394 // So that the UntaggedFunction pointer visitor can determine whether code the
7395 // function points to is optimized.
7396 friend class UntaggedFunction;
7397 friend class CallSiteResetter;
7398 friend class CodeKeyValueTrait; // for UncheckedEntryPointOffset
7399 friend class InstanceCall; // for StorePointerUnaligned
7400 friend class StaticCall; // for StorePointerUnaligned
7401 friend void DumpStackFrame(intptr_t frame_index, uword pc, uword fp);
7402};
7403
7404class Context : public Object {
7405 public:
7406 ContextPtr parent() const { return untag()->parent(); }
7407 void set_parent(const Context& parent) const {
7408 untag()->set_parent(parent.ptr());
7409 }
7410 static intptr_t parent_offset() {
7411 return OFFSET_OF(UntaggedContext, parent_);
7412 }
7413
7414 intptr_t num_variables() const { return untag()->num_variables_; }
7415 static intptr_t num_variables_offset() {
7416 return OFFSET_OF(UntaggedContext, num_variables_);
7417 }
7418 static intptr_t NumVariables(const ContextPtr context) {
7419 return context->untag()->num_variables_;
7420 }
7421
7422 ObjectPtr At(intptr_t context_index) const {
7423 return untag()->element(context_index);
7424 }
7425 inline void SetAt(intptr_t context_index, const Object& value) const;
7426
7427 intptr_t GetLevel() const;
7428
7429 void Dump(int indent = 0) const;
7430
7431 static constexpr intptr_t kBytesPerElement = kCompressedWordSize;
7432 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
7433
7435 static intptr_t elements_start_offset() { return sizeof(UntaggedContext); }
7436 static constexpr intptr_t kElementSize = kBytesPerElement;
7437 };
7438
7439 static intptr_t variable_offset(intptr_t context_index) {
7441 (kBytesPerElement * context_index);
7442 }
7443
7444 static bool IsValidLength(intptr_t len) {
7446 }
7447
7448 static intptr_t InstanceSize() {
7449 ASSERT(sizeof(UntaggedContext) ==
7451 return 0;
7452 }
7453
7454 static intptr_t InstanceSize(intptr_t len) {
7455 ASSERT(IsValidLength(len));
7456 return RoundedAllocationSize(sizeof(UntaggedContext) +
7457 (len * kBytesPerElement));
7458 }
7459
7460 static ContextPtr New(intptr_t num_variables, Heap::Space space = Heap::kNew);
7461
7462 private:
7463 void set_num_variables(intptr_t num_variables) const {
7464 StoreNonPointer(&untag()->num_variables_, num_variables);
7465 }
7466
7468 friend class Class;
7469 friend class Object;
7470};
7471
7472// The ContextScope class makes it possible to delay the compilation of a local
7473// function until it is invoked. A ContextScope instance collects the local
7474// variables that are referenced by the local function to be compiled and that
7475// belong to the outer scopes, that is, to the local scopes of (possibly nested)
7476// functions enclosing the local function. Each captured variable is represented
7477// by its token position in the source, its name, its type, its allocation index
7478// in the context, and its context level. The function nesting level and loop
7479// nesting level are not preserved, since they are only used until the context
7480// level is assigned. In addition the ContextScope has a field 'is_implicit'
7481// which is true if the ContextScope was created for an implicit closure.
7482class ContextScope : public Object {
7483 public:
7484 intptr_t num_variables() const { return untag()->num_variables_; }
7485
7486 TokenPosition TokenIndexAt(intptr_t scope_index) const;
7487 void SetTokenIndexAt(intptr_t scope_index, TokenPosition token_pos) const;
7488
7489 TokenPosition DeclarationTokenIndexAt(intptr_t scope_index) const;
7490 void SetDeclarationTokenIndexAt(intptr_t scope_index,
7491 TokenPosition declaration_token_pos) const;
7492
7493 StringPtr NameAt(intptr_t scope_index) const;
7494 void SetNameAt(intptr_t scope_index, const String& name) const;
7495
7496 void ClearFlagsAt(intptr_t scope_index) const;
7497
7498 intptr_t LateInitOffsetAt(intptr_t scope_index) const;
7499 void SetLateInitOffsetAt(intptr_t scope_index,
7500 intptr_t late_init_offset) const;
7501
7502#define DECLARE_FLAG_ACCESSORS(Name) \
7503 bool Is##Name##At(intptr_t scope_index) const; \
7504 void SetIs##Name##At(intptr_t scope_index, bool value) const;
7505
7507#undef DECLARE_FLAG_ACCESSORS
7508
7509 AbstractTypePtr TypeAt(intptr_t scope_index) const;
7510 void SetTypeAt(intptr_t scope_index, const AbstractType& type) const;
7511
7512 intptr_t CidAt(intptr_t scope_index) const;
7513 void SetCidAt(intptr_t scope_index, intptr_t cid) const;
7514
7515 intptr_t ContextIndexAt(intptr_t scope_index) const;
7516 void SetContextIndexAt(intptr_t scope_index, intptr_t context_index) const;
7517
7518 intptr_t ContextLevelAt(intptr_t scope_index) const;
7519 void SetContextLevelAt(intptr_t scope_index, intptr_t context_level) const;
7520
7521 intptr_t KernelOffsetAt(intptr_t scope_index) const;
7522 void SetKernelOffsetAt(intptr_t scope_index, intptr_t kernel_offset) const;
7523
7524 static constexpr intptr_t kBytesPerElement =
7525 sizeof(UntaggedContextScope::VariableDesc);
7526 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
7527
7529 static intptr_t elements_start_offset() {
7530 return sizeof(UntaggedContextScope);
7531 }
7532 static constexpr intptr_t kElementSize = kBytesPerElement;
7533 };
7534
7535 static intptr_t InstanceSize() {
7536 ASSERT(sizeof(UntaggedContextScope) ==
7538 return 0;
7539 }
7540
7541 static intptr_t InstanceSize(intptr_t len) {
7542 ASSERT(0 <= len && len <= kMaxElements);
7544 (len * kBytesPerElement));
7545 }
7546
7547 static ContextScopePtr New(intptr_t num_variables, bool is_implicit);
7548
7549 private:
7550 void set_num_variables(intptr_t num_variables) const {
7551 StoreNonPointer(&untag()->num_variables_, num_variables);
7552 }
7553
7554 void set_is_implicit(bool is_implicit) const {
7555 StoreNonPointer(&untag()->is_implicit_, is_implicit);
7556 }
7557
7558 const UntaggedContextScope::VariableDesc* VariableDescAddr(
7559 intptr_t index) const {
7560 ASSERT((index >= 0) && (index < num_variables()));
7561 return untag()->VariableDescAddr(index);
7562 }
7563
7564 bool GetFlagAt(intptr_t scope_index, intptr_t bit_index) const;
7565 void SetFlagAt(intptr_t scope_index, intptr_t bit_index, bool value) const;
7566
7568 friend class Class;
7569 friend class Object;
7570};
7571
7572// Class of special sentinel values:
7573// - Object::sentinel() is a value that cannot be produced by Dart code.
7574// It can be used to mark special values, for example to distinguish
7575// "uninitialized" fields.
7576// - Object::transition_sentinel() is a value marking that we are transitioning
7577// from sentinel, e.g., computing a field value. Used to detect circular
7578// initialization of static fields.
7579// - Object::unknown_constant() and Object::non_constant() are optimizing
7580// compiler's constant propagation constants.
7581// - Object::optimized_out() result from deopt environment pruning or failure
7582// to capture variables in a closure's context
7583class Sentinel : public Object {
7584 public:
7585 static intptr_t InstanceSize() {
7587 }
7588
7589 static SentinelPtr New();
7590
7591 private:
7593 friend class Class;
7594 friend class Object;
7595};
7596
7598 public:
7599 static constexpr intptr_t kInitialCapacity = 16;
7600 static constexpr intptr_t kSpreadFactor = 7;
7601 static constexpr double kLoadFactor = 0.50;
7602
7607 };
7608
7609 ArrayPtr buckets() const;
7610 void set_buckets(const Array& buckets) const;
7611
7612 intptr_t mask() const;
7613 void set_mask(intptr_t mask) const;
7614
7615 intptr_t filled_entry_count() const;
7616 void set_filled_entry_count(intptr_t num) const;
7617
7618 static intptr_t buckets_offset() {
7619 return OFFSET_OF(UntaggedMegamorphicCache, buckets_);
7620 }
7621 static intptr_t mask_offset() {
7622 return OFFSET_OF(UntaggedMegamorphicCache, mask_);
7623 }
7625 return OFFSET_OF(UntaggedMegamorphicCache, args_descriptor_);
7626 }
7627
7628 static MegamorphicCachePtr New(const String& target_name,
7630
7631 void EnsureContains(const Smi& class_id, const Object& target) const;
7632 ObjectPtr Lookup(const Smi& class_id) const;
7633
7634 static intptr_t InstanceSize() {
7636 }
7637
7638 private:
7639 friend class Class;
7641 friend class ProgramVisitor;
7642
7643 static MegamorphicCachePtr New();
7644
7645 // The caller must hold IsolateGroup::type_feedback_mutex().
7646 void InsertLocked(const Smi& class_id, const Object& target) const;
7647 void EnsureCapacityLocked() const;
7648 ObjectPtr LookupLocked(const Smi& class_id) const;
7649
7650 void InsertEntryLocked(const Smi& class_id, const Object& target) const;
7651
7652 static inline void SetEntry(const Array& array,
7653 intptr_t index,
7654 const Smi& class_id,
7655 const Object& target);
7656
7657 static inline ObjectPtr GetClassId(const Array& array, intptr_t index);
7658 static inline ObjectPtr GetTargetFunction(const Array& array, intptr_t index);
7659
7661};
7662
7663class SubtypeTestCache : public Object {
7664 public:
7665 // The contents of the backing array storage is a number of entry tuples.
7666 // Any entry that is unoccupied has the null value as its first component.
7667 //
7668 // If the cache is linear, the entries can be accessed in a linear fashion:
7669 // all occupied entries come first, followed by at least one unoccupied
7670 // entry to mark the end of the cache. Guaranteeing at least one unoccupied
7671 // entry avoids the need for a length check when iterating over the contents
7672 // of the linear cache in stubs.
7673 //
7674 // If the cache is hash-based, the array is instead treated as a hash table
7675 // probed by using a hash value derived from the inputs.
7676
7677 // The tuple of values stored in a given entry.
7678 //
7679 // Note that occupied entry contents are never modified. That means reading a
7680 // non-null instance cid or signature means the rest of the entry can be
7681 // loaded without worrying about concurrent modification. Thus, we always set
7682 // the instance cid or signature last when making an occupied entry.
7683 //
7684 // Also note that each STC, when created, has a set number of used inputs.
7685 // The value of any unused input is unspecified, so for example, if the
7686 // STC only uses 3 inputs, then no assumptions can be made about the value
7687 // stored in the instantiator type arguments slot.
7688 enum Entries {
7689 kInstanceCidOrSignature = 0,
7690 kInstanceTypeArguments = 1,
7691 kInstantiatorTypeArguments = 2,
7692 kFunctionTypeArguments = 3,
7693 kInstanceParentFunctionTypeArguments = 4,
7694 kInstanceDelayedFunctionTypeArguments = 5,
7695 kDestinationType = 6,
7696 kTestResult = 7,
7697 kTestEntryLength = 8,
7698 };
7699
7700 // Assumes only one non-input entry in the array, kTestResult.
7701 static_assert(kInstanceCidOrSignature == 0 &&
7702 kDestinationType + 1 == kTestResult &&
7703 kTestResult + 1 == kTestEntryLength,
7704 "Need to adjust number of max inputs");
7705 static constexpr intptr_t kMaxInputs = kTestResult;
7706
7707 // Returns the number of occupied entries stored in the cache.
7708 intptr_t NumberOfChecks() const;
7709
7710 // Retrieves the number of entries (occupied or unoccupied) in the cache.
7711 intptr_t NumEntries() const;
7712
7713 // Adds a check, returning the index of the new entry in the cache.
7714 intptr_t AddCheck(
7715 const Object& instance_class_id_or_signature,
7716 const AbstractType& destination_type,
7717 const TypeArguments& instance_type_arguments,
7718 const TypeArguments& instantiator_type_arguments,
7719 const TypeArguments& function_type_arguments,
7720 const TypeArguments& instance_parent_function_type_arguments,
7721 const TypeArguments& instance_delayed_type_arguments,
7722 const Bool& test_result) const;
7723 void GetCheck(intptr_t ix,
7724 Object* instance_class_id_or_signature,
7725 AbstractType* destination_type,
7726 TypeArguments* instance_type_arguments,
7727 TypeArguments* instantiator_type_arguments,
7728 TypeArguments* function_type_arguments,
7729 TypeArguments* instance_parent_function_type_arguments,
7730 TypeArguments* instance_delayed_type_arguments,
7731 Bool* test_result) const;
7732
7733 // Like GetCheck(), but does not require the subtype test cache mutex and so
7734 // may see an outdated view of the cache.
7735 void GetCurrentCheck(intptr_t ix,
7736 Object* instance_class_id_or_signature,
7737 AbstractType* destination_type,
7738 TypeArguments* instance_type_arguments,
7739 TypeArguments* instantiator_type_arguments,
7740 TypeArguments* function_type_arguments,
7741 TypeArguments* instance_parent_function_type_arguments,
7742 TypeArguments* instance_delayed_type_arguments,
7743 Bool* test_result) const;
7744
7745 // Like GetCheck(), but returns the contents of the first occupied entry
7746 // at or after the initial contents of [ix]. Returns whether an occupied entry
7747 // was found, and if an occupied entry was found, [ix] is updated to the entry
7748 // index following the occupied entry.
7749 bool GetNextCheck(intptr_t* ix,
7750 Object* instance_class_id_or_signature,
7751 AbstractType* destination_type,
7752 TypeArguments* instance_type_arguments,
7753 TypeArguments* instantiator_type_arguments,
7754 TypeArguments* function_type_arguments,
7755 TypeArguments* instance_parent_function_type_arguments,
7756 TypeArguments* instance_delayed_type_arguments,
7757 Bool* test_result) const;
7758
7759 // Returns whether all the elements of an existing cache entry, excluding
7760 // the result, match the non-pointer arguments. The pointer arguments are
7761 // out parameters as follows:
7762 //
7763 // If [index] is not nullptr, then it is set to the matching entry's index.
7764 // If [result] is not nullptr, then it is set to the matching entry's result.
7765 //
7766 // If called without the STC mutex lock, may return outdated information:
7767 // * May return a false negative if the entry was added concurrently.
7768 // * The [index] field may be invalid for the STC if the backing array is
7769 // grown concurrently and the new backing array is hash-based.
7770 bool HasCheck(const Object& instance_class_id_or_signature,
7771 const AbstractType& destination_type,
7772 const TypeArguments& instance_type_arguments,
7773 const TypeArguments& instantiator_type_arguments,
7774 const TypeArguments& function_type_arguments,
7775 const TypeArguments& instance_parent_function_type_arguments,
7776 const TypeArguments& instance_delayed_type_arguments,
7777 intptr_t* index,
7778 Bool* result) const;
7779
7780 // Writes the cache entry at index [index] to the given text buffer.
7781 //
7782 // The output is comma separated on a single line if [line_prefix] is nullptr,
7783 // otherwise line breaks followed by [line_prefix] is used as a separator.
7784 void WriteEntryToBuffer(Zone* zone,
7786 intptr_t index,
7787 const char* line_prefix = nullptr) const;
7788
7789 // Writes the contents of this SubtypeTestCache to the given text buffer.
7790 void WriteToBuffer(Zone* zone,
7792 const char* line_prefix = nullptr) const;
7793
7794 void Reset() const;
7795
7796 // Tests that [other] contains the same entries in the same order.
7797 bool Equals(const SubtypeTestCache& other) const;
7798
7799 // Returns whether the cache backed by the given storage is hash-based.
7800 bool IsHash() const;
7801
7802 // Creates a separate copy of the current STC contents.
7803 SubtypeTestCachePtr Copy(Thread* thread) const;
7804
7805 static SubtypeTestCachePtr New(intptr_t num_inputs);
7806
7807 static intptr_t InstanceSize() {
7809 }
7810
7811 static intptr_t cache_offset() {
7812 return OFFSET_OF(UntaggedSubtypeTestCache, cache_);
7813 }
7814 ArrayPtr cache() const;
7815
7816 static intptr_t num_inputs_offset() {
7817 return OFFSET_OF(UntaggedSubtypeTestCache, num_inputs_);
7818 }
7819 intptr_t num_inputs() const { return untag()->num_inputs_; }
7820
7821 intptr_t num_occupied() const { return untag()->num_occupied_; }
7822
7823 // The maximum number of occupied entries for a linear subtype test cache
7824 // before swapping to a hash table-based cache. Exposed publicly for tests.
7825#if defined(TARGET_ARCH_IA32)
7826 // We don't generate hash cache probing in the stub on IA32, so larger caches
7827 // force runtime checks.
7828 static constexpr intptr_t kMaxLinearCacheEntries = 100;
7829#else
7830 static constexpr intptr_t kMaxLinearCacheEntries = 30;
7831#endif
7832
7833 // Whether the entry at the given index in the cache is occupied. Exposed
7834 // publicly for tests.
7835 bool IsOccupied(intptr_t index) const;
7836
7837 // Returns the number of inputs needed to cache entries for the given type.
7838 static intptr_t UsedInputsForType(const AbstractType& type);
7839
7840 // Given a minimum entry count, calculates an entry count that won't force
7841 // additional allocation but minimizes the number of unoccupied entries.
7842 // Used to calculate an appropriate value for FLAG_max_subtype_cache_entries.
7843 static constexpr intptr_t MaxEntriesForCacheAllocatedFor(intptr_t count) {
7844 // If the cache would be linear, just return the count unchanged.
7845 if (count <= kMaxLinearCacheEntries) return count;
7846 intptr_t allocated_entries = Utils::RoundUpToPowerOfTwo(count);
7847 if (LoadFactor(count, allocated_entries) >= kMaxLoadFactor) {
7848 allocated_entries *= 2;
7849 }
7850 const intptr_t max_entries =
7851 static_cast<intptr_t>(kMaxLoadFactor * allocated_entries);
7852 assert(LoadFactor(max_entries, allocated_entries) < kMaxLoadFactor);
7853 assert(max_entries >= count);
7854 return max_entries;
7855 }
7856
7857 private:
7858 static constexpr double LoadFactor(intptr_t occupied, intptr_t capacity) {
7859 return occupied / static_cast<double>(capacity);
7860 }
7861
7862 // Retrieves the number of entries (occupied or unoccupied) in a cache
7863 // backed by the given array.
7864 static intptr_t NumEntries(const Array& array);
7865
7866 // Returns whether the cache backed by the given storage is linear.
7867 static bool IsLinear(const Array& array) { return !IsHash(array); }
7868
7869 // Returns whether the cache backed by the given storage is hash-based.
7870 static bool IsHash(const Array& array);
7871
7872 struct KeyLocation {
7873 // The entry index if [present] is true, otherwise where the entry would
7874 // be located if added afterwards without any intermediate additions.
7875 intptr_t entry;
7876 bool present; // Whether an entry already exists in the cache.
7877 };
7878
7879 // If a cache entry in the given array contains the given inputs, returns a
7880 // KeyLocation with the index of the entry and true. Otherwise, returns a
7881 // KeyLocation with the index that would be used if the instantiation for the
7882 // given type arguments is added and false.
7883 //
7884 // If called without the STC mutex lock, may return outdated information:
7885 // * The [present] field may be a false negative if the entry was added
7886 // concurrently.
7887 static KeyLocation FindKeyOrUnused(
7888 const Array& array,
7889 intptr_t num_inputs,
7890 const Object& instance_class_id_or_signature,
7891 const AbstractType& destination_type,
7892 const TypeArguments& instance_type_arguments,
7893 const TypeArguments& instantiator_type_arguments,
7894 const TypeArguments& function_type_arguments,
7895 const TypeArguments& instance_parent_function_type_arguments,
7896 const TypeArguments& instance_delayed_type_arguments);
7897
7898 // If the given array can contain the requested number of entries, returns
7899 // the same array and sets [was_grown] to false.
7900 //
7901 // If the given array cannot contain the requested number of entries,
7902 // returns a new array that can and which contains all the entries of the
7903 // given array and sets [was_grown] to true.
7904 ArrayPtr EnsureCapacity(Zone* zone,
7905 const Array& array,
7906 intptr_t new_capacity,
7907 bool* was_grown) const;
7908
7909 public: // Used in the StubCodeCompiler.
7910 // The maximum size of the array backing a linear cache. All hash based
7911 // caches are guaranteed to have sizes larger than this.
7912 static constexpr intptr_t kMaxLinearCacheSize =
7913 (kMaxLinearCacheEntries + 1) * kTestEntryLength;
7914
7915 private:
7916 // The initial number of entries used when converting from a linear to
7917 // a hash-based cache.
7918 static constexpr intptr_t kNumInitialHashCacheEntries =
7919 Utils::RoundUpToPowerOfTwo(2 * kMaxLinearCacheEntries);
7920 static_assert(Utils::IsPowerOfTwo(kNumInitialHashCacheEntries),
7921 "number of hash-based cache entries must be a power of two");
7922
7923 // The max load factor allowed in hash-based caches.
7924 static constexpr double kMaxLoadFactor = 0.71;
7925
7926 void set_cache(const Array& value) const;
7927 void set_num_occupied(intptr_t value) const;
7928
7929 // Like GetCurrentCheck, but takes the backing storage array.
7930 static void GetCheckFromArray(
7931 const Array& array,
7932 intptr_t num_inputs,
7933 intptr_t ix,
7934 Object* instance_class_id_or_signature,
7935 AbstractType* destination_type,
7936 TypeArguments* instance_type_arguments,
7937 TypeArguments* instantiator_type_arguments,
7938 TypeArguments* function_type_arguments,
7939 TypeArguments* instance_parent_function_type_arguments,
7940 TypeArguments* instance_delayed_type_arguments,
7941 Bool* test_result);
7942
7943 // Like WriteEntryToBuffer(), but does not require the subtype test cache
7944 // mutex and so may see an incorrect view of the cache if there are concurrent
7945 // modifications.
7946 void WriteCurrentEntryToBuffer(Zone* zone,
7948 intptr_t index,
7949 const char* line_prefix = nullptr) const;
7950
7951 // Like WriteToBuffer(), but does not require the subtype test cache mutex and
7952 // so may see an incorrect view of the cache if there are concurrent
7953 // modifications.
7954 void WriteToBufferUnlocked(Zone* zone,
7956 const char* line_prefix = nullptr) const;
7957
7959 friend class Class;
7960 friend class FieldInvalidator;
7963};
7964
7965class LoadingUnit : public Object {
7966 public:
7967 static constexpr intptr_t kIllegalId = 0;
7969 static constexpr intptr_t kRootId = 1;
7970
7971 static LoadingUnitPtr New(intptr_t id, const LoadingUnit& parent);
7972
7973 static intptr_t InstanceSize() {
7975 }
7976
7977 static intptr_t LoadingUnitOf(const Function& function);
7978 static intptr_t LoadingUnitOf(const Code& code);
7979
7980 LoadingUnitPtr parent() const { return untag()->parent(); }
7981
7982 ArrayPtr base_objects() const { return untag()->base_objects(); }
7983 void set_base_objects(const Array& value) const;
7984
7985 intptr_t id() const {
7986 return untag()->packed_fields_.Read<UntaggedLoadingUnit::IdBits>();
7987 }
7988
7989 // True once the VM deserializes this unit's snapshot.
7990 bool loaded() const {
7991 return untag()->packed_fields_.Read<UntaggedLoadingUnit::LoadStateBits>() ==
7992 UntaggedLoadingUnit::kLoaded;
7993 }
7994 // value is whether the load succeeded or not.
7995 void set_loaded(bool value) const {
7996 ASSERT(load_outstanding());
7997 auto const expected =
7998 value ? UntaggedLoadingUnit::kLoaded : UntaggedLoadingUnit::kNotLoaded;
7999 auto const got = untag()
8000 ->packed_fields_
8001 .UpdateConditional<UntaggedLoadingUnit::LoadStateBits>(
8002 expected, UntaggedLoadingUnit::kLoadOutstanding);
8003 // Check that we're in the expected state afterwards.
8004 ASSERT_EQUAL(got, expected);
8005 }
8006
8007 // True once the VM invokes the embedder's deferred load callback until the
8008 // embedder calls Dart_DeferredLoadComplete[Error].
8009 bool load_outstanding() const {
8010 return untag()->packed_fields_.Read<UntaggedLoadingUnit::LoadStateBits>() ==
8011 UntaggedLoadingUnit::kLoadOutstanding;
8012 }
8014 auto const previous = UntaggedLoadingUnit::kNotLoaded;
8016 untag()->packed_fields_.Read<UntaggedLoadingUnit::LoadStateBits>(),
8017 previous);
8018 auto const expected = UntaggedLoadingUnit::kLoadOutstanding;
8019 auto const got = untag()
8020 ->packed_fields_
8021 .UpdateConditional<UntaggedLoadingUnit::LoadStateBits>(
8022 expected, previous);
8023 // Check that we're in the expected state afterwards.
8024 ASSERT_EQUAL(got, expected);
8025 }
8026
8027 const uint8_t* instructions_image() const {
8028 // The instructions image should only be accessed if the load succeeded.
8029 ASSERT(loaded());
8030 return untag()->instructions_image_;
8031 }
8032 void set_instructions_image(const uint8_t* value) const {
8033 ASSERT(load_outstanding());
8034 StoreNonPointer(&untag()->instructions_image_, value);
8035 }
8037 return loaded() && instructions_image() != nullptr;
8038 }
8039
8040 ObjectPtr IssueLoad() const;
8041 ObjectPtr CompleteLoad(const String& error_message,
8042 bool transient_error) const;
8043
8044 private:
8046 friend class Class;
8047};
8048
8049class Error : public Object {
8050 public:
8051 virtual const char* ToErrorCString() const;
8052
8053 private:
8055};
8056
8057class ApiError : public Error {
8058 public:
8059 StringPtr message() const { return untag()->message(); }
8060
8061 static intptr_t InstanceSize() {
8063 }
8064
8065 static ApiErrorPtr New(const String& message, Heap::Space space = Heap::kNew);
8066
8067 virtual const char* ToErrorCString() const;
8068
8069 private:
8070 void set_message(const String& message) const;
8071
8072 static ApiErrorPtr New();
8073
8075 friend class Class;
8076};
8077
8078class LanguageError : public Error {
8079 public:
8081 return static_cast<Report::Kind>(untag()->kind_);
8082 }
8083
8084 // Build, cache, and return formatted message.
8085 StringPtr FormatMessage() const;
8086
8087 static intptr_t InstanceSize() {
8089 }
8090
8091 // A null script means no source and a negative token_pos means no position.
8092 static LanguageErrorPtr NewFormatted(const Error& prev_error,
8093 const Script& script,
8094 TokenPosition token_pos,
8095 bool report_after_token,
8096 Report::Kind kind,
8097 Heap::Space space,
8098 const char* format,
8099 ...) PRINTF_ATTRIBUTE(7, 8);
8100
8101 static LanguageErrorPtr NewFormattedV(const Error& prev_error,
8102 const Script& script,
8103 TokenPosition token_pos,
8104 bool report_after_token,
8105 Report::Kind kind,
8106 Heap::Space space,
8107 const char* format,
8108 va_list args);
8109
8110 static LanguageErrorPtr New(const String& formatted_message,
8111 Report::Kind kind = Report::kError,
8112 Heap::Space space = Heap::kNew);
8113
8114 virtual const char* ToErrorCString() const;
8115
8116 TokenPosition token_pos() const { return untag()->token_pos_; }
8117
8118 private:
8119 ErrorPtr previous_error() const { return untag()->previous_error(); }
8120 void set_previous_error(const Error& value) const;
8121
8122 ScriptPtr script() const { return untag()->script(); }
8123 void set_script(const Script& value) const;
8124
8125 void set_token_pos(TokenPosition value) const;
8126
8127 bool report_after_token() const { return untag()->report_after_token_; }
8128 void set_report_after_token(bool value) const;
8129
8130 void set_kind(uint8_t value) const;
8131
8132 StringPtr message() const { return untag()->message(); }
8133 void set_message(const String& value) const;
8134
8135 StringPtr formatted_message() const { return untag()->formatted_message(); }
8136 void set_formatted_message(const String& value) const;
8137
8138 static LanguageErrorPtr New();
8139
8140 FINAL_HEAP_OBJECT_IMPLEMENTATION(LanguageError, Error);
8141 friend class Class;
8142};
8143
8145 public:
8146 InstancePtr exception() const { return untag()->exception(); }
8147 static intptr_t exception_offset() {
8148 return OFFSET_OF(UntaggedUnhandledException, exception_);
8149 }
8150
8151 InstancePtr stacktrace() const { return untag()->stacktrace(); }
8152 static intptr_t stacktrace_offset() {
8153 return OFFSET_OF(UntaggedUnhandledException, stacktrace_);
8154 }
8155
8156 static intptr_t InstanceSize() {
8158 }
8159
8160 static UnhandledExceptionPtr New(const Instance& exception,
8161 const Instance& stacktrace,
8162 Heap::Space space = Heap::kNew);
8163
8164 virtual const char* ToErrorCString() const;
8165
8166 private:
8167 static UnhandledExceptionPtr New(Heap::Space space = Heap::kNew);
8168
8169 void set_exception(const Instance& exception) const;
8170 void set_stacktrace(const Instance& stacktrace) const;
8171
8173 friend class Class;
8174 friend class ObjectStore;
8175};
8176
8177class UnwindError : public Error {
8178 public:
8179 bool is_user_initiated() const { return untag()->is_user_initiated_; }
8180 void set_is_user_initiated(bool value) const;
8181
8182 StringPtr message() const { return untag()->message(); }
8183
8184 static intptr_t InstanceSize() {
8186 }
8187
8188 static UnwindErrorPtr New(const String& message,
8189 Heap::Space space = Heap::kNew);
8190
8191 virtual const char* ToErrorCString() const;
8192
8193 private:
8194 void set_message(const String& message) const;
8195
8197 friend class Class;
8198};
8199
8200// Instance is the base class for all instance objects (aka the Object class
8201// in Dart source code.
8202class Instance : public Object {
8203 public:
8204 // Equality and identity testing.
8205 // 1. OperatorEquals: true iff 'this == other' is true in Dart code.
8206 // 2. IsIdenticalTo: true iff 'identical(this, other)' is true in Dart code.
8207 // 3. CanonicalizeEquals: used to canonicalize compile-time constants, e.g.,
8208 // using bitwise equality of fields and list elements.
8209 // Subclasses where 1 and 3 coincide may also define a plain Equals, e.g.,
8210 // String and Integer.
8211 virtual bool OperatorEquals(const Instance& other) const;
8212 bool IsIdenticalTo(const Instance& other) const;
8213 virtual bool CanonicalizeEquals(const Instance& other) const;
8214 virtual uint32_t CanonicalizeHash() const;
8215
8216 intptr_t SizeFromClass() const {
8217#if defined(DEBUG)
8218 const Class& cls = Class::Handle(clazz());
8219 ASSERT(cls.is_finalized() || cls.is_prefinalized());
8220#endif
8221 return (clazz()->untag()->host_instance_size_in_words_ *
8223 }
8224
8225 InstancePtr Canonicalize(Thread* thread) const;
8226 // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
8227 virtual InstancePtr CanonicalizeLocked(Thread* thread) const;
8228 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
8229
8230 InstancePtr CopyShallowToOldSpace(Thread* thread) const;
8231
8232 ObjectPtr GetField(const Field& field) const;
8233
8234 void SetField(const Field& field, const Object& value) const;
8235
8236 AbstractTypePtr GetType(Heap::Space space) const;
8237
8238 // Access the type arguments vector of this [Instance].
8239 // This vector includes type arguments corresponding to type parameters of
8240 // instance's class and all its superclasses.
8241 virtual TypeArgumentsPtr GetTypeArguments() const;
8242 virtual void SetTypeArguments(const TypeArguments& value) const;
8243
8244 // Check if the type of this instance is a subtype of the given other type.
8245 // The type argument vectors are used to instantiate the other type if needed.
8246 bool IsInstanceOf(const AbstractType& other,
8247 const TypeArguments& other_instantiator_type_arguments,
8248 const TypeArguments& other_function_type_arguments) const;
8249
8250 // Check if this instance is assignable to the given other type.
8251 // The type argument vectors are used to instantiate the other type if needed.
8252 bool IsAssignableTo(const AbstractType& other,
8253 const TypeArguments& other_instantiator_type_arguments,
8254 const TypeArguments& other_function_type_arguments) const;
8255
8256 // Return true if the null instance can be assigned to a variable of [other]
8257 // type. Return false if null cannot be assigned or we cannot tell (if
8258 // [other] is a type parameter in NNBD strong mode). Only used for checks at
8259 // compile time.
8260 static bool NullIsAssignableTo(const AbstractType& other);
8261
8262 // Return true if the null instance can be assigned to a variable of [other]
8263 // type. Return false if null cannot be assigned. Used for checks at runtime,
8264 // when the instantiator and function type argument vectors are available.
8265 static bool NullIsAssignableTo(
8266 const AbstractType& other,
8267 const TypeArguments& other_instantiator_type_arguments,
8268 const TypeArguments& other_function_type_arguments);
8269
8270 bool IsValidNativeIndex(int index) const {
8271 return ((index >= 0) && (index < clazz()->untag()->num_native_fields_));
8272 }
8273
8274 intptr_t* NativeFieldsDataAddr() const;
8275 inline intptr_t GetNativeField(int index) const;
8276 inline void GetNativeFields(uint16_t num_fields,
8277 intptr_t* field_values) const;
8278 void SetNativeFields(uint16_t num_fields, const intptr_t* field_values) const;
8279
8280 uint16_t NumNativeFields() const {
8281 return clazz()->untag()->num_native_fields_;
8282 }
8283
8284 void SetNativeField(int index, intptr_t value) const;
8285
8286 // If the instance is a callable object, i.e. a closure or the instance of a
8287 // class implementing a 'call' method, return true and set the function
8288 // (if not nullptr) to call.
8289 bool IsCallable(Function* function) const;
8290
8291 ObjectPtr Invoke(const String& selector,
8292 const Array& arguments,
8293 const Array& argument_names,
8294 bool respect_reflectable = true,
8295 bool check_is_entrypoint = false) const;
8296 ObjectPtr InvokeGetter(const String& selector,
8297 bool respect_reflectable = true,
8298 bool check_is_entrypoint = false) const;
8299 ObjectPtr InvokeSetter(const String& selector,
8300 const Instance& argument,
8301 bool respect_reflectable = true,
8302 bool check_is_entrypoint = false) const;
8303
8305 const Class& klass,
8306 const ExternalTypedData& kernel_buffer,
8307 const Array& type_definitions,
8308 const Array& arguments,
8309 const TypeArguments& type_arguments) const;
8310
8311 // Evaluate the given expression as if it appeared in an instance method of
8312 // [receiver] and return the resulting value, or an error object if
8313 // evaluating the expression fails. The method has the formal (type)
8314 // parameters given in (type_)param_names, and is invoked with the (type)
8315 // argument values given in (type_)param_values.
8316 //
8317 // We allow [receiver] to be null/<optimized out> if
8318 // * the evaluation function doesn't access `this`
8319 // * the evaluation function is static
8321 Thread* thread,
8322 const Object& receiver,
8323 const Library& library,
8324 const Class& klass,
8325 const ExternalTypedData& kernel_buffer,
8326 const Array& type_definitions,
8327 const Array& param_values,
8328 const TypeArguments& type_param_values);
8329
8330 // Equivalent to invoking hashCode on this instance.
8331 virtual ObjectPtr HashCode() const;
8332
8333 // Equivalent to invoking identityHashCode with this instance.
8334 IntegerPtr IdentityHashCode(Thread* thread) const;
8335
8336 static intptr_t UnroundedSize() { return sizeof(UntaggedInstance); }
8337 static intptr_t InstanceSize() {
8339 }
8340
8341 static InstancePtr New(const Class& cls, Heap::Space space = Heap::kNew);
8342 static InstancePtr NewAlreadyFinalized(const Class& cls,
8343 Heap::Space space = Heap::kNew);
8344
8345 // Array/list element address computations.
8346 static intptr_t DataOffsetFor(intptr_t cid);
8347 static intptr_t ElementSizeFor(intptr_t cid);
8348
8349 // Pointers may be subtyped, but their subtypes may not get extra fields.
8350 // The subtype runtime representation has exactly the same object layout,
8351 // only the class_id is different. So, it is safe to use subtype instances in
8352 // Pointer handles.
8353 virtual bool IsPointer() const;
8354
8355 static intptr_t NextFieldOffset() { return sizeof(UntaggedInstance); }
8356
8357 static intptr_t NativeFieldsOffset() { return sizeof(UntaggedObject); }
8358
8359 protected:
8360#ifndef PRODUCT
8361 virtual void PrintSharedInstanceJSON(JSONObject* jsobj,
8362 bool ref,
8363 bool include_id = true) const;
8364#endif
8365
8366 private:
8367 // Return true if the runtimeType of this instance is a subtype of other type.
8368 bool RuntimeTypeIsSubtypeOf(
8369 const AbstractType& other,
8370 const TypeArguments& other_instantiator_type_arguments,
8371 const TypeArguments& other_function_type_arguments) const;
8372
8373 // Returns true if the type of this instance is a subtype of FutureOr<T>
8374 // specified by instantiated type 'other'.
8375 // Returns false if other type is not a FutureOr.
8376 bool RuntimeTypeIsSubtypeOfFutureOr(Zone* zone,
8377 const AbstractType& other) const;
8378
8379 // Return true if the null instance is an instance of other type.
8380 static bool NullIsInstanceOf(
8381 const AbstractType& other,
8382 const TypeArguments& other_instantiator_type_arguments,
8383 const TypeArguments& other_function_type_arguments);
8384
8385 CompressedObjectPtr* FieldAddrAtOffset(intptr_t offset) const {
8386 ASSERT(IsValidFieldOffset(offset));
8387 return reinterpret_cast<CompressedObjectPtr*>(raw_value() - kHeapObjectTag +
8388 offset);
8389 }
8390 CompressedObjectPtr* FieldAddr(const Field& field) const {
8391 return FieldAddrAtOffset(field.HostOffset());
8392 }
8393 CompressedObjectPtr* NativeFieldsAddr() const {
8394 return FieldAddrAtOffset(sizeof(UntaggedObject));
8395 }
8396 void SetFieldAtOffset(intptr_t offset, const Object& value) const {
8397 StoreCompressedPointer(FieldAddrAtOffset(offset), value.ptr());
8398 }
8399 bool IsValidFieldOffset(intptr_t offset) const;
8400
8401 // The following raw methods are used for morphing.
8402 // They are needed due to the extraction of the class in IsValidFieldOffset.
8403 CompressedObjectPtr* RawFieldAddrAtOffset(intptr_t offset) const {
8404 return reinterpret_cast<CompressedObjectPtr*>(raw_value() - kHeapObjectTag +
8405 offset);
8406 }
8407 ObjectPtr RawGetFieldAtOffset(intptr_t offset) const {
8408 return RawFieldAddrAtOffset(offset)->Decompress(untag()->heap_base());
8409 }
8410 void RawSetFieldAtOffset(intptr_t offset, const Object& value) const {
8411 StoreCompressedPointer(RawFieldAddrAtOffset(offset), value.ptr());
8412 }
8413 void RawSetFieldAtOffset(intptr_t offset, ObjectPtr value) const {
8414 StoreCompressedPointer(RawFieldAddrAtOffset(offset), value);
8415 }
8416
8417 template <typename T>
8418 T* RawUnboxedFieldAddrAtOffset(intptr_t offset) const {
8419 return reinterpret_cast<T*>(raw_value() - kHeapObjectTag + offset);
8420 }
8421 template <typename T>
8422 T RawGetUnboxedFieldAtOffset(intptr_t offset) const {
8423 return *RawUnboxedFieldAddrAtOffset<T>(offset);
8424 }
8425 template <typename T>
8426 void RawSetUnboxedFieldAtOffset(intptr_t offset, const T& value) const {
8427 *RawUnboxedFieldAddrAtOffset<T>(offset) = value;
8428 }
8429
8430 // TODO(iposva): Determine if this gets in the way of Smi.
8432 friend class ByteBuffer;
8433 friend class Class;
8434 friend class Closure;
8435 friend class Pointer;
8436 friend class DeferredObject;
8439 friend class RegExp;
8440 friend class StubCode;
8441 friend class TypedDataView;
8444 friend class ClassDeserializationCluster; // vtable
8445 friend class InstanceMorpher;
8446 friend class Obfuscator; // RawGetFieldAtOffset, RawSetFieldAtOffset
8447};
8448
8449class LibraryPrefix : public Instance {
8450 public:
8451 StringPtr name() const { return untag()->name(); }
8452 virtual StringPtr DictionaryName() const { return name(); }
8453
8454 ArrayPtr imports() const { return untag()->imports(); }
8455 intptr_t num_imports() const { return untag()->num_imports_; }
8456 LibraryPtr importer() const { return untag()->importer(); }
8457
8458 LibraryPtr GetLibrary(int index) const;
8459 void AddImport(const Namespace& import) const;
8460
8461 bool is_deferred_load() const { return untag()->is_deferred_load_; }
8462
8463 static intptr_t InstanceSize() {
8465 }
8466
8467 static LibraryPrefixPtr New(const String& name,
8468 const Namespace& import,
8469 bool deferred_load,
8470 const Library& importer);
8471
8472 private:
8473 static constexpr int kInitialSize = 2;
8474 static constexpr int kIncrementSize = 2;
8475
8476 void set_name(const String& value) const;
8477 void set_imports(const Array& value) const;
8478 void set_num_imports(intptr_t value) const;
8479 void set_importer(const Library& value) const;
8480
8481 static LibraryPrefixPtr New();
8482
8484 friend class Class;
8485};
8486
8487// TypeParameters represents a list of formal type parameters with their bounds
8488// and their default values as calculated by CFE.
8489class TypeParameters : public Object {
8490 public:
8491 intptr_t Length() const;
8492
8493 static intptr_t names_offset() {
8494 return OFFSET_OF(UntaggedTypeParameters, names_);
8495 }
8496 StringPtr NameAt(intptr_t index) const;
8497 void SetNameAt(intptr_t index, const String& value) const;
8498
8499 static intptr_t flags_offset() {
8500 return OFFSET_OF(UntaggedTypeParameters, flags_);
8501 }
8502
8503 static intptr_t bounds_offset() {
8504 return OFFSET_OF(UntaggedTypeParameters, bounds_);
8505 }
8506 AbstractTypePtr BoundAt(intptr_t index) const;
8507 void SetBoundAt(intptr_t index, const AbstractType& value) const;
8508 bool AllDynamicBounds() const;
8509
8510 static intptr_t defaults_offset() {
8511 return OFFSET_OF(UntaggedTypeParameters, defaults_);
8512 }
8513 AbstractTypePtr DefaultAt(intptr_t index) const;
8514 void SetDefaultAt(intptr_t index, const AbstractType& value) const;
8515 bool AllDynamicDefaults() const;
8516
8517 // The isGenericCovariantImpl bits are packed into SMIs in the flags array,
8518 // but omitted if they're 0.
8519 bool IsGenericCovariantImplAt(intptr_t index) const;
8520 void SetIsGenericCovariantImplAt(intptr_t index, bool value) const;
8521
8522 // The number of flags per Smi should be a power of 2 in order to simplify the
8523 // generated code accessing the flags array.
8524#if !defined(DART_COMPRESSED_POINTERS)
8525 static constexpr intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 1;
8526#else
8527 static constexpr intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 2;
8528#endif
8529 static constexpr intptr_t kFlagsPerSmi = 1LL << kFlagsPerSmiShift;
8530 COMPILE_ASSERT(kFlagsPerSmi < kSmiBits);
8531 static constexpr intptr_t kFlagsPerSmiMask = kFlagsPerSmi - 1;
8532
8533 void Print(Thread* thread,
8534 Zone* zone,
8535 bool are_class_type_parameters,
8536 intptr_t base,
8537 NameVisibility name_visibility,
8538 BaseTextBuffer* printer) const;
8539
8540 static intptr_t InstanceSize() {
8542 }
8543
8544 static TypeParametersPtr New(Heap::Space space = Heap::kOld);
8545 static TypeParametersPtr New(intptr_t count, Heap::Space space = Heap::kOld);
8546
8547 private:
8548 ArrayPtr names() const { return untag()->names(); }
8549 void set_names(const Array& value) const;
8550 ArrayPtr flags() const { return untag()->flags(); }
8551 void set_flags(const Array& value) const;
8552 TypeArgumentsPtr bounds() const { return untag()->bounds(); }
8553 void set_bounds(const TypeArguments& value) const;
8554 TypeArgumentsPtr defaults() const { return untag()->defaults(); }
8555 void set_defaults(const TypeArguments& value) const;
8556
8557 // Allocate and initialize the flags array to zero.
8558 void AllocateFlags(Heap::Space space) const;
8559 // Reset the flags array to null if all flags are zero.
8560 void OptimizeFlags() const;
8561
8563 friend class Class;
8564 friend class ClassFinalizer;
8567 friend class Function;
8568 friend class FunctionType;
8569 friend class Object;
8570 friend class Precompiler;
8571 friend class Type; // To determine whether to print type arguments.
8572};
8573
8574// A TypeArguments is an array of AbstractType.
8575class TypeArguments : public Instance {
8576 public:
8577 // Hash value for a type argument vector consisting solely of dynamic types.
8578 static constexpr intptr_t kAllDynamicHash = 1;
8579
8580 // Returns whether this TypeArguments vector can be used in a context that
8581 // expects a vector of length [count]. Always true for the null vector.
8582 bool HasCount(intptr_t count) const;
8583 static intptr_t length_offset() {
8584 return OFFSET_OF(UntaggedTypeArguments, length_);
8585 }
8586 intptr_t Length() const;
8587 AbstractTypePtr TypeAt(intptr_t index) const;
8588 AbstractTypePtr TypeAtNullSafe(intptr_t index) const;
8589 static intptr_t types_offset() {
8591 }
8592 static intptr_t type_at_offset(intptr_t index) {
8593 return types_offset() + index * kCompressedWordSize;
8594 }
8595 void SetTypeAt(intptr_t index, const AbstractType& value) const;
8596
8598 static intptr_t elements_start_offset() {
8600 }
8601
8602 static constexpr intptr_t kElementSize = kCompressedWordSize;
8603 };
8604
8605 // The nullability of a type argument vector represents the nullability of its
8606 // type elements (up to a maximum number of them, i.e. kNullabilityMaxTypes).
8607 // It is used at runtime in some cases (predetermined by the compiler) to
8608 // decide whether the instantiator type arguments (ITA) can be shared instead
8609 // of performing a more costly instantiation of the uninstantiated type
8610 // arguments (UTA).
8611 // The vector nullability is stored as a bit vector (in a Smi field), using
8612 // 1 bit per type, which is set if the type is nullable.
8613 // The nullability is 0 if the vector is longer than kNullabilityMaxTypes.
8614 // The condition evaluated at runtime to decide whether UTA can share ITA is
8615 // (UTA.nullability & ITA.nullability) == UTA.nullability
8616 // Note that this allows for ITA to be longer than UTA (the bit vector must be
8617 // stored in the same order as the corresponding type vector, i.e. with the
8618 // least significant bit representing the nullability of the first type).
8619 static constexpr intptr_t kNullabilityBitsPerType = 1;
8620 static constexpr intptr_t kNullabilityMaxTypes =
8621 kSmiBits / kNullabilityBitsPerType;
8622 static constexpr intptr_t kNonNullableBit = 0;
8623 static constexpr intptr_t kNullableBit = 1;
8624 intptr_t nullability() const;
8625 static intptr_t nullability_offset() {
8626 return OFFSET_OF(UntaggedTypeArguments, nullability_);
8627 }
8628
8629 // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
8630 StringPtr Name() const;
8631
8632 // The name of this type argument vector, e.g. "<T, dynamic, List<T>, int>".
8633 // Names of internal classes are mapped to their public interfaces.
8634 StringPtr UserVisibleName() const;
8635
8636 // Print the internal or public name of a subvector of this type argument
8637 // vector, e.g. "<T, dynamic, List<T>, int>".
8638 void PrintSubvectorName(intptr_t from_index,
8639 intptr_t len,
8640 NameVisibility name_visibility,
8641 BaseTextBuffer* printer) const;
8642 void PrintTo(BaseTextBuffer* printer) const;
8643
8644 // Check if the subvector of length 'len' starting at 'from_index' of this
8645 // type argument vector consists solely of DynamicType.
8646 bool IsRaw(intptr_t from_index, intptr_t len) const {
8647 return IsDynamicTypes(false, from_index, len);
8648 }
8649
8650 // Check if this type argument vector would consist solely of DynamicType if
8651 // it was instantiated from both a raw (null) instantiator type arguments and
8652 // a raw (null) function type arguments, i.e. consider each class type
8653 // parameter and function type parameters as it would be first instantiated
8654 // from a vector of dynamic types.
8655 // Consider only a prefix of length 'len'.
8656 bool IsRawWhenInstantiatedFromRaw(intptr_t len) const {
8657 return IsDynamicTypes(true, 0, len);
8658 }
8659
8660 TypeArgumentsPtr Prepend(Zone* zone,
8661 const TypeArguments& other,
8662 intptr_t other_length,
8663 intptr_t total_length) const;
8664
8665 // Concatenate [this] and [other] vectors of type parameters.
8666 TypeArgumentsPtr ConcatenateTypeParameters(Zone* zone,
8667 const TypeArguments& other) const;
8668
8669 // Returns an InstantiationMode for this type argument vector, which
8670 // specifies whether the type argument vector requires instantiation and
8671 // shortcuts to instantiate the vector when possible.
8672 //
8673 // If [function] is provided, any function type arguments used in the type
8674 // arguments vector are assumed to be bound by the function or its parent
8675 // functions.
8676 //
8677 // If [class] is provided, any class type arguments used in the type arguments
8678 // vector are assumed to be bound by that class. If [function] is provided
8679 // but [class] is not, then the owning class of the function is retrieved
8680 // and used.
8681 InstantiationMode GetInstantiationMode(Zone* zone,
8682 const Function* function = nullptr,
8683 const Class* cls = nullptr) const;
8684
8685 // Check if the vectors are equal (they may be null).
8686 bool Equals(const TypeArguments& other) const {
8687 return IsSubvectorEquivalent(other, 0, IsNull() ? 0 : Length(),
8689 }
8690
8692 const TypeArguments& other,
8693 TypeEquality kind,
8694 FunctionTypeMapping* function_type_equivalence = nullptr) const {
8695 // Make a null vector a vector of dynamic as long as the other vector.
8696 return IsSubvectorEquivalent(other, 0, IsNull() ? other.Length() : Length(),
8697 kind, function_type_equivalence);
8698 }
8699 bool IsSubvectorEquivalent(
8700 const TypeArguments& other,
8701 intptr_t from_index,
8702 intptr_t len,
8703 TypeEquality kind,
8704 FunctionTypeMapping* function_type_equivalence = nullptr) const;
8705
8706 // Check if the vector is instantiated (it must not be null).
8707 bool IsInstantiated(Genericity genericity = kAny,
8708 intptr_t num_free_fun_type_params = kAllFree) const {
8709 return IsSubvectorInstantiated(0, Length(), genericity,
8710 num_free_fun_type_params);
8711 }
8712 bool IsSubvectorInstantiated(
8713 intptr_t from_index,
8714 intptr_t len,
8715 Genericity genericity = kAny,
8716 intptr_t num_free_fun_type_params = kAllFree) const;
8717 bool IsUninstantiatedIdentity() const;
8718
8719 // Determine whether this uninstantiated type argument vector can share its
8720 // instantiator (resp. function) type argument vector instead of being
8721 // instantiated at runtime.
8722 // If null is passed in for 'with_runtime_check', the answer is unconditional
8723 // (i.e. the answer will be false even if a runtime check may allow sharing),
8724 // otherwise, in case the function returns true, 'with_runtime_check'
8725 // indicates if a check is still required at runtime before allowing sharing.
8726 bool CanShareInstantiatorTypeArguments(
8727 const Class& instantiator_class,
8728 bool* with_runtime_check = nullptr) const;
8729 bool CanShareFunctionTypeArguments(const Function& function,
8730 bool* with_runtime_check = nullptr) const;
8731 TypeArgumentsPtr TruncatedTo(intptr_t length) const;
8732
8733 // Return true if all types of this vector are finalized.
8734 bool IsFinalized() const;
8735
8736 // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
8737 virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
8738 return Canonicalize(thread);
8739 }
8740
8741 // Canonicalize only if instantiated, otherwise returns 'this'.
8742 TypeArgumentsPtr Canonicalize(Thread* thread) const;
8743
8744 // Shrinks flattened instance type arguments to ordinary type arguments.
8745 TypeArgumentsPtr FromInstanceTypeArguments(Thread* thread,
8746 const Class& cls) const;
8747
8748 // Expands type arguments to a vector suitable as instantiator type
8749 // arguments.
8750 //
8751 // Only fills positions corresponding to type parameters of [cls], leave
8752 // all positions of superclass type parameters blank.
8753 // Use [GetInstanceTypeArguments] on a class or a type if full vector is
8754 // needed.
8755 TypeArgumentsPtr ToInstantiatorTypeArguments(Thread* thread,
8756 const Class& cls) const;
8757
8758 // Add the class name and URI of each type argument of this vector to the uris
8759 // list and mark ambiguous triplets to be printed.
8760 void EnumerateURIs(URIs* uris) const;
8761
8762 // Return 'this' if this type argument vector is instantiated, i.e. if it does
8763 // not refer to type parameters. Otherwise, return a new type argument vector
8764 // where each reference to a type parameter is replaced with the corresponding
8765 // type from the various type argument vectors (class instantiator, function,
8766 // or parent functions via the current context).
8767 TypeArgumentsPtr InstantiateFrom(
8768 const TypeArguments& instantiator_type_arguments,
8769 const TypeArguments& function_type_arguments,
8770 intptr_t num_free_fun_type_params,
8771 Heap::Space space,
8772 FunctionTypeMapping* function_type_mapping = nullptr,
8773 intptr_t num_parent_type_args_adjustment = 0) const;
8774
8775 // Update number of parent function type arguments for
8776 // all elements of this vector.
8777 TypeArgumentsPtr UpdateFunctionTypes(
8778 intptr_t num_parent_type_args_adjustment,
8779 intptr_t num_free_fun_type_params,
8780 Heap::Space space,
8781 FunctionTypeMapping* function_type_mapping) const;
8782
8783 // Runtime instantiation with canonicalization. Not to be used during type
8784 // finalization at compile time.
8785 TypeArgumentsPtr InstantiateAndCanonicalizeFrom(
8786 const TypeArguments& instantiator_type_arguments,
8787 const TypeArguments& function_type_arguments) const;
8788
8789 class Cache : public ValueObject {
8790 public:
8791 // The contents of the backing array storage is a header followed by
8792 // a number of entry tuples. Any entry that is unoccupied has
8793 // Sentinel() as its first component.
8794 //
8795 // If the cache is linear, the entries can be accessed in a linear fashion:
8796 // all occupied entries come first, followed by at least one unoccupied
8797 // entry to mark the end of the cache. Guaranteeing at least one unoccupied
8798 // entry avoids the need for a length check when iterating over the contents
8799 // of the linear cache in stubs.
8800 //
8801 // If the cache is hash-based, the array is instead treated as a hash table
8802 // probed by using a hash value derived from the instantiator and function
8803 // type arguments.
8804
8805 enum Header {
8806 // A single Smi that is a bitfield containing two values:
8807 // - The number of occupied entries in the cache for all caches.
8808 // - For hash-based caches, the upper bits contain log2(N) where N
8809 // is the number of total entries in the cache, so this information can
8810 // be quickly retrieved by stubs.
8811 //
8812 // Note: accesses outside of the type arguments canonicalization mutex
8813 // must have acquire semantics. In C++ code, use NumOccupied to retrieve
8814 // the number of occupied entries.
8815 kMetadataIndex = 0,
8817 };
8818
8819 using NumOccupiedBits = BitField<intptr_t,
8820 intptr_t,
8821 0,
8825 intptr_t,
8826 NumOccupiedBits::kNextBit,
8828
8829 // The tuple of values stored in a given entry.
8830 //
8831 // Note: accesses of the first component outside of the type arguments
8832 // canonicalization mutex must have acquire semantics.
8833 enum Entry {
8834 kSentinelIndex = 0, // Used when only checking for sentinel values.
8835 kInstantiatorTypeArgsIndex = kSentinelIndex,
8839 };
8840
8841 // Requires that the type arguments canonicalization mutex is held.
8842 Cache(Zone* zone, const TypeArguments& source);
8843
8844 // Requires that the type arguments canonicalization mutex is held.
8845 Cache(Zone* zone, const Array& array);
8846
8847 // Used to check that the state of the backing array is valid.
8848 //
8849 // Requires that the type arguments canonicalization mutex is held.
8850 DEBUG_ONLY(static bool IsValidStorageLocked(const Array& array);)
8851
8852 // Returns the number of entries stored in the cache.
8853 intptr_t NumOccupied() const { return NumOccupied(data_); }
8854
8856 // The entry index if [present] is true, otherwise where the entry would
8857 // be located if added afterwards without any intermediate additions.
8858 intptr_t entry;
8859 bool present; // Whether an entry already exists in the cache.
8860 };
8861
8862 // If an entry contains the given instantiator and function type arguments,
8863 // returns a KeyLocation with the index of the entry and true. Otherwise,
8864 // returns the index an entry with those keys would have if added and false.
8866 const TypeArguments& function_tav) const {
8867 return FindKeyOrUnused(data_, instantiator_tav, function_tav);
8868 }
8869
8870 // Returns whether the entry at the given index in the cache is occupied.
8871 bool IsOccupied(intptr_t entry) const;
8872
8873 // Given an occupied entry index, returns the instantiated TypeArguments.
8874 TypeArgumentsPtr Retrieve(intptr_t entry) const;
8875
8876 // Adds a new instantiation mapping to the cache at index [entry]. Assumes
8877 // that the entry at index [entry] is unoccupied.
8878 //
8879 // May replace the underlying storage array, in which case the returned
8880 // index of the entry may differ from the requested one. If this Cache was
8881 // constructed using a TypeArguments object, its instantiations field is
8882 // also updated to point to the new storage.
8883 KeyLocation AddEntry(intptr_t entry,
8884 const TypeArguments& instantiator_tav,
8885 const TypeArguments& function_tav,
8886 const TypeArguments& instantiated_tav) const;
8887
8888 // The sentinel value used to mark unoccupied entries.
8889 static SmiPtr Sentinel();
8890
8891 static const Array& EmptyStorage() {
8892 return Object::empty_instantiations_cache_array();
8893 }
8894
8895 // Returns whether the cache is linear.
8896 bool IsLinear() const { return IsLinear(data_); }
8897
8898 // Returns whether the cache is hash-based.
8899 bool IsHash() const { return IsHash(data_); }
8900
8901 private:
8902 static constexpr double LoadFactor(intptr_t occupied, intptr_t capacity) {
8903 return occupied / static_cast<double>(capacity);
8904 }
8905
8906 // Returns the number of entries stored in the cache backed by the given
8907 // array.
8908 static intptr_t NumOccupied(const Array& array);
8909
8910 // Returns whether the cache backed by the given storage is linear.
8911 static bool IsLinear(const Array& array) { return !IsHash(array); }
8912
8913 // Returns whether the cache backed by the given storage is hash-based.
8914 static bool IsHash(const Array& array);
8915
8916 // Ensures that the backing store for the cache can hold at least [occupied]
8917 // occupied entries. If it cannot, replaces the backing store with one that
8918 // can, copying over entries from the old backing store.
8919 //
8920 // Returns whether the backing store changed.
8921 bool EnsureCapacity(intptr_t occupied) const;
8922
8923 public: // For testing purposes only.
8924 // Retrieves the number of entries (occupied or unoccupied) in the cache.
8925 intptr_t NumEntries() const { return NumEntries(data_); }
8926
8927 // The maximum number of occupied entries for a linear cache of
8928 // instantiations before swapping to a hash table-based cache.
8929#if defined(TARGET_ARCH_IA32)
8930 // We don't generate hash cache probing in the stub on IA32.
8931 static constexpr intptr_t kMaxLinearCacheEntries = 500;
8932#else
8933 static constexpr intptr_t kMaxLinearCacheEntries = 10;
8934#endif
8935
8936 private:
8937 // Retrieves the number of entries (occupied or unoccupied) in a cache
8938 // backed by the given array.
8939 static intptr_t NumEntries(const Array& array);
8940
8941 // If an entry in the given array contains the given instantiator and
8942 // function type arguments, returns a KeyLocation with the index of the
8943 // entry and true. Otherwise, returns a KeyLocation with the index that
8944 // would be used if the instantiation for the given type arguments is
8945 // added and false.
8946 static KeyLocation FindKeyOrUnused(const Array& array,
8947 const TypeArguments& instantiator_tav,
8948 const TypeArguments& function_tav);
8949
8950 // The sentinel value in the Smi returned from Sentinel().
8951 static constexpr intptr_t kSentinelValue = 0;
8952
8953 public: // Used in the StubCodeCompiler.
8954 // The maximum size of the array backing a linear cache. All hash based
8955 // caches are guaranteed to have sizes larger than this.
8956 static constexpr intptr_t kMaxLinearCacheSize =
8957 kHeaderSize + (kMaxLinearCacheEntries + 1) * kEntrySize;
8958
8959 private:
8960 // The initial number of entries used when converting from a linear to
8961 // a hash-based cache.
8962 static constexpr intptr_t kNumInitialHashCacheEntries =
8963 Utils::RoundUpToPowerOfTwo(2 * kMaxLinearCacheEntries);
8964 static_assert(Utils::IsPowerOfTwo(kNumInitialHashCacheEntries),
8965 "number of hash-based cache entries must be a power of two");
8966
8967 // The max load factor allowed in hash-based caches.
8968 static constexpr double kMaxLoadFactor = 0.71;
8969
8970 Zone* const zone_;
8971 const TypeArguments* const cache_container_;
8972 Array& data_;
8973 Smi& smi_handle_;
8974
8975 friend class TypeArguments; // For asserts against data_.
8976 };
8977
8978 // Return true if this type argument vector has cached instantiations.
8979 bool HasInstantiations() const;
8980
8981 static intptr_t instantiations_offset() {
8982 return OFFSET_OF(UntaggedTypeArguments, instantiations_);
8983 }
8984
8985 static constexpr intptr_t kBytesPerElement = kCompressedWordSize;
8986 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
8987
8988 static intptr_t InstanceSize() {
8989 ASSERT(sizeof(UntaggedTypeArguments) ==
8991 return 0;
8992 }
8993
8994 static intptr_t InstanceSize(intptr_t len) {
8995 // Ensure that the types() is not adding to the object size, which includes
8996 // 4 fields: instantiations_, length_, hash_, and nullability_.
8997 ASSERT(sizeof(UntaggedTypeArguments) ==
8998 (sizeof(UntaggedObject) + (kNumFields * kCompressedWordSize)));
8999 ASSERT(0 <= len && len <= kMaxElements);
9001 (len * kBytesPerElement));
9002 }
9003
9004 virtual uint32_t CanonicalizeHash() const { return Hash(); }
9005 uword Hash() const;
9006 uword HashForRange(intptr_t from_index, intptr_t len) const;
9007 static intptr_t hash_offset() {
9008 return OFFSET_OF(UntaggedTypeArguments, hash_);
9009 }
9010
9011 static TypeArgumentsPtr New(intptr_t len, Heap::Space space = Heap::kOld);
9012
9013 private:
9014 intptr_t ComputeNullability() const;
9015 void set_nullability(intptr_t value) const;
9016
9017 uword ComputeHash() const;
9018 void SetHash(intptr_t value) const;
9019
9020 // Check if the subvector of length 'len' starting at 'from_index' of this
9021 // type argument vector consists solely of DynamicType.
9022 // If raw_instantiated is true, consider each class type parameter to be first
9023 // instantiated from a vector of dynamic types.
9024 bool IsDynamicTypes(bool raw_instantiated,
9025 intptr_t from_index,
9026 intptr_t len) const;
9027
9028 ArrayPtr instantiations() const;
9029 void set_instantiations(const Array& value) const;
9030 void SetLength(intptr_t value) const;
9031 // Number of fields in the raw object is 4:
9032 // instantiations_, length_, hash_ and nullability_.
9033 static constexpr int kNumFields = 4;
9034
9036 friend class AbstractType;
9037 friend class Class;
9039 friend class Object;
9040};
9041
9042// AbstractType is an abstract superclass.
9043// Subclasses of AbstractType are Type and TypeParameter.
9044class AbstractType : public Instance {
9045 public:
9046 static intptr_t flags_offset() {
9047 return OFFSET_OF(UntaggedAbstractType, flags_);
9048 }
9049 static intptr_t hash_offset() {
9050 return OFFSET_OF(UntaggedAbstractType, hash_);
9051 }
9052
9053 bool IsFinalized() const {
9054 const auto state = type_state();
9057 }
9058 void SetIsFinalized() const;
9059
9061 return static_cast<Nullability>(
9063 }
9064 // Returns true if type has '?' nullability suffix, or it is a
9065 // built-in type which is always nullable (Null, dynamic or void).
9066 bool IsNullable() const { return nullability() == Nullability::kNullable; }
9067 // Returns true if type does not have any nullability suffix.
9068 // This function also returns true for type parameters without
9069 // nullability suffix ("T") which can be instantiated with
9070 // nullable or legacy types.
9071 bool IsNonNullable() const {
9072 return nullability() == Nullability::kNonNullable;
9073 }
9074 // Returns true if it is guaranteed that null cannot be
9075 // assigned to this type.
9076 bool IsStrictlyNonNullable() const;
9077
9078 virtual AbstractTypePtr SetInstantiatedNullability(
9079 const TypeParameter& type_param,
9080 Heap::Space space) const;
9081 virtual AbstractTypePtr NormalizeFutureOrType(Heap::Space space) const;
9082
9083 virtual bool HasTypeClass() const { return type_class_id() != kIllegalCid; }
9084 virtual classid_t type_class_id() const;
9085 virtual ClassPtr type_class() const;
9086 virtual TypeArgumentsPtr arguments() const;
9087 virtual bool IsInstantiated(
9088 Genericity genericity = kAny,
9089 intptr_t num_free_fun_type_params = kAllFree) const;
9090 virtual bool CanonicalizeEquals(const Instance& other) const {
9091 return Equals(other);
9092 }
9093 virtual uint32_t CanonicalizeHash() const { return Hash(); }
9094 virtual bool Equals(const Instance& other) const {
9095 return IsEquivalent(other, TypeEquality::kCanonical);
9096 }
9097 virtual bool IsEquivalent(
9098 const Instance& other,
9099 TypeEquality kind,
9100 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9101
9102 // Instantiate this type using the given type argument vectors.
9103 //
9104 // Note that some type parameters appearing in this type may not require
9105 // instantiation. Consider a class C<T> declaring a non-generic method
9106 // foo(bar<B>(T t, B b)). Although foo is not a generic method, it takes a
9107 // generic function bar<B> as argument and its function type refers to class
9108 // type parameter T and function type parameter B. When instantiating the
9109 // function type of foo for a particular value of T, function type parameter B
9110 // must remain uninstantiated, because only T is a free variable in this type.
9111 //
9112 // Return a new type, or return 'this' if it is already instantiated.
9113 virtual AbstractTypePtr InstantiateFrom(
9114 const TypeArguments& instantiator_type_arguments,
9115 const TypeArguments& function_type_arguments,
9116 intptr_t num_free_fun_type_params,
9117 Heap::Space space,
9118 FunctionTypeMapping* function_type_mapping = nullptr,
9119 intptr_t num_parent_type_args_adjustment = 0) const;
9120
9121 // Update number of parent function type arguments for the
9122 // nested function types and their type parameters.
9123 //
9124 // This adjustment is needed when nesting one generic function type
9125 // inside another. It is also needed when function type is copied
9126 // and owners of type parameters need to be adjusted.
9127 //
9128 // Number of parent function type arguments is adjusted by
9129 // [num_parent_type_args_adjustment].
9130 // Type parameters up to [num_free_fun_type_params] are not adjusted.
9131 virtual AbstractTypePtr UpdateFunctionTypes(
9132 intptr_t num_parent_type_args_adjustment,
9133 intptr_t num_free_fun_type_params,
9134 Heap::Space space,
9135 FunctionTypeMapping* function_type_mapping) const;
9136
9137 // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
9138 virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
9139 return Canonicalize(thread);
9140 }
9141
9142 // Return the canonical version of this type.
9143 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
9144
9145 // Add the pair <name, uri> to the list, if not already present.
9146 static void AddURI(URIs* uris, const String& name, const String& uri);
9147
9148 // Return a formatted string of the uris.
9149 static StringPtr PrintURIs(URIs* uris);
9150
9151 // Returns a C-String (possibly "") representing the nullability of this type.
9152 // Legacy and undetermined suffixes are only displayed with kInternalName.
9153 virtual const char* NullabilitySuffix(NameVisibility name_visibility) const;
9154
9155 // The name of this type, including the names of its type arguments, if any.
9156 StringPtr Name() const;
9157 const char* NameCString() const;
9158
9159 // The name of this type, including the names of its type arguments, if any.
9160 // Names of internal classes are mapped to their public interfaces.
9161 StringPtr UserVisibleName() const;
9162 const char* UserVisibleNameCString() const;
9163
9164 // The name of this type, including the names of its type arguments, if any.
9165 // Privacy suffixes are dropped.
9166 StringPtr ScrubbedName() const;
9167 const char* ScrubbedNameCString() const;
9168
9169 // Return the internal or public name of this type, including the names of its
9170 // type arguments, if any.
9171 virtual void PrintName(NameVisibility visibility,
9172 BaseTextBuffer* printer) const;
9173
9174 // Add the class name and URI of each occurring type to the uris
9175 // list and mark ambiguous triplets to be printed.
9176 virtual void EnumerateURIs(URIs* uris) const;
9177
9178 uword Hash() const;
9179 virtual uword ComputeHash() const;
9180
9181 // The name of this type's class, i.e. without the type argument names of this
9182 // type.
9183 StringPtr ClassName() const;
9184
9185 // Check if this type represents the 'dynamic' type.
9186 bool IsDynamicType() const { return type_class_id() == kDynamicCid; }
9187
9188 // Check if this type represents the 'void' type.
9189 bool IsVoidType() const { return type_class_id() == kVoidCid; }
9190
9191 // Check if this type represents the 'Null' type.
9192 bool IsNullType() const;
9193
9194 // Check if this type represents the 'Never' type.
9195 bool IsNeverType() const;
9196
9197 // Check if this type represents the 'Sentinel' type.
9198 bool IsSentinelType() const;
9199
9200 // Check if this type represents the 'Object' type.
9201 bool IsObjectType() const { return type_class_id() == kInstanceCid; }
9202
9203 // Check if this type represents the 'Object?' type.
9205 return IsObjectType() && (nullability() == Nullability::kNullable);
9206 }
9207
9208 // Check if this type represents a top type for subtyping,
9209 // assignability and 'as' type tests.
9210 //
9211 // Returns true if
9212 // - any type is a subtype of this type;
9213 // - any value can be assigned to a variable of this type;
9214 // - 'as' type test always succeeds for this type.
9215 bool IsTopTypeForSubtyping() const;
9216
9217 // Check if this type represents a top type for 'is' type tests.
9218 // Returns true if 'is' type test always returns true for this type.
9219 bool IsTopTypeForInstanceOf() const;
9220
9221 // Check if this type represents the 'bool' type.
9222 bool IsBoolType() const { return type_class_id() == kBoolCid; }
9223
9224 // Check if this type represents the 'int' type.
9225 bool IsIntType() const;
9226
9227 // Check if this type represents the '_IntegerImplementation' type.
9228 bool IsIntegerImplementationType() const;
9229
9230 // Check if this type represents the 'double' type.
9231 bool IsDoubleType() const;
9232
9233 // Check if this type represents the 'Float32x4' type.
9234 bool IsFloat32x4Type() const;
9235
9236 // Check if this type represents the 'Float64x2' type.
9237 bool IsFloat64x2Type() const;
9238
9239 // Check if this type represents the 'Int32x4' type.
9240 bool IsInt32x4Type() const;
9241
9242 // Check if this type represents the 'num' type.
9243 bool IsNumberType() const { return type_class_id() == kNumberCid; }
9244
9245 // Check if this type represents the '_Smi' type.
9246 bool IsSmiType() const { return type_class_id() == kSmiCid; }
9247
9248 // Check if this type represents the '_Mint' type.
9249 bool IsMintType() const { return type_class_id() == kMintCid; }
9250
9251 // Check if this type represents the 'String' type.
9252 bool IsStringType() const;
9253
9254 // Check if this type represents the Dart 'Function' type.
9255 bool IsDartFunctionType() const;
9256
9257 // Check if this type represents the Dart '_Closure' type.
9258 bool IsDartClosureType() const;
9259
9260 // Check if this type represents the Dart 'Record' type.
9261 bool IsDartRecordType() const;
9262
9263 // Check if this type represents the 'Pointer' type from "dart:ffi".
9264 bool IsFfiPointerType() const;
9265
9266 // Check if this type represents the 'FutureOr' type.
9267 bool IsFutureOrType() const { return type_class_id() == kFutureOrCid; }
9268
9269 // Returns the type argument of this (possibly nested) 'FutureOr' type.
9270 // Returns unmodified type if this type is not a 'FutureOr' type.
9271 AbstractTypePtr UnwrapFutureOr() const;
9272
9273 // Returns true if catching this type will catch all exceptions.
9274 // Exception objects are guaranteed to be non-nullable, so
9275 // non-nullable Object is also a catch-all type.
9276 bool IsCatchAllType() const { return IsDynamicType() || IsObjectType(); }
9277
9278 // Returns true if this type has a type class permitted by SendPort.send for
9279 // messages between isolates in different groups. Does not recursively visit
9280 // type arguments.
9281 bool IsTypeClassAllowedBySpawnUri() const;
9282
9283 // Check the subtype relationship.
9284 bool IsSubtypeOf(
9285 const AbstractType& other,
9286 Heap::Space space,
9287 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9288
9289 // Returns true iff subtype is a subtype of supertype, false otherwise or if
9290 // an error occurred.
9291 static bool InstantiateAndTestSubtype(
9292 AbstractType* subtype,
9293 AbstractType* supertype,
9294 const TypeArguments& instantiator_type_args,
9295 const TypeArguments& function_type_args);
9296
9298 return OFFSET_OF(UntaggedAbstractType, type_test_stub_entry_point_);
9299 }
9300
9302 return untag()->type_test_stub_entry_point_;
9303 }
9304 CodePtr type_test_stub() const { return untag()->type_test_stub(); }
9305
9306 // Sets the TTS to [stub].
9307 //
9308 // The update will ensure both fields (code as well as the cached entrypoint)
9309 // are updated together.
9310 //
9311 // Can be used concurrently by multiple threads - the updates will be applied
9312 // in undetermined order - but always consistently.
9313 void SetTypeTestingStub(const Code& stub) const;
9314
9315 // Sets the TTS to the [stub].
9316 //
9317 // The caller has to ensure no other thread can concurrently try to update the
9318 // TTS. This should mainly be used when initializing newly allocated Type
9319 // objects.
9320 void InitializeTypeTestingStubNonAtomic(const Code& stub) const;
9321
9323 StoreNonPointer(&untag()->type_test_stub_entry_point_,
9324 Code::EntryPointOf(untag()->type_test_stub()));
9325 }
9326
9327 // No instances of type AbstractType are allocated, but InstanceSize() and
9328 // NextFieldOffset() are required to register class _AbstractType.
9329 static intptr_t InstanceSize() {
9331 }
9332
9333 static intptr_t NextFieldOffset() { return -kWordSize; }
9334
9335 private:
9336 // Returns true if this type is a subtype of FutureOr<T> specified by 'other'.
9337 // Returns false if other type is not a FutureOr.
9338 bool IsSubtypeOfFutureOr(
9339 Zone* zone,
9340 const AbstractType& other,
9341 Heap::Space space,
9342 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9343
9344 protected:
9345 bool IsNullabilityEquivalent(Thread* thread,
9346 const AbstractType& other_type,
9347 TypeEquality kind) const;
9348
9349 void SetHash(intptr_t value) const;
9350
9352 return static_cast<UntaggedAbstractType::TypeState>(
9354 }
9355 void set_flags(uint32_t value) const;
9356 void set_type_state(UntaggedAbstractType::TypeState value) const;
9357 void set_nullability(Nullability value) const;
9358
9360 friend class Class;
9362 friend class Function;
9363 friend class TypeArguments;
9364};
9365
9366// A Type consists of a class, possibly parameterized with type
9367// arguments. Example: C<T1, T2>.
9368class Type : public AbstractType {
9369 public:
9370 static intptr_t arguments_offset() {
9371 return OFFSET_OF(UntaggedType, arguments_);
9372 }
9373 virtual bool HasTypeClass() const {
9374 ASSERT(type_class_id() != kIllegalCid);
9375 return true;
9376 }
9378 virtual classid_t type_class_id() const;
9379 virtual ClassPtr type_class() const;
9380 void set_type_class(const Class& value) const;
9381 virtual TypeArgumentsPtr arguments() const { return untag()->arguments(); }
9383
9384 // Returns flattened instance type arguments vector for
9385 // instance of this type.
9386 TypeArgumentsPtr GetInstanceTypeArguments(Thread* thread,
9387 bool canonicalize = true) const;
9388
9389 virtual bool IsInstantiated(
9390 Genericity genericity = kAny,
9391 intptr_t num_free_fun_type_params = kAllFree) const;
9392 virtual bool IsEquivalent(
9393 const Instance& other,
9394 TypeEquality kind,
9395 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9396
9397 // Return true if this type can be used as the declaration type of cls after
9398 // canonicalization (passed-in cls must match type_class()).
9399 bool IsDeclarationTypeOf(const Class& cls) const;
9400
9401 virtual AbstractTypePtr InstantiateFrom(
9402 const TypeArguments& instantiator_type_arguments,
9403 const TypeArguments& function_type_arguments,
9404 intptr_t num_free_fun_type_params,
9405 Heap::Space space,
9406 FunctionTypeMapping* function_type_mapping = nullptr,
9407 intptr_t num_parent_type_args_adjustment = 0) const;
9408
9409 virtual AbstractTypePtr UpdateFunctionTypes(
9410 intptr_t num_parent_type_args_adjustment,
9411 intptr_t num_free_fun_type_params,
9412 Heap::Space space,
9413 FunctionTypeMapping* function_type_mapping) const;
9414
9415 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
9416 virtual void EnumerateURIs(URIs* uris) const;
9417 virtual void PrintName(NameVisibility visibility,
9418 BaseTextBuffer* printer) const;
9419
9420 virtual uword ComputeHash() const;
9421
9422 static intptr_t InstanceSize() {
9423 return RoundedAllocationSize(sizeof(UntaggedType));
9424 }
9425
9426 // The type of the literal 'null'.
9427 static TypePtr NullType();
9428
9429 // The 'dynamic' type.
9430 static TypePtr DynamicType();
9431
9432 // The 'void' type.
9433 static TypePtr VoidType();
9434
9435 // The 'Never' type.
9436 static TypePtr NeverType();
9437
9438 // The 'Object' type.
9439 static TypePtr ObjectType();
9440
9441 // The 'bool' type.
9442 static TypePtr BoolType();
9443
9444 // The 'int' type.
9445 static TypePtr IntType();
9446
9447 // The 'int?' type.
9448 static TypePtr NullableIntType();
9449
9450 // The 'Smi' type.
9451 static TypePtr SmiType();
9452
9453 // The 'Mint' type.
9454 static TypePtr MintType();
9455
9456 // The 'double' type.
9457 static TypePtr Double();
9458
9459 // The 'double?' type.
9460 static TypePtr NullableDouble();
9461
9462 // The 'Float32x4' type.
9463 static TypePtr Float32x4();
9464
9465 // The 'Float64x2' type.
9466 static TypePtr Float64x2();
9467
9468 // The 'Int32x4' type.
9469 static TypePtr Int32x4();
9470
9471 // The 'num' type.
9472 static TypePtr Number();
9473
9474 // The 'num?' type.
9475 static TypePtr NullableNumber();
9476
9477 // The 'String' type.
9478 static TypePtr StringType();
9479
9480 // The 'Array' type.
9481 static TypePtr ArrayType();
9482
9483 // The 'Function' type.
9484 static TypePtr DartFunctionType();
9485
9486 // The 'Type' type.
9487 static TypePtr DartTypeType();
9488
9489 // The finalized type of the given non-parameterized class.
9490 static TypePtr NewNonParameterizedType(const Class& type_class);
9491
9492 static TypePtr New(const Class& clazz,
9493 const TypeArguments& arguments,
9495 Heap::Space space = Heap::kOld);
9496
9497 private:
9498 // Takes an intptr_t since the cids of some classes are larger than will fit
9499 // in ClassIdTagType. This allows us to guard against that case, instead of
9500 // silently truncating the cid.
9501 void set_type_class_id(intptr_t id) const;
9502
9503 static TypePtr New(Heap::Space space = Heap::kOld);
9504
9506 friend class Class;
9507 friend class TypeArguments;
9508};
9509
9510// A FunctionType represents the type of a function. It describes most of the
9511// signature of a function, excluding the names of type parameters and names
9512// of parameters, but includes the names of optional named parameters.
9514 public:
9515 // Reexported so they can be used by the flow graph builders.
9527
9528 virtual bool HasTypeClass() const { return false; }
9529 FunctionTypePtr ToNullability(Nullability value, Heap::Space space) const;
9530 virtual classid_t type_class_id() const { return kIllegalCid; }
9531 virtual bool IsInstantiated(
9532 Genericity genericity = kAny,
9533 intptr_t num_free_fun_type_params = kAllFree) const;
9534 virtual bool IsEquivalent(
9535 const Instance& other,
9536 TypeEquality kind,
9537 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9538
9539 virtual AbstractTypePtr InstantiateFrom(
9540 const TypeArguments& instantiator_type_arguments,
9541 const TypeArguments& function_type_arguments,
9542 intptr_t num_free_fun_type_params,
9543 Heap::Space space,
9544 FunctionTypeMapping* function_type_mapping = nullptr,
9545 intptr_t num_parent_type_args_adjustment = 0) const;
9546
9547 virtual AbstractTypePtr UpdateFunctionTypes(
9548 intptr_t num_parent_type_args_adjustment,
9549 intptr_t num_free_fun_type_params,
9550 Heap::Space space,
9551 FunctionTypeMapping* function_type_mapping) const;
9552
9553 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
9554 virtual void EnumerateURIs(URIs* uris) const;
9555 virtual void PrintName(NameVisibility visibility,
9556 BaseTextBuffer* printer) const;
9557
9558 virtual uword ComputeHash() const;
9559
9560 bool IsSubtypeOf(
9561 const FunctionType& other,
9562 Heap::Space space,
9563 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9564
9565 static intptr_t NumParentTypeArgumentsOf(FunctionTypePtr ptr) {
9566 return ptr->untag()
9567 ->packed_type_parameter_counts_.Read<PackedNumParentTypeArguments>();
9568 }
9569 // Return the number of type arguments in the enclosing signature.
9570 intptr_t NumParentTypeArguments() const {
9571 return NumParentTypeArgumentsOf(ptr());
9572 }
9573 void SetNumParentTypeArguments(intptr_t value) const;
9574 static intptr_t NumTypeParametersOf(FunctionTypePtr ptr) {
9575 return ptr->untag()
9576 ->packed_type_parameter_counts_.Read<PackedNumTypeParameters>();
9577 }
9578 intptr_t NumTypeParameters() const { return NumTypeParametersOf(ptr()); }
9579
9580 static intptr_t NumTypeArgumentsOf(FunctionTypePtr ptr) {
9581 return NumTypeParametersOf(ptr) + NumParentTypeArgumentsOf(ptr);
9582 }
9583 intptr_t NumTypeArguments() const { return NumTypeArgumentsOf(ptr()); }
9584
9585 intptr_t num_implicit_parameters() const {
9586 return untag()
9587 ->packed_parameter_counts_.Read<PackedNumImplicitParameters>();
9588 }
9589 void set_num_implicit_parameters(intptr_t value) const;
9590
9591 static intptr_t NumFixedParametersOf(FunctionTypePtr ptr) {
9592 return ptr->untag()
9593 ->packed_parameter_counts_.Read<PackedNumFixedParameters>();
9594 }
9595 intptr_t num_fixed_parameters() const { return NumFixedParametersOf(ptr()); }
9596 void set_num_fixed_parameters(intptr_t value) const;
9597
9598 static bool HasOptionalParameters(FunctionTypePtr ptr) {
9599 return ptr->untag()
9600 ->packed_parameter_counts_.Read<PackedNumOptionalParameters>() >
9601 0;
9602 }
9604
9605 static bool HasOptionalNamedParameters(FunctionTypePtr ptr) {
9606 return ptr->untag()
9607 ->packed_parameter_counts_.Read<PackedHasNamedOptionalParameters>();
9608 }
9610 return HasOptionalNamedParameters(ptr());
9611 }
9612 bool HasRequiredNamedParameters() const;
9613
9614 static bool HasOptionalPositionalParameters(FunctionTypePtr ptr) {
9615 return !HasOptionalNamedParameters(ptr) && HasOptionalParameters(ptr);
9616 }
9618 return HasOptionalPositionalParameters(ptr());
9619 }
9620
9621 static intptr_t NumOptionalParametersOf(FunctionTypePtr ptr) {
9622 return ptr->untag()
9623 ->packed_parameter_counts_.Read<PackedNumOptionalParameters>();
9624 }
9625 intptr_t NumOptionalParameters() const {
9626 return NumOptionalParametersOf(ptr());
9627 }
9628 void SetNumOptionalParameters(intptr_t num_optional_parameters,
9629 bool are_optional_positional) const;
9630
9631 static intptr_t NumOptionalPositionalParametersOf(FunctionTypePtr ptr) {
9632 return HasOptionalNamedParameters(ptr) ? 0 : NumOptionalParametersOf(ptr);
9633 }
9635 return NumOptionalPositionalParametersOf(ptr());
9636 }
9637
9638 static intptr_t NumOptionalNamedParametersOf(FunctionTypePtr ptr) {
9639 return HasOptionalNamedParameters(ptr) ? NumOptionalParametersOf(ptr) : 0;
9640 }
9642 return NumOptionalNamedParametersOf(ptr());
9643 }
9644
9645 static intptr_t NumParametersOf(FunctionTypePtr ptr) {
9646 return NumFixedParametersOf(ptr) + NumOptionalParametersOf(ptr);
9647 }
9648 intptr_t NumParameters() const { return NumParametersOf(ptr()); }
9649
9650 uint32_t packed_parameter_counts() const {
9651 return untag()->packed_parameter_counts_;
9652 }
9653 void set_packed_parameter_counts(uint32_t packed_parameter_counts) const;
9655 return OFFSET_OF(UntaggedFunctionType, packed_parameter_counts_);
9656 }
9658 return untag()->packed_type_parameter_counts_;
9659 }
9660 void set_packed_type_parameter_counts(uint16_t packed_parameter_counts) const;
9662 return OFFSET_OF(UntaggedFunctionType, packed_type_parameter_counts_);
9663 }
9664
9665 // Return the type parameter declared at index.
9666 TypeParameterPtr TypeParameterAt(
9667 intptr_t index,
9668 Nullability nullability = Nullability::kNonNullable) const;
9669
9670 AbstractTypePtr result_type() const { return untag()->result_type(); }
9671 void set_result_type(const AbstractType& value) const;
9672
9673 // The parameters, starting with NumImplicitParameters() parameters which are
9674 // only visible to the VM, but not to Dart users.
9675 // Note that type checks exclude implicit parameters.
9676 AbstractTypePtr ParameterTypeAt(intptr_t index) const;
9677 void SetParameterTypeAt(intptr_t index, const AbstractType& value) const;
9678 ArrayPtr parameter_types() const { return untag()->parameter_types(); }
9679 void set_parameter_types(const Array& value) const;
9680 static intptr_t parameter_types_offset() {
9681 return OFFSET_OF(UntaggedFunctionType, parameter_types_);
9682 }
9683 // Parameter names are only stored for named parameters. If there are no named
9684 // parameters, named_parameter_names() is null.
9685 // If there are parameter flags (eg required) they're stored at the end of
9686 // this array, so the size of this array isn't necessarily
9687 // NumOptionalNamedParameters(), but the first NumOptionalNamedParameters()
9688 // elements are the names.
9689 ArrayPtr named_parameter_names() const {
9690 return untag()->named_parameter_names();
9691 }
9692 void set_named_parameter_names(const Array& value) const;
9694 return OFFSET_OF(UntaggedFunctionType, named_parameter_names_);
9695 }
9696 // The index for these operations is the absolute index of the parameter, not
9697 // the index relative to the start of the named parameters (if any).
9698 StringPtr ParameterNameAt(intptr_t index) const;
9699 // Only valid for absolute indexes of named parameters.
9700 void SetParameterNameAt(intptr_t index, const String& value) const;
9701
9702 // The required flags are stored at the end of the parameter_names. The flags
9703 // are packed into SMIs, but omitted if they're 0.
9704 bool IsRequiredAt(intptr_t index) const;
9705 void SetIsRequiredAt(intptr_t index) const;
9706
9707 // Sets up the signature's parameter name array, including appropriate space
9708 // for any possible parameter flags. This may be an overestimate if some
9709 // parameters don't have flags, and so FinalizeNameArray() should
9710 // be called after all parameter flags have been appropriately set.
9711 //
9712 // Assumes that the number of fixed and optional parameters for the signature
9713 // has already been set. Uses same default space as FunctionType::New.
9714 void CreateNameArrayIncludingFlags(Heap::Space space = Heap::kOld) const;
9715
9716 // Truncate the parameter names array to remove any unused flag slots. Make
9717 // sure to only do this after calling SetIsRequiredAt as necessary.
9718 void FinalizeNameArray() const;
9719
9720 // Returns the length of the parameter names array that is required to store
9721 // all the names plus all their flags. This may be an overestimate if some
9722 // parameters don't have flags.
9723 static intptr_t NameArrayLengthIncludingFlags(intptr_t num_parameters);
9724
9725 // The formal type parameters, their bounds, and defaults, are specified as an
9726 // object of type TypeParameters.
9727 TypeParametersPtr type_parameters() const {
9728 return untag()->type_parameters();
9729 }
9730 void SetTypeParameters(const TypeParameters& value) const;
9731 static intptr_t type_parameters_offset() {
9732 return OFFSET_OF(UntaggedFunctionType, type_parameters_);
9733 }
9734
9735 // Returns true if this function type has the same number of type parameters
9736 // with equal bounds as the other function type. Type parameter names and
9737 // parameter names (unless optional named) are ignored.
9738 bool HasSameTypeParametersAndBounds(
9739 const FunctionType& other,
9740 TypeEquality kind,
9741 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9742
9743 // Return true if this function type declares type parameters.
9744 static bool IsGeneric(FunctionTypePtr ptr) {
9745 return ptr->untag()->type_parameters() != TypeParameters::null();
9746 }
9747 bool IsGeneric() const { return IsGeneric(ptr()); }
9748
9749 // Return true if any enclosing signature of this signature is generic.
9750 bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
9751
9752 // Returns true if the type of the formal parameter at the given position in
9753 // this function type is contravariant with the type of the other formal
9754 // parameter at the given position in the other function type.
9755 bool IsContravariantParameter(
9756 intptr_t parameter_position,
9757 const FunctionType& other,
9758 intptr_t other_parameter_position,
9759 Heap::Space space,
9760 FunctionTypeMapping* function_type_equivalence) const;
9761
9762 // Returns the index in the parameter names array of the corresponding flag
9763 // for the given parameter index. Also returns (via flag_mask) the
9764 // corresponding mask within the flag.
9765 intptr_t GetRequiredFlagIndex(intptr_t index, intptr_t* flag_mask) const;
9766
9767 void Print(NameVisibility name_visibility, BaseTextBuffer* printer) const;
9768 void PrintParameters(Thread* thread,
9769 Zone* zone,
9770 NameVisibility name_visibility,
9771 BaseTextBuffer* printer) const;
9772
9773 StringPtr ToUserVisibleString() const;
9774 const char* ToUserVisibleCString() const;
9775
9776 static intptr_t InstanceSize() {
9778 }
9779
9780 static FunctionTypePtr New(
9781 intptr_t num_parent_type_arguments = 0,
9783 Heap::Space space = Heap::kOld);
9784
9785 static FunctionTypePtr Clone(const FunctionType& orig, Heap::Space space);
9786
9787 bool ContainsHandles() const;
9788
9789 private:
9790 static FunctionTypePtr New(Heap::Space space);
9791
9793 friend class Class;
9794 friend class Function;
9795};
9796
9797// A TypeParameter represents a type parameter of a parameterized class.
9798// It specifies its index (and its name for debugging purposes), as well as its
9799// upper bound.
9800// For example, the type parameter 'V' is specified as index 1 in the context of
9801// the class HashMap<K, V>. At compile time, the TypeParameter is not
9802// instantiated yet, i.e. it is only a place holder.
9803// Upon finalization, the TypeParameter index is changed to reflect its position
9804// as type argument (rather than type parameter) of the parameterized class.
9805// If the type parameter is declared without an extends clause, its bound is set
9806// to the ObjectType.
9808 public:
9809 TypeParameterPtr ToNullability(Nullability value, Heap::Space space) const;
9810 virtual bool HasTypeClass() const { return false; }
9811 virtual classid_t type_class_id() const { return kIllegalCid; }
9812
9815 untag()->flags());
9816 }
9817 bool IsClassTypeParameter() const { return !IsFunctionTypeParameter(); }
9818
9819 intptr_t base() const { return untag()->base_; }
9820 void set_base(intptr_t value) const;
9821 intptr_t index() const { return untag()->index_; }
9822 void set_index(intptr_t value) const;
9823 static intptr_t index_offset() {
9824 return OFFSET_OF(UntaggedTypeParameter, index_);
9825 }
9826
9827 classid_t parameterized_class_id() const;
9828 void set_parameterized_class_id(classid_t value) const;
9829 ClassPtr parameterized_class() const;
9830 FunctionTypePtr parameterized_function_type() const;
9831
9832 AbstractTypePtr bound() const;
9833
9834 virtual bool IsInstantiated(
9835 Genericity genericity = kAny,
9836 intptr_t num_free_fun_type_params = kAllFree) const;
9837 virtual bool IsEquivalent(
9838 const Instance& other,
9839 TypeEquality kind,
9840 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9841 virtual AbstractTypePtr InstantiateFrom(
9842 const TypeArguments& instantiator_type_arguments,
9843 const TypeArguments& function_type_arguments,
9844 intptr_t num_free_fun_type_params,
9845 Heap::Space space,
9846 FunctionTypeMapping* function_type_mapping = nullptr,
9847 intptr_t num_parent_type_args_adjustment = 0) const;
9848
9849 virtual AbstractTypePtr UpdateFunctionTypes(
9850 intptr_t num_parent_type_args_adjustment,
9851 intptr_t num_free_fun_type_params,
9852 Heap::Space space,
9853 FunctionTypeMapping* function_type_mapping) const;
9854
9855 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
9856 virtual void EnumerateURIs(URIs* uris) const { return; }
9857 virtual void PrintName(NameVisibility visibility,
9858 BaseTextBuffer* printer) const;
9859
9860 // Returns type corresponding to [this] type parameter from the
9861 // given [instantiator_type_arguments] and [function_type_arguments].
9862 // Unlike InstantiateFrom, nullability of type parameter is not applied to
9863 // the result.
9864 AbstractTypePtr GetFromTypeArguments(
9865 const TypeArguments& instantiator_type_arguments,
9866 const TypeArguments& function_type_arguments) const;
9867
9868 // Return a constructed name for this nameless type parameter.
9869 const char* CanonicalNameCString() const {
9870 return CanonicalNameCString(IsClassTypeParameter(), base(), index());
9871 }
9872
9873 static const char* CanonicalNameCString(bool is_class_type_parameter,
9874 intptr_t base,
9875 intptr_t index);
9876
9877 static intptr_t InstanceSize() {
9879 }
9880
9881 // 'owner' is a Class or FunctionType.
9882 static TypeParameterPtr New(const Object& owner,
9883 intptr_t base,
9884 intptr_t index,
9885 Nullability nullability);
9886
9887 private:
9888 virtual uword ComputeHash() const;
9889
9890 void set_owner(const Object& value) const;
9891
9892 static TypeParameterPtr New();
9893
9895 friend class Class;
9896};
9897
9898class Number : public Instance {
9899 public:
9900 // TODO(iposva): Add more useful Number methods.
9901 StringPtr ToString(Heap::Space space) const;
9902
9903 private:
9905
9906 friend class Class;
9907};
9908
9909class Integer : public Number {
9910 public:
9911 static IntegerPtr New(const String& str, Heap::Space space = Heap::kNew);
9912
9913 // Creates a new Integer by given uint64_t value.
9914 // Silently casts value to int64_t with wrap-around if it is greater
9915 // than kMaxInt64.
9916 static IntegerPtr NewFromUint64(uint64_t value,
9917 Heap::Space space = Heap::kNew);
9918
9919 // Returns a canonical Integer object allocated in the old gen space.
9920 // Returns null if integer is out of range.
9921 static IntegerPtr NewCanonical(const String& str);
9922 static IntegerPtr NewCanonical(int64_t value);
9923
9924 static IntegerPtr New(int64_t value, Heap::Space space = Heap::kNew);
9925
9926 // Returns true iff the given uint64_t value is representable as Dart integer.
9927 static bool IsValueInRange(uint64_t value);
9928
9929 virtual bool OperatorEquals(const Instance& other) const {
9930 return Equals(other);
9931 }
9932 virtual bool CanonicalizeEquals(const Instance& other) const {
9933 return Equals(other);
9934 }
9935 virtual uint32_t CanonicalizeHash() const;
9936 virtual bool Equals(const Instance& other) const;
9937
9938 virtual ObjectPtr HashCode() const { return ptr(); }
9939
9940 virtual bool IsZero() const;
9941 virtual bool IsNegative() const;
9942
9943 virtual double AsDoubleValue() const;
9944 virtual int64_t AsInt64Value() const;
9945 virtual int64_t AsTruncatedInt64Value() const { return AsInt64Value(); }
9946 virtual uint32_t AsTruncatedUint32Value() const;
9947
9948 virtual bool FitsIntoSmi() const;
9949
9950 // Returns 0, -1 or 1.
9951 virtual int CompareWith(const Integer& other) const;
9952
9953 // Converts integer to hex string.
9954 const char* ToHexCString(Zone* zone) const;
9955
9956 // Return the most compact presentation of an integer.
9957 IntegerPtr AsValidInteger() const;
9958
9959 // Returns null to indicate that a bigint operation is required.
9960 IntegerPtr ArithmeticOp(Token::Kind operation,
9961 const Integer& other,
9962 Heap::Space space = Heap::kNew) const;
9963 IntegerPtr BitOp(Token::Kind operation,
9964 const Integer& other,
9965 Heap::Space space = Heap::kNew) const;
9966 IntegerPtr ShiftOp(Token::Kind operation,
9967 const Integer& other,
9968 Heap::Space space = Heap::kNew) const;
9969
9970 static int64_t GetInt64Value(const IntegerPtr obj) {
9971 if (obj->IsSmi()) {
9972 return RawSmiValue(static_cast<const SmiPtr>(obj));
9973 } else {
9974 ASSERT(obj->IsMint());
9975 return static_cast<const MintPtr>(obj)->untag()->value_;
9976 }
9977 }
9978
9979 private:
9981 friend class Class;
9982};
9983
9984class Smi : public Integer {
9985 public:
9986 static constexpr intptr_t kBits = kSmiBits;
9987 static constexpr intptr_t kMaxValue = kSmiMax;
9988 static constexpr intptr_t kMinValue = kSmiMin;
9989
9990 intptr_t Value() const { return RawSmiValue(ptr()); }
9991
9992 virtual bool Equals(const Instance& other) const;
9993 virtual bool IsZero() const { return Value() == 0; }
9994 virtual bool IsNegative() const { return Value() < 0; }
9995
9996 virtual double AsDoubleValue() const;
9997 virtual int64_t AsInt64Value() const;
9998 virtual uint32_t AsTruncatedUint32Value() const;
9999
10000 virtual bool FitsIntoSmi() const { return true; }
10001
10002 virtual int CompareWith(const Integer& other) const;
10003
10004 static intptr_t InstanceSize() { return 0; }
10005
10006 static SmiPtr New(intptr_t value) {
10007 SmiPtr raw_smi = static_cast<SmiPtr>(
10008 (static_cast<uintptr_t>(value) << kSmiTagShift) | kSmiTag);
10009 ASSERT(RawSmiValue(raw_smi) == value);
10010 return raw_smi;
10011 }
10012
10013 static ClassPtr Class();
10014
10015 static intptr_t Value(const SmiPtr raw_smi) { return RawSmiValue(raw_smi); }
10016#if defined(DART_COMPRESSED_POINTERS)
10017 static intptr_t Value(const CompressedSmiPtr raw_smi) {
10018 return Smi::Value(static_cast<SmiPtr>(raw_smi.DecompressSmi()));
10019 }
10020#endif
10021
10022 static intptr_t RawValue(intptr_t value) {
10023 return static_cast<intptr_t>(New(value));
10024 }
10025
10026 static bool IsValid(int64_t value) { return compiler::target::IsSmi(value); }
10027
10028 void operator=(SmiPtr value) {
10029 ptr_ = value;
10030 CHECK_HANDLE();
10031 }
10033 ptr_ = value;
10034 CHECK_HANDLE();
10035 }
10036
10037 private:
10038 static intptr_t NextFieldOffset() {
10039 // Indicates this class cannot be extended by dart code.
10040 return -kWordSize;
10041 }
10042
10043 Smi() : Integer() {}
10044 BASE_OBJECT_IMPLEMENTATION(Smi, Integer);
10046 friend class Api; // For ValueFromRaw
10047 friend class Class;
10048 friend class Object;
10049 friend class ReusableSmiHandleScope;
10050 friend class Thread;
10051};
10052
10054 public:
10055 static const char* Name() { return "SmiTraits"; }
10056 static bool ReportStats() { return false; }
10057
10058 static bool IsMatch(const Object& a, const Object& b) {
10059 return Smi::Cast(a).Value() == Smi::Cast(b).Value();
10060 }
10061
10062 static uword Hash(const Object& obj) { return Smi::Cast(obj).Value(); }
10063};
10064
10065class Mint : public Integer {
10066 public:
10067 static constexpr intptr_t kBits = 63; // 64-th bit is sign.
10068 static constexpr int64_t kMaxValue =
10069 static_cast<int64_t>(DART_2PART_UINT64_C(0x7FFFFFFF, FFFFFFFF));
10070 static constexpr int64_t kMinValue =
10071 static_cast<int64_t>(DART_2PART_UINT64_C(0x80000000, 00000000));
10072
10073 int64_t value() const { return untag()->value_; }
10074 static intptr_t value_offset() { return OFFSET_OF(UntaggedMint, value_); }
10075 static int64_t Value(MintPtr mint) { return mint->untag()->value_; }
10076
10077 virtual bool IsZero() const { return value() == 0; }
10078 virtual bool IsNegative() const { return value() < 0; }
10079
10080 virtual bool Equals(const Instance& other) const;
10081
10082 virtual double AsDoubleValue() const;
10083 virtual int64_t AsInt64Value() const;
10084 virtual uint32_t AsTruncatedUint32Value() const;
10085
10086 virtual bool FitsIntoSmi() const;
10087
10088 virtual int CompareWith(const Integer& other) const;
10089
10090 static intptr_t InstanceSize() {
10091 return RoundedAllocationSize(sizeof(UntaggedMint));
10092 }
10093
10094 protected:
10095 // Only Integer::NewXXX is allowed to call Mint::NewXXX directly.
10096 friend class Integer;
10098
10099 static MintPtr New(int64_t value, Heap::Space space = Heap::kNew);
10100
10101 static MintPtr NewCanonical(int64_t value);
10102
10103 private:
10104 void set_value(int64_t value) const;
10105
10107 friend class Class;
10108 friend class Number;
10109};
10110
10111// Class Double represents class Double in corelib_impl, which implements
10112// abstract class double in corelib.
10113class Double : public Number {
10114 public:
10115 double value() const { return untag()->value_; }
10116 static double Value(DoublePtr dbl) { return dbl->untag()->value_; }
10117
10118 bool BitwiseEqualsToDouble(double value) const;
10119 virtual bool OperatorEquals(const Instance& other) const;
10120 virtual bool CanonicalizeEquals(const Instance& other) const;
10121 virtual uint32_t CanonicalizeHash() const;
10122
10123 static DoublePtr New(double d, Heap::Space space = Heap::kNew);
10124
10125 static DoublePtr New(const String& str, Heap::Space space = Heap::kNew);
10126
10127 // Returns a canonical double object allocated in the old gen space.
10128 static DoublePtr NewCanonical(double d);
10129
10130 // Returns a canonical double object (allocated in the old gen space) or
10131 // Double::null() if str points to a string that does not convert to a
10132 // double value.
10133 static DoublePtr NewCanonical(const String& str);
10134
10135 static intptr_t InstanceSize() {
10136 return RoundedAllocationSize(sizeof(UntaggedDouble));
10137 }
10138
10139 static intptr_t value_offset() { return OFFSET_OF(UntaggedDouble, value_); }
10140
10141 private:
10142 void set_value(double value) const;
10143
10145 friend class Class;
10146 friend class Number;
10147};
10148
10149// TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
10150class Symbol : public AllStatic {
10151 public:
10152 static bool IsSymbolCid(Thread* thread, classid_t class_id);
10153
10154 static uint32_t CanonicalizeHash(Thread* thread, const Instance& instance);
10155};
10156
10157// String may not be '\0' terminated.
10158class String : public Instance {
10159 public:
10160 static constexpr intptr_t kOneByteChar = 1;
10161 static constexpr intptr_t kTwoByteChar = 2;
10162
10163// All strings share the same maximum element count to keep things
10164// simple. We choose a value that will prevent integer overflow for
10165// 2 byte strings, since it is the worst case.
10166#if defined(HASH_IN_OBJECT_HEADER)
10167 static constexpr intptr_t kSizeofRawString =
10168 sizeof(UntaggedInstance) + kWordSize;
10169#else
10170 static constexpr intptr_t kSizeofRawString =
10171 sizeof(UntaggedInstance) + 2 * kWordSize;
10172#endif
10173 static constexpr intptr_t kMaxElements = kSmiMax / kTwoByteChar;
10174
10175 static intptr_t HeaderSize() { return String::kSizeofRawString; }
10176
10177 static intptr_t InstanceSize() {
10178 return RoundedAllocationSize(sizeof(UntaggedString));
10179 }
10180
10182 public:
10183 explicit CodePointIterator(const String& str)
10184 : str_(str), ch_(0), index_(-1), end_(str.Length()) {
10185 ASSERT(!str_.IsNull());
10186 }
10187
10188 CodePointIterator(const String& str, intptr_t start, intptr_t length)
10189 : str_(str), ch_(0), index_(start - 1), end_(start + length) {
10190 ASSERT(start >= 0);
10191 ASSERT(end_ <= str.Length());
10192 }
10193
10194 int32_t Current() const {
10195 ASSERT(index_ >= 0);
10196 ASSERT(index_ < end_);
10197 return ch_;
10198 }
10199
10200 bool Next();
10201
10202 private:
10203 const String& str_;
10204 int32_t ch_;
10205 intptr_t index_;
10206 intptr_t end_;
10208 };
10209
10210 intptr_t Length() const { return LengthOf(ptr()); }
10211 static intptr_t LengthOf(StringPtr obj) {
10212 return Smi::Value(obj->untag()->length());
10213 }
10214 static intptr_t length_offset() { return OFFSET_OF(UntaggedString, length_); }
10215
10216 uword Hash() const {
10217 uword result = GetCachedHash(ptr());
10218 if (result != 0) {
10219 return result;
10220 }
10221 result = String::Hash(*this, 0, this->Length());
10222 uword set_hash = SetCachedHashIfNotSet(ptr(), result);
10223 ASSERT(set_hash == result);
10224 return result;
10225 }
10226
10227 static uword Hash(StringPtr raw);
10228
10229 bool HasHash() const {
10230 ASSERT(Smi::New(0) == nullptr);
10231 return GetCachedHash(ptr()) != 0;
10232 }
10233
10234 static intptr_t hash_offset() {
10235#if defined(HASH_IN_OBJECT_HEADER)
10237 return OFFSET_OF(UntaggedObject, tags_) +
10239#else
10240 return OFFSET_OF(UntaggedString, hash_);
10241#endif
10242 }
10243 static uword Hash(const String& str, intptr_t begin_index, intptr_t len);
10244 static uword Hash(const char* characters, intptr_t len);
10245 static uword Hash(const uint16_t* characters, intptr_t len);
10246 static uword Hash(const int32_t* characters, intptr_t len);
10247 static uword HashRawSymbol(const StringPtr symbol) {
10248 ASSERT(symbol->untag()->IsCanonical());
10249 const uword result = GetCachedHash(symbol);
10250 ASSERT(result != 0);
10251 return result;
10252 }
10253
10254 // Returns the hash of str1 + str2.
10255 static uword HashConcat(const String& str1, const String& str2);
10256
10257 virtual ObjectPtr HashCode() const { return Integer::New(Hash()); }
10258
10259 uint16_t CharAt(intptr_t index) const { return CharAt(ptr(), index); }
10260 static uint16_t CharAt(StringPtr str, intptr_t index);
10261
10262 intptr_t CharSize() const;
10263
10264 inline bool Equals(const String& str) const;
10265
10266 bool Equals(const String& str,
10267 intptr_t begin_index, // begin index on 'str'.
10268 intptr_t len) const; // len on 'str'.
10269
10270 // Compares to a '\0' terminated array of UTF-8 encoded characters.
10271 bool Equals(const char* cstr) const;
10272
10273 // Compares to an array of Latin-1 encoded characters.
10274 bool EqualsLatin1(const uint8_t* characters, intptr_t len) const {
10275 return Equals(characters, len);
10276 }
10277
10278 // Compares to an array of UTF-16 encoded characters.
10279 bool Equals(const uint16_t* characters, intptr_t len) const;
10280
10281 // Compares to an array of UTF-32 encoded characters.
10282 bool Equals(const int32_t* characters, intptr_t len) const;
10283
10284 // True iff this string equals str1 + str2.
10285 bool EqualsConcat(const String& str1, const String& str2) const;
10286
10287 virtual bool OperatorEquals(const Instance& other) const {
10288 return Equals(other);
10289 }
10290 virtual bool CanonicalizeEquals(const Instance& other) const {
10291 return Equals(other);
10292 }
10293 virtual uint32_t CanonicalizeHash() const { return Hash(); }
10294 virtual bool Equals(const Instance& other) const;
10295
10296 intptr_t CompareTo(const String& other) const;
10297
10298 bool StartsWith(const String& other) const {
10299 NoSafepointScope no_safepoint;
10300 return StartsWith(ptr(), other.ptr());
10301 }
10302 static bool StartsWith(StringPtr str, StringPtr prefix);
10303 bool EndsWith(const String& other) const;
10304
10305 // Strings are canonicalized using the symbol table.
10306 // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
10307 virtual InstancePtr CanonicalizeLocked(Thread* thread) const;
10308
10309 bool IsSymbol() const { return ptr()->untag()->IsCanonical(); }
10310
10311 bool IsOneByteString() const {
10312 return ptr()->GetClassId() == kOneByteStringCid;
10313 }
10314
10315 bool IsTwoByteString() const {
10316 return ptr()->GetClassId() == kTwoByteStringCid;
10317 }
10318
10319 char* ToMallocCString() const;
10320 void ToUTF8(uint8_t* utf8_array, intptr_t array_len) const;
10321 static const char* ToCString(Thread* thread, StringPtr ptr);
10322
10323 // Creates a new String object from a C string that is assumed to contain
10324 // UTF-8 encoded characters and '\0' is considered a termination character.
10325 // TODO(7123) - Rename this to FromCString(....).
10326 static StringPtr New(const char* cstr, Heap::Space space = Heap::kNew);
10327
10328 // Creates a new String object from an array of UTF-8 encoded characters.
10329 static StringPtr FromUTF8(const uint8_t* utf8_array,
10330 intptr_t array_len,
10331 Heap::Space space = Heap::kNew);
10332
10333 // Creates a new String object from an array of Latin-1 encoded characters.
10334 static StringPtr FromLatin1(const uint8_t* latin1_array,
10335 intptr_t array_len,
10336 Heap::Space space = Heap::kNew);
10337
10338 // Creates a new String object from an array of UTF-16 encoded characters.
10339 static StringPtr FromUTF16(const uint16_t* utf16_array,
10340 intptr_t array_len,
10341 Heap::Space space = Heap::kNew);
10342
10343 // Creates a new String object from an array of UTF-32 encoded characters.
10344 static StringPtr FromUTF32(const int32_t* utf32_array,
10345 intptr_t array_len,
10346 Heap::Space space = Heap::kNew);
10347
10348 // Create a new String object from another Dart String instance.
10349 static StringPtr New(const String& str, Heap::Space space = Heap::kNew);
10350
10351 // Creates a new External String object using the specified array of
10352 // UTF-8 encoded characters as the external reference.
10353 static StringPtr NewExternal(const uint8_t* utf8_array,
10354 intptr_t array_len,
10355 void* peer,
10356 intptr_t external_allocation_size,
10359
10360 // Creates a new External String object using the specified array of
10361 // UTF-16 encoded characters as the external reference.
10362 static StringPtr NewExternal(const uint16_t* utf16_array,
10363 intptr_t array_len,
10364 void* peer,
10365 intptr_t external_allocation_size,
10368
10369 static void Copy(const String& dst,
10370 intptr_t dst_offset,
10371 const uint8_t* characters,
10372 intptr_t len);
10373 static void Copy(const String& dst,
10374 intptr_t dst_offset,
10375 const uint16_t* characters,
10376 intptr_t len);
10377 static void Copy(const String& dst,
10378 intptr_t dst_offset,
10379 const String& src,
10380 intptr_t src_offset,
10381 intptr_t len);
10382
10383 static StringPtr EscapeSpecialCharacters(const String& str);
10384 // Encodes 'str' for use in an Internationalized Resource Identifier (IRI),
10385 // a generalization of URI (percent-encoding). See RFC 3987.
10386 static const char* EncodeIRI(const String& str);
10387 // Returns null if 'str' is not a valid encoding.
10388 static StringPtr DecodeIRI(const String& str);
10389 static StringPtr Concat(const String& str1,
10390 const String& str2,
10391 Heap::Space space = Heap::kNew);
10392 static StringPtr ConcatAll(const Array& strings,
10393 Heap::Space space = Heap::kNew);
10394 // Concat all strings in 'strings' from 'start' to 'end' (excluding).
10395 static StringPtr ConcatAllRange(const Array& strings,
10396 intptr_t start,
10397 intptr_t end,
10398 Heap::Space space = Heap::kNew);
10399
10400 static StringPtr SubString(const String& str,
10401 intptr_t begin_index,
10402 Heap::Space space = Heap::kNew);
10403 static StringPtr SubString(const String& str,
10404 intptr_t begin_index,
10405 intptr_t length,
10406 Heap::Space space = Heap::kNew) {
10407 return SubString(Thread::Current(), str, begin_index, length, space);
10408 }
10409 static StringPtr SubString(Thread* thread,
10410 const String& str,
10411 intptr_t begin_index,
10412 intptr_t length,
10413 Heap::Space space = Heap::kNew);
10414
10415 static StringPtr Transform(int32_t (*mapping)(int32_t ch),
10416 const String& str,
10417 Heap::Space space = Heap::kNew);
10418
10419 static StringPtr ToUpperCase(const String& str,
10420 Heap::Space space = Heap::kNew);
10421 static StringPtr ToLowerCase(const String& str,
10422 Heap::Space space = Heap::kNew);
10423
10424 static StringPtr RemovePrivateKey(const String& name);
10425
10426 static const char* ScrubName(const String& name, bool is_extension = false);
10427 static StringPtr ScrubNameRetainPrivate(const String& name,
10428 bool is_extension = false);
10429
10430 static bool EqualsIgnoringPrivateKey(const String& str1, const String& str2);
10431
10432 static StringPtr NewFormatted(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
10433 static StringPtr NewFormatted(Heap::Space space, const char* format, ...)
10434 PRINTF_ATTRIBUTE(2, 3);
10435 static StringPtr NewFormattedV(const char* format,
10436 va_list args,
10437 Heap::Space space = Heap::kNew);
10438
10439 static bool ParseDouble(const String& str,
10440 intptr_t start,
10441 intptr_t end,
10442 double* result);
10443
10444#if !defined(HASH_IN_OBJECT_HEADER)
10445 static uint32_t GetCachedHash(const StringPtr obj) {
10446 return Smi::Value(obj->untag()->hash_);
10447 }
10448
10449 static uint32_t SetCachedHashIfNotSet(StringPtr obj, uint32_t hash) {
10450 ASSERT(Smi::Value(obj->untag()->hash_) == 0 ||
10451 Smi::Value(obj->untag()->hash_) == static_cast<intptr_t>(hash));
10452 return SetCachedHash(obj, hash);
10453 }
10454 static uint32_t SetCachedHash(StringPtr obj, uint32_t hash) {
10455 obj->untag()->hash_ = Smi::New(hash);
10456 return hash;
10457 }
10458#else
10459 static uint32_t SetCachedHash(StringPtr obj, uint32_t hash) {
10460 return Object::SetCachedHashIfNotSet(obj, hash);
10461 }
10462#endif
10463
10464 protected:
10465 // These two operate on an array of Latin-1 encoded characters.
10466 // They are protected to avoid mistaking Latin-1 for UTF-8, but used
10467 // by friendly templated code (e.g., Symbols).
10468 bool Equals(const uint8_t* characters, intptr_t len) const;
10469 static uword Hash(const uint8_t* characters, intptr_t len);
10470
10471 void SetLength(intptr_t value) const {
10472 // This is only safe because we create a new Smi, which does not cause
10473 // heap allocation.
10474 untag()->set_length(Smi::New(value));
10475 }
10476
10477 void SetHash(intptr_t value) const {
10478 const intptr_t hash_set = SetCachedHashIfNotSet(ptr(), value);
10479 ASSERT(hash_set == value);
10480 }
10481
10483
10484 friend class Class;
10485 friend class Symbols;
10486 friend class StringSlice; // SetHash
10487 template <typename CharType>
10488 friend class CharArray; // SetHash
10489 friend class ConcatString; // SetHash
10490 friend class OneByteString;
10491 friend class TwoByteString;
10493 friend class RODataSerializationCluster; // SetHash
10494 friend class Pass2Visitor; // Stack "handle"
10495};
10496
10497// Synchronize with implementation in compiler (intrinsifier).
10499 public:
10500 StringHasher() : hash_(0) {}
10501 void Add(uint16_t code_unit) { hash_ = CombineHashes(hash_, code_unit); }
10502 void Add(const uint8_t* code_units, intptr_t len) {
10503 while (len > 0) {
10504 Add(*code_units);
10505 code_units++;
10506 len--;
10507 }
10508 }
10509 void Add(const uint16_t* code_units, intptr_t len) {
10510 while (len > 0) {
10511 Add(LoadUnaligned(code_units));
10512 code_units++;
10513 len--;
10514 }
10515 }
10516 void Add(const String& str, intptr_t begin_index, intptr_t len);
10517 intptr_t Finalize() { return FinalizeHash(hash_, String::kHashBits); }
10518
10519 private:
10520 uint32_t hash_;
10521};
10522
10523class OneByteString : public AllStatic {
10524 public:
10525 static uint16_t CharAt(const String& str, intptr_t index) {
10526 ASSERT(str.IsOneByteString());
10527 return OneByteString::CharAt(static_cast<OneByteStringPtr>(str.ptr()),
10528 index);
10529 }
10530
10531 static uint16_t CharAt(OneByteStringPtr str, intptr_t index) {
10532 ASSERT(index >= 0 && index < String::LengthOf(str));
10533 return str->untag()->data()[index];
10534 }
10535
10536 static void SetCharAt(const String& str, intptr_t index, uint8_t code_unit) {
10537 NoSafepointScope no_safepoint;
10538 *CharAddr(str, index) = code_unit;
10539 }
10540 static OneByteStringPtr EscapeSpecialCharacters(const String& str);
10541 // We use the same maximum elements for all strings.
10542 static constexpr intptr_t kBytesPerElement = 1;
10543 static constexpr intptr_t kMaxElements = String::kMaxElements;
10544 static constexpr intptr_t kMaxNewSpaceElements =
10545 (kNewAllocatableSize - sizeof(UntaggedOneByteString)) / kBytesPerElement;
10546
10548 static intptr_t elements_start_offset() {
10549 return sizeof(UntaggedOneByteString);
10550 }
10551 static constexpr intptr_t kElementSize = kBytesPerElement;
10552 };
10553
10554 static intptr_t data_offset() {
10556 }
10557
10558 static intptr_t UnroundedSize(OneByteStringPtr str) {
10559 return UnroundedSize(Smi::Value(str->untag()->length()));
10560 }
10561 static intptr_t UnroundedSize(intptr_t len) {
10562 return sizeof(UntaggedOneByteString) + (len * kBytesPerElement);
10563 }
10564 static intptr_t InstanceSize() {
10565 ASSERT(sizeof(UntaggedOneByteString) ==
10567 return 0;
10568 }
10569 static intptr_t InstanceSize(intptr_t len) {
10571 ASSERT(0 <= len && len <= kMaxElements);
10572 return String::RoundedAllocationSize(UnroundedSize(len));
10573 }
10574
10575 static OneByteStringPtr New(intptr_t len, Heap::Space space);
10576 static OneByteStringPtr New(const char* c_string,
10577 Heap::Space space = Heap::kNew) {
10578 return New(reinterpret_cast<const uint8_t*>(c_string), strlen(c_string),
10579 space);
10580 }
10581 static OneByteStringPtr New(const uint8_t* characters,
10582 intptr_t len,
10583 Heap::Space space);
10584 static OneByteStringPtr New(const uint16_t* characters,
10585 intptr_t len,
10586 Heap::Space space);
10587 static OneByteStringPtr New(const int32_t* characters,
10588 intptr_t len,
10589 Heap::Space space);
10590 static OneByteStringPtr New(const String& str, Heap::Space space);
10591 // 'other' must be OneByteString.
10592 static OneByteStringPtr New(const String& other_one_byte_string,
10593 intptr_t other_start_index,
10594 intptr_t other_len,
10595 Heap::Space space);
10596
10597 static OneByteStringPtr New(const TypedDataBase& other_typed_data,
10598 intptr_t other_start_index,
10599 intptr_t other_len,
10600 Heap::Space space = Heap::kNew);
10601
10602 static OneByteStringPtr Concat(const String& str1,
10603 const String& str2,
10604 Heap::Space space);
10605 static OneByteStringPtr ConcatAll(const Array& strings,
10606 intptr_t start,
10607 intptr_t end,
10608 intptr_t len,
10609 Heap::Space space);
10610
10611 static OneByteStringPtr Transform(int32_t (*mapping)(int32_t ch),
10612 const String& str,
10613 Heap::Space space);
10614
10615 // High performance version of substring for one-byte strings.
10616 // "str" must be OneByteString.
10617 static OneByteStringPtr SubStringUnchecked(const String& str,
10618 intptr_t begin_index,
10619 intptr_t length,
10620 Heap::Space space);
10621
10622 static const ClassId kClassId = kOneByteStringCid;
10623
10624 static OneByteStringPtr null() {
10625 return static_cast<OneByteStringPtr>(Object::null());
10626 }
10627
10628 private:
10629 static OneByteStringPtr raw(const String& str) {
10630 return static_cast<OneByteStringPtr>(str.ptr());
10631 }
10632
10633 static const UntaggedOneByteString* untag(const String& str) {
10634 return reinterpret_cast<const UntaggedOneByteString*>(str.untag());
10635 }
10636
10637 static uint8_t* CharAddr(const String& str, intptr_t index) {
10638 ASSERT((index >= 0) && (index < str.Length()));
10639 ASSERT(str.IsOneByteString());
10640 return &str.UnsafeMutableNonPointer(untag(str)->data())[index];
10641 }
10642
10643 static uint8_t* DataStart(const String& str) {
10644 ASSERT(str.IsOneByteString());
10645 return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
10646 }
10647
10649
10650 friend class Class;
10652 friend class ImageWriter;
10653 friend class String;
10654 friend class StringHasher;
10655 friend class Symbols;
10656 friend class Utf8;
10658 friend class Deserializer;
10659 friend class JSONWriter;
10660};
10661
10662class TwoByteString : public AllStatic {
10663 public:
10664 static uint16_t CharAt(const String& str, intptr_t index) {
10665 ASSERT(str.IsTwoByteString());
10666 return TwoByteString::CharAt(static_cast<TwoByteStringPtr>(str.ptr()),
10667 index);
10668 }
10669
10670 static uint16_t CharAt(TwoByteStringPtr str, intptr_t index) {
10671 ASSERT(index >= 0 && index < String::LengthOf(str));
10672 return str->untag()->data()[index];
10673 }
10674
10675 static void SetCharAt(const String& str, intptr_t index, uint16_t ch) {
10676 NoSafepointScope no_safepoint;
10677 *CharAddr(str, index) = ch;
10678 }
10679
10680 static TwoByteStringPtr EscapeSpecialCharacters(const String& str);
10681
10682 // We use the same maximum elements for all strings.
10683 static constexpr intptr_t kBytesPerElement = 2;
10684 static constexpr intptr_t kMaxElements = String::kMaxElements;
10685 static constexpr intptr_t kMaxNewSpaceElements =
10686 (kNewAllocatableSize - sizeof(UntaggedTwoByteString)) / kBytesPerElement;
10687
10689 static intptr_t elements_start_offset() {
10690 return sizeof(UntaggedTwoByteString);
10691 }
10692 static constexpr intptr_t kElementSize = kBytesPerElement;
10693 };
10694
10695 static intptr_t data_offset() {
10697 }
10698 static intptr_t UnroundedSize(TwoByteStringPtr str) {
10699 return UnroundedSize(Smi::Value(str->untag()->length()));
10700 }
10701 static intptr_t UnroundedSize(intptr_t len) {
10702 return sizeof(UntaggedTwoByteString) + (len * kBytesPerElement);
10703 }
10704 static intptr_t InstanceSize() {
10705 ASSERT(sizeof(UntaggedTwoByteString) ==
10707 return 0;
10708 }
10709 static intptr_t InstanceSize(intptr_t len) {
10711 ASSERT(0 <= len && len <= kMaxElements);
10712 return String::RoundedAllocationSize(UnroundedSize(len));
10713 }
10714
10715 static TwoByteStringPtr New(intptr_t len, Heap::Space space);
10716 static TwoByteStringPtr New(const uint16_t* characters,
10717 intptr_t len,
10718 Heap::Space space);
10719 static TwoByteStringPtr New(intptr_t utf16_len,
10720 const int32_t* characters,
10721 intptr_t len,
10722 Heap::Space space);
10723 static TwoByteStringPtr New(const String& str, Heap::Space space);
10724
10725 static TwoByteStringPtr New(const TypedDataBase& other_typed_data,
10726 intptr_t other_start_index,
10727 intptr_t other_len,
10728 Heap::Space space = Heap::kNew);
10729
10730 static TwoByteStringPtr Concat(const String& str1,
10731 const String& str2,
10732 Heap::Space space);
10733 static TwoByteStringPtr ConcatAll(const Array& strings,
10734 intptr_t start,
10735 intptr_t end,
10736 intptr_t len,
10737 Heap::Space space);
10738
10739 static TwoByteStringPtr Transform(int32_t (*mapping)(int32_t ch),
10740 const String& str,
10741 Heap::Space space);
10742
10743 static TwoByteStringPtr null() {
10744 return static_cast<TwoByteStringPtr>(Object::null());
10745 }
10746
10747 static const ClassId kClassId = kTwoByteStringCid;
10748
10749 private:
10750 static TwoByteStringPtr raw(const String& str) {
10751 return static_cast<TwoByteStringPtr>(str.ptr());
10752 }
10753
10754 static const UntaggedTwoByteString* untag(const String& str) {
10755 return reinterpret_cast<const UntaggedTwoByteString*>(str.untag());
10756 }
10757
10758 static uint16_t* CharAddr(const String& str, intptr_t index) {
10759 ASSERT((index >= 0) && (index < str.Length()));
10760 ASSERT(str.IsTwoByteString());
10761 return &str.UnsafeMutableNonPointer(untag(str)->data())[index];
10762 }
10763
10764 // Use this instead of CharAddr(0). It will not assert that the index is <
10765 // length.
10766 static uint16_t* DataStart(const String& str) {
10767 ASSERT(str.IsTwoByteString());
10768 return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
10769 }
10770
10772
10773 friend class Class;
10775 friend class ImageWriter;
10776 friend class String;
10777 friend class StringHasher;
10778 friend class Symbols;
10780 friend class JSONWriter;
10781};
10782
10783// Matches null_patch.dart / bool_patch.dart.
10784static constexpr intptr_t kNullIdentityHash = 2011;
10785static constexpr intptr_t kTrueIdentityHash = 1231;
10786static constexpr intptr_t kFalseIdentityHash = 1237;
10787
10788// Class Bool implements Dart core class bool.
10789class Bool : public Instance {
10790 public:
10791 bool value() const { return untag()->value_; }
10792
10793 static intptr_t InstanceSize() {
10794 return RoundedAllocationSize(sizeof(UntaggedBool));
10795 }
10796
10797 static const Bool& True() { return Object::bool_true(); }
10798
10799 static const Bool& False() { return Object::bool_false(); }
10800
10801 static const Bool& Get(bool value) {
10802 return value ? Bool::True() : Bool::False();
10803 }
10804
10805 virtual uint32_t CanonicalizeHash() const {
10806 return ptr() == True().ptr() ? kTrueIdentityHash : kFalseIdentityHash;
10807 }
10808
10809 private:
10811 friend class Class;
10812 friend class Object; // To initialize the true and false values.
10813};
10814
10815class Array : public Instance {
10816 public:
10817 // Returns `true` if we use card marking for arrays of length [array_length].
10818 static constexpr bool UseCardMarkingForAllocation(
10819 const intptr_t array_length) {
10820 return Array::InstanceSize(array_length) > kNewAllocatableSize;
10821 }
10822
10823 // WB invariant restoration code only applies to arrives which have at most
10824 // this many elements. Consequently WB elimination code should not eliminate
10825 // WB on arrays of larger lengths across instructions that can cause GC.
10826 // Note: we also can't restore WB invariant for arrays which use card marking.
10827 static constexpr intptr_t kMaxLengthForWriteBarrierElimination = 8;
10828
10829 intptr_t Length() const { return LengthOf(ptr()); }
10830 static intptr_t LengthOf(const ArrayPtr array) {
10831 return Smi::Value(array->untag()->length());
10832 }
10833
10834 static intptr_t length_offset() { return OFFSET_OF(UntaggedArray, length_); }
10835 static intptr_t data_offset() {
10837 }
10838 static intptr_t element_offset(intptr_t index) {
10840 kBytesPerElement * index;
10841 }
10842 static intptr_t index_at_offset(intptr_t offset_in_bytes) {
10843 intptr_t index = (offset_in_bytes - data_offset()) / kBytesPerElement;
10844 ASSERT(index >= 0);
10845 return index;
10846 }
10847
10849 static intptr_t elements_start_offset() { return Array::data_offset(); }
10850
10851 static constexpr intptr_t kElementSize = kCompressedWordSize;
10852 };
10853
10854 static bool Equals(ArrayPtr a, ArrayPtr b) {
10855 if (a == b) return true;
10856 if (a->IsRawNull() || b->IsRawNull()) return false;
10857 if (a->untag()->length() != b->untag()->length()) return false;
10858 if (a->untag()->type_arguments() != b->untag()->type_arguments()) {
10859 return false;
10860 }
10861 const intptr_t length = LengthOf(a);
10862 return memcmp(a->untag()->data(), b->untag()->data(),
10863 kBytesPerElement * length) == 0;
10864 }
10865 bool Equals(const Array& other) const {
10866 NoSafepointScope scope;
10867 return Equals(ptr(), other.ptr());
10868 }
10869
10870 static CompressedObjectPtr* DataOf(ArrayPtr array) {
10871 return array->untag()->data();
10872 }
10873
10874 template <std::memory_order order = std::memory_order_relaxed>
10875 ObjectPtr At(intptr_t index) const {
10876 ASSERT((0 <= index) && (index < Length()));
10877 return untag()->element<order>(index);
10878 }
10879 template <std::memory_order order = std::memory_order_relaxed>
10880 void SetAt(intptr_t index, const Object& value) const {
10881 ASSERT((0 <= index) && (index < Length()));
10882 untag()->set_element<order>(index, value.ptr());
10883 }
10884 template <std::memory_order order = std::memory_order_relaxed>
10885 void SetAt(intptr_t index, const Object& value, Thread* thread) const {
10886 ASSERT((0 <= index) && (index < Length()));
10887 untag()->set_element<order>(index, value.ptr(), thread);
10888 }
10889
10890 // Access to the array with acquire release semantics.
10891 ObjectPtr AtAcquire(intptr_t index) const {
10892 ASSERT((0 <= index) && (index < Length()));
10893 return untag()->element<std::memory_order_acquire>(index);
10894 }
10895 void SetAtRelease(intptr_t index, const Object& value) const {
10896 ASSERT((0 <= index) && (index < Length()));
10897 untag()->set_element<std::memory_order_release>(index, value.ptr());
10898 }
10899
10900 bool IsImmutable() const { return ptr()->GetClassId() == kImmutableArrayCid; }
10901
10902 // Position of element type in type arguments.
10903 static constexpr intptr_t kElementTypeTypeArgPos = 0;
10904
10905 virtual TypeArgumentsPtr GetTypeArguments() const {
10906 return untag()->type_arguments();
10907 }
10908 virtual void SetTypeArguments(const TypeArguments& value) const {
10909 // An Array is raw or takes one type argument. However, its type argument
10910 // vector may be longer than 1 due to a type optimization reusing the type
10911 // argument vector of the instantiator.
10912 ASSERT(value.IsNull() ||
10913 ((value.Length() >= 1) &&
10914 value.IsInstantiated() /*&& value.IsCanonical()*/));
10915 // TODO(asiva): Values read from a message snapshot are not properly marked
10916 // as canonical. See for example tests/isolate/mandel_isolate_test.dart.
10917 StoreArrayPointer(&untag()->type_arguments_, value.ptr());
10918 }
10919
10920 virtual bool CanonicalizeEquals(const Instance& other) const;
10921 virtual uint32_t CanonicalizeHash() const;
10922
10923 static constexpr intptr_t kBytesPerElement = ArrayTraits::kElementSize;
10924 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
10925 static constexpr intptr_t kMaxNewSpaceElements =
10926 (kNewAllocatableSize - sizeof(UntaggedArray)) / kBytesPerElement;
10927
10928 static intptr_t type_arguments_offset() {
10929 return OFFSET_OF(UntaggedArray, type_arguments_);
10930 }
10931
10932 static constexpr bool IsValidLength(intptr_t len) {
10933 return 0 <= len && len <= kMaxElements;
10934 }
10935
10936 static intptr_t InstanceSize() {
10937 ASSERT(sizeof(UntaggedArray) ==
10939 return 0;
10940 }
10941
10942 static constexpr intptr_t UnroundedSize(intptr_t len) {
10943 // Ensure that variable length data is not adding to the object length.
10944 ASSERT(sizeof(UntaggedArray) ==
10945 (sizeof(UntaggedInstance) + (2 * kBytesPerElement)));
10946 ASSERT(IsValidLength(len));
10947 return sizeof(UntaggedArray) + (len * kBytesPerElement);
10948 }
10949 static constexpr intptr_t InstanceSize(intptr_t len) {
10950 return RoundedAllocationSize(UnroundedSize(len));
10951 }
10952
10953 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
10954
10955 // Make the array immutable to Dart code by switching the class pointer
10956 // to ImmutableArray.
10957 void MakeImmutable() const;
10958
10959 static ArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew) {
10960 return New(kArrayCid, len, space);
10961 }
10962 // The result's type arguments and elements are GC-safe but not initialized to
10963 // null.
10964 static ArrayPtr NewUninitialized(intptr_t len,
10965 Heap::Space space = Heap::kNew) {
10966 return NewUninitialized(kArrayCid, len, space);
10967 }
10968 static ArrayPtr New(intptr_t len,
10969 const AbstractType& element_type,
10970 Heap::Space space = Heap::kNew);
10971
10972 // Creates and returns a new array with 'new_length'. Copies all elements from
10973 // 'source' to the new array. 'new_length' must be greater than or equal to
10974 // 'source.Length()'. 'source' can be null.
10975 static ArrayPtr Grow(const Array& source,
10976 intptr_t new_length,
10977 Heap::Space space = Heap::kNew);
10978
10979 // Truncates the array to a given length. 'new_length' must be less than
10980 // or equal to 'source.Length()'. The remaining unused part of the array is
10981 // marked as an Array object or a regular Object so that it can be traversed
10982 // during garbage collection.
10983 void Truncate(intptr_t new_length) const;
10984
10985 // Return an Array object that contains all the elements currently present
10986 // in the specified Growable Object Array. This is done by first truncating
10987 // the Growable Object Array's backing array to the currently used size and
10988 // returning the truncated backing array.
10989 // The backing array of the original Growable Object Array is
10990 // set to an empty array.
10991 // If the unique parameter is false, the function is allowed to return
10992 // a shared Array instance.
10993 static ArrayPtr MakeFixedLength(const GrowableObjectArray& growable_array,
10994 bool unique = false);
10995
10996 ArrayPtr Slice(intptr_t start, intptr_t count, bool with_type_argument) const;
10997 ArrayPtr Copy() const {
10998 return Slice(0, Length(), /*with_type_argument=*/true);
10999 }
11000
11001 protected:
11002 static ArrayPtr New(intptr_t class_id,
11003 intptr_t len,
11004 Heap::Space space = Heap::kNew);
11005 static ArrayPtr NewUninitialized(intptr_t class_id,
11006 intptr_t len,
11007 Heap::Space space = Heap::kNew);
11008
11009 private:
11010 CompressedObjectPtr const* ObjectAddr(intptr_t index) const {
11011 // TODO(iposva): Determine if we should throw an exception here.
11012 ASSERT((index >= 0) && (index < Length()));
11013 return &untag()->data()[index];
11014 }
11015
11016 void SetLength(intptr_t value) const { untag()->set_length(Smi::New(value)); }
11017 void SetLengthRelease(intptr_t value) const {
11018 untag()->set_length<std::memory_order_release>(Smi::New(value));
11019 }
11020
11021 template <typename type,
11022 std::memory_order order = std::memory_order_relaxed,
11023 typename value_type>
11024 void StoreArrayPointer(type const* addr, value_type value) const {
11025 ptr()->untag()->StoreArrayPointer<type, order, value_type>(addr, value);
11026 }
11027
11028 FINAL_HEAP_OBJECT_IMPLEMENTATION(Array, Instance);
11029 friend class Class;
11030 friend class ImmutableArray;
11031 friend class Object;
11032 friend class String;
11034};
11035
11037 public:
11038 static constexpr bool ContainsCompressedPointers() {
11040 }
11041
11042 static ImmutableArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);
11043
11044 static const ClassId kClassId = kImmutableArrayCid;
11045
11046 static intptr_t InstanceSize() { return Array::InstanceSize(); }
11047
11048 static intptr_t InstanceSize(intptr_t len) {
11049 return Array::InstanceSize(len);
11050 }
11051
11052 private:
11053 static intptr_t NextFieldOffset() {
11054 // Indicates this class cannot be extended by dart code.
11055 return -kWordSize;
11056 }
11057
11058 static ImmutableArrayPtr raw(const Array& array) {
11059 return static_cast<ImmutableArrayPtr>(array.ptr());
11060 }
11061
11062 friend class Class;
11063};
11064
11066 public:
11067 intptr_t Capacity() const {
11068 NoSafepointScope no_safepoint;
11069 ASSERT(!IsNull());
11070 return Smi::Value(DataArray()->length());
11071 }
11072 intptr_t Length() const {
11073 ASSERT(!IsNull());
11074 return Smi::Value(untag()->length());
11075 }
11076 void SetLength(intptr_t value) const {
11077 // This is only safe because we create a new Smi, which does not cause
11078 // heap allocation.
11079 untag()->set_length(Smi::New(value));
11080 }
11081
11082 ArrayPtr data() const { return untag()->data(); }
11083 void SetData(const Array& value) const { untag()->set_data(value.ptr()); }
11084
11085 ObjectPtr At(intptr_t index) const {
11086 NoSafepointScope no_safepoint;
11087 ASSERT(!IsNull());
11088 ASSERT(index < Length());
11089 return data()->untag()->element(index);
11090 }
11091 void SetAt(intptr_t index, const Object& value) const {
11092 ASSERT(!IsNull());
11093 ASSERT(index < Length());
11094
11095 // TODO(iposva): Add storing NoSafepointScope.
11096 data()->untag()->set_element(index, value.ptr());
11097 }
11098
11099 void Add(const Object& value, Heap::Space space = Heap::kNew) const;
11100
11101 void Grow(intptr_t new_capacity, Heap::Space space = Heap::kNew) const;
11102 ObjectPtr RemoveLast() const;
11103
11104 virtual TypeArgumentsPtr GetTypeArguments() const {
11105 return untag()->type_arguments();
11106 }
11107 virtual void SetTypeArguments(const TypeArguments& value) const {
11108 // A GrowableObjectArray is raw or takes one type argument. However, its
11109 // type argument vector may be longer than 1 due to a type optimization
11110 // reusing the type argument vector of the instantiator.
11111 ASSERT(value.IsNull() || ((value.Length() >= 1) && value.IsInstantiated() &&
11112 value.IsCanonical()));
11113
11114 untag()->set_type_arguments(value.ptr());
11115 }
11116
11117 // We don't expect a growable object array to be canonicalized.
11118 virtual bool CanonicalizeEquals(const Instance& other) const {
11119 UNREACHABLE();
11120 return false;
11121 }
11122
11123 // We don't expect a growable object array to be canonicalized.
11124 virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
11125 UNREACHABLE();
11126 return Instance::null();
11127 }
11128
11129 static intptr_t type_arguments_offset() {
11130 return OFFSET_OF(UntaggedGrowableObjectArray, type_arguments_);
11131 }
11132
11133 static intptr_t length_offset() {
11134 return OFFSET_OF(UntaggedGrowableObjectArray, length_);
11135 }
11136 static intptr_t data_offset() {
11138 }
11139
11140 static intptr_t InstanceSize() {
11142 }
11143
11144 static GrowableObjectArrayPtr New(Heap::Space space = Heap::kNew) {
11145 return New(kDefaultInitialCapacity, space);
11146 }
11147 static GrowableObjectArrayPtr New(intptr_t capacity,
11148 Heap::Space space = Heap::kNew);
11149 static GrowableObjectArrayPtr New(const Array& array,
11150 Heap::Space space = Heap::kNew);
11151
11152 static SmiPtr NoSafepointLength(const GrowableObjectArrayPtr array) {
11153 return array->untag()->length();
11154 }
11155
11156 static ArrayPtr NoSafepointData(const GrowableObjectArrayPtr array) {
11157 return array->untag()->data();
11158 }
11159
11160 private:
11161 UntaggedArray* DataArray() const { return data()->untag(); }
11162
11163 static constexpr int kDefaultInitialCapacity = 0;
11164
11165 FINAL_HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray, Instance);
11166 friend class Array;
11167 friend class Class;
11168};
11169
11170class Float32x4 : public Instance {
11171 public:
11172 static Float32x4Ptr New(float value0,
11173 float value1,
11174 float value2,
11175 float value3,
11176 Heap::Space space = Heap::kNew);
11177 static Float32x4Ptr New(simd128_value_t value,
11178 Heap::Space space = Heap::kNew);
11179
11180 float x() const;
11181 float y() const;
11182 float z() const;
11183 float w() const;
11184
11185 void set_x(float x) const;
11186 void set_y(float y) const;
11187 void set_z(float z) const;
11188 void set_w(float w) const;
11189
11190 simd128_value_t value() const;
11191 void set_value(simd128_value_t value) const;
11192
11193 static intptr_t InstanceSize() {
11195 }
11196
11197 static intptr_t value_offset() {
11198 return OFFSET_OF(UntaggedFloat32x4, value_);
11199 }
11200
11201 virtual bool CanonicalizeEquals(const Instance& other) const;
11202 virtual uint32_t CanonicalizeHash() const;
11203
11204 private:
11206 friend class Class;
11207};
11208
11209class Int32x4 : public Instance {
11210 public:
11211 static Int32x4Ptr New(int32_t value0,
11212 int32_t value1,
11213 int32_t value2,
11214 int32_t value3,
11215 Heap::Space space = Heap::kNew);
11216 static Int32x4Ptr New(simd128_value_t value, Heap::Space space = Heap::kNew);
11217
11218 int32_t x() const;
11219 int32_t y() const;
11220 int32_t z() const;
11221 int32_t w() const;
11222
11223 void set_x(int32_t x) const;
11224 void set_y(int32_t y) const;
11225 void set_z(int32_t z) const;
11226 void set_w(int32_t w) const;
11227
11228 simd128_value_t value() const;
11229 void set_value(simd128_value_t value) const;
11230
11231 static intptr_t InstanceSize() {
11232 return RoundedAllocationSize(sizeof(UntaggedInt32x4));
11233 }
11234
11235 static intptr_t value_offset() { return OFFSET_OF(UntaggedInt32x4, value_); }
11236
11237 virtual bool CanonicalizeEquals(const Instance& other) const;
11238 virtual uint32_t CanonicalizeHash() const;
11239
11240 private:
11242 friend class Class;
11243};
11244
11245class Float64x2 : public Instance {
11246 public:
11247 static Float64x2Ptr New(double value0,
11248 double value1,
11249 Heap::Space space = Heap::kNew);
11250 static Float64x2Ptr New(simd128_value_t value,
11251 Heap::Space space = Heap::kNew);
11252
11253 double x() const;
11254 double y() const;
11255
11256 void set_x(double x) const;
11257 void set_y(double y) const;
11258
11259 simd128_value_t value() const;
11260 void set_value(simd128_value_t value) const;
11261
11262 static intptr_t InstanceSize() {
11264 }
11265
11266 static intptr_t value_offset() {
11267 return OFFSET_OF(UntaggedFloat64x2, value_);
11268 }
11269
11270 virtual bool CanonicalizeEquals(const Instance& other) const;
11271 virtual uint32_t CanonicalizeHash() const;
11272
11273 private:
11275 friend class Class;
11276};
11277
11278// Packed representation of record shape (number of fields and field names).
11280 enum {
11281 kNumFieldsBits = 16,
11282 kFieldNamesIndexBits = kSmiBits - kNumFieldsBits,
11283 };
11285 using FieldNamesIndexBitField = BitField<intptr_t,
11286 intptr_t,
11287 NumFieldsBitField::kNextBit,
11288 kFieldNamesIndexBits>;
11289
11290 public:
11291 static constexpr intptr_t kNumFieldsMask = NumFieldsBitField::mask();
11292 static constexpr intptr_t kMaxNumFields = kNumFieldsMask;
11293 static constexpr intptr_t kFieldNamesIndexMask =
11294 FieldNamesIndexBitField::mask();
11295 static constexpr intptr_t kFieldNamesIndexShift =
11296 FieldNamesIndexBitField::shift();
11297 static constexpr intptr_t kMaxFieldNamesIndex = kFieldNamesIndexMask;
11298
11299 explicit RecordShape(intptr_t value) : value_(value) { ASSERT(value_ >= 0); }
11300 explicit RecordShape(SmiPtr smi_value) : value_(Smi::Value(smi_value)) {
11301 ASSERT(value_ >= 0);
11302 }
11303 RecordShape(intptr_t num_fields, intptr_t field_names_index)
11304 : value_(NumFieldsBitField::encode(num_fields) |
11305 FieldNamesIndexBitField::encode(field_names_index)) {
11306 ASSERT(value_ >= 0);
11307 }
11308 static RecordShape ForUnnamed(intptr_t num_fields) {
11309 return RecordShape(num_fields, 0);
11310 }
11311
11312 bool HasNamedFields() const { return field_names_index() != 0; }
11313
11314 intptr_t num_fields() const { return NumFieldsBitField::decode(value_); }
11315
11316 intptr_t field_names_index() const {
11317 return FieldNamesIndexBitField::decode(value_);
11318 }
11319
11320 SmiPtr AsSmi() const { return Smi::New(value_); }
11321
11322 intptr_t AsInt() const { return value_; }
11323
11324 bool operator==(const RecordShape& other) const {
11325 return value_ == other.value_;
11326 }
11327 bool operator!=(const RecordShape& other) const {
11328 return value_ != other.value_;
11329 }
11330
11331 // Registers record shape with [num_fields] and [field_names] in the current
11332 // isolate group.
11333 static RecordShape Register(Thread* thread,
11334 intptr_t num_fields,
11335 const Array& field_names);
11336
11337 // Retrieves an array of field names.
11338 ArrayPtr GetFieldNames(Thread* thread) const;
11339
11340 private:
11341 intptr_t value_;
11342
11344};
11345
11346// A RecordType represents the type of a record. It describes
11347// number of named and positional fields, field types and
11348// names of the named fields.
11349class RecordType : public AbstractType {
11350 public:
11351 virtual bool HasTypeClass() const { return false; }
11352 RecordTypePtr ToNullability(Nullability value, Heap::Space space) const;
11353 virtual classid_t type_class_id() const { return kIllegalCid; }
11354 virtual bool IsInstantiated(
11355 Genericity genericity = kAny,
11356 intptr_t num_free_fun_type_params = kAllFree) const;
11357 virtual bool IsEquivalent(
11358 const Instance& other,
11359 TypeEquality kind,
11360 FunctionTypeMapping* function_type_equivalence = nullptr) const;
11361
11362 virtual AbstractTypePtr InstantiateFrom(
11363 const TypeArguments& instantiator_type_arguments,
11364 const TypeArguments& function_type_arguments,
11365 intptr_t num_free_fun_type_params,
11366 Heap::Space space,
11367 FunctionTypeMapping* function_type_mapping = nullptr,
11368 intptr_t num_parent_type_args_adjustment = 0) const;
11369
11370 virtual AbstractTypePtr UpdateFunctionTypes(
11371 intptr_t num_parent_type_args_adjustment,
11372 intptr_t num_free_fun_type_params,
11373 Heap::Space space,
11374 FunctionTypeMapping* function_type_mapping) const;
11375
11376 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
11377 virtual void EnumerateURIs(URIs* uris) const;
11378 virtual void PrintName(NameVisibility visibility,
11379 BaseTextBuffer* printer) const;
11380
11381 virtual uword ComputeHash() const;
11382
11383 bool IsSubtypeOf(
11384 const RecordType& other,
11385 Heap::Space space,
11386 FunctionTypeMapping* function_type_equivalence = nullptr) const;
11387
11388 RecordShape shape() const { return RecordShape(untag()->shape()); }
11389
11390 ArrayPtr field_types() const { return untag()->field_types(); }
11391
11392 AbstractTypePtr FieldTypeAt(intptr_t index) const;
11393 void SetFieldTypeAt(intptr_t index, const AbstractType& value) const;
11394
11395 // Names of the named fields, sorted.
11396 ArrayPtr GetFieldNames(Thread* thread) const;
11397
11398 intptr_t NumFields() const;
11399
11400 void Print(NameVisibility name_visibility, BaseTextBuffer* printer) const;
11401
11402 static intptr_t InstanceSize() {
11404 }
11405
11406 static RecordTypePtr New(RecordShape shape,
11407 const Array& field_types,
11409 Heap::Space space = Heap::kOld);
11410
11411 private:
11412 void set_shape(RecordShape shape) const;
11413 void set_field_types(const Array& value) const;
11414
11415 static RecordTypePtr New(Heap::Space space);
11416
11418 friend class Class;
11419 friend class ClassFinalizer;
11420 friend class Record;
11421};
11422
11423class Record : public Instance {
11424 public:
11425 intptr_t num_fields() const { return NumFields(ptr()); }
11426 static intptr_t NumFields(RecordPtr ptr) {
11427 return RecordShape(ptr->untag()->shape()).num_fields();
11428 }
11429
11430 RecordShape shape() const { return RecordShape(untag()->shape()); }
11431 static intptr_t shape_offset() { return OFFSET_OF(UntaggedRecord, shape_); }
11432
11433 ObjectPtr FieldAt(intptr_t field_index) const {
11434 return untag()->field(field_index);
11435 }
11436 void SetFieldAt(intptr_t field_index, const Object& value) const {
11437 untag()->set_field(field_index, value.ptr());
11438 }
11439
11440 static constexpr intptr_t kBytesPerElement = kCompressedWordSize;
11441 static constexpr intptr_t kMaxElements = RecordShape::kMaxNumFields;
11442
11444 static intptr_t elements_start_offset() { return sizeof(UntaggedRecord); }
11445 static constexpr intptr_t kElementSize = kBytesPerElement;
11446 };
11447
11448 static intptr_t field_offset(intptr_t index) {
11450 kBytesPerElement * index;
11451 }
11452 static intptr_t field_index_at_offset(intptr_t offset_in_bytes) {
11453 const intptr_t index =
11454 (offset_in_bytes - OFFSET_OF_RETURNED_VALUE(UntaggedRecord, data)) /
11455 kBytesPerElement;
11456 ASSERT(index >= 0);
11457 return index;
11458 }
11459
11460 static intptr_t InstanceSize() {
11461 ASSERT(sizeof(UntaggedRecord) ==
11463 return 0;
11464 }
11465
11466 static intptr_t InstanceSize(intptr_t num_fields) {
11467 return RoundedAllocationSize(sizeof(UntaggedRecord) +
11468 (num_fields * kBytesPerElement));
11469 }
11470
11471 static RecordPtr New(RecordShape shape, Heap::Space space = Heap::kNew);
11472
11473 virtual bool CanonicalizeEquals(const Instance& other) const;
11474 virtual uint32_t CanonicalizeHash() const;
11475 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
11476
11477 // Returns RecordType representing runtime type of this record instance.
11478 // It is not created eagerly when record instance is allocated because
11479 // it depends on runtime types of values if its fields, which can be
11480 // quite expensive to query.
11481 RecordTypePtr GetRecordType() const;
11482
11483 // Parses positional field name and return its index,
11484 // or -1 if [field_name] is not a valid positional field name.
11485 static intptr_t GetPositionalFieldIndexFromFieldName(
11486 const String& field_name);
11487
11488 // Returns index of the field with given name, or -1
11489 // if such field doesn't exist.
11490 // Supports positional field names ("$1", "$2", etc).
11491 intptr_t GetFieldIndexByName(Thread* thread, const String& field_name) const;
11492
11493 ArrayPtr GetFieldNames(Thread* thread) const {
11494 return shape().GetFieldNames(thread);
11495 }
11496
11497 private:
11499 friend class Class;
11500 friend class Object;
11501};
11502
11503class PointerBase : public Instance {
11504 public:
11505 static intptr_t data_offset() {
11506 return OFFSET_OF(UntaggedPointerBase, data_);
11507 }
11508};
11509
11511 public:
11512 static intptr_t length_offset() {
11513 return OFFSET_OF(UntaggedTypedDataBase, length_);
11514 }
11515
11516 SmiPtr length() const { return untag()->length(); }
11517
11518 intptr_t Length() const {
11519 ASSERT(!IsNull());
11520 return Smi::Value(untag()->length());
11521 }
11522
11523 intptr_t LengthInBytes() const {
11524 return ElementSizeInBytes(ptr()->GetClassId()) * Length();
11525 }
11526
11528 return ElementType(ptr()->GetClassId());
11529 }
11530
11531 intptr_t ElementSizeInBytes() const {
11532 return element_size(ElementType(ptr()->GetClassId()));
11533 }
11534
11536 return element_size(ElementType(cid));
11537 }
11538
11541 return kUint8ArrayElement;
11542 } else if (IsTypedDataClassId(cid)) {
11543 const intptr_t index =
11546 return static_cast<TypedDataElementType>(index);
11547 } else if (IsTypedDataViewClassId(cid)) {
11548 const intptr_t index =
11551 return static_cast<TypedDataElementType>(index);
11552 } else if (IsExternalTypedDataClassId(cid)) {
11553 const intptr_t index =
11556 return static_cast<TypedDataElementType>(index);
11557 } else {
11559 const intptr_t index =
11562 return static_cast<TypedDataElementType>(index);
11563 }
11564 }
11565
11566 bool IsExternalOrExternalView() const;
11567 TypedDataViewPtr ViewFromTo(intptr_t start,
11568 intptr_t end,
11569 Heap::Space space = Heap::kNew) const;
11570
11571 void* DataAddr(intptr_t byte_offset) const {
11572 ASSERT((byte_offset == 0) ||
11573 ((byte_offset > 0) && (byte_offset < LengthInBytes())));
11574 return reinterpret_cast<void*>(Validate(untag()->data_) + byte_offset);
11575 }
11576
11577#define TYPED_GETTER_SETTER(name, type) \
11578 type Get##name(intptr_t byte_offset) const { \
11579 ASSERT(static_cast<uintptr_t>(byte_offset) <= \
11580 static_cast<uintptr_t>(LengthInBytes()) - sizeof(type)); \
11581 return LoadUnaligned( \
11582 reinterpret_cast<type*>(untag()->data_ + byte_offset)); \
11583 } \
11584 void Set##name(intptr_t byte_offset, type value) const { \
11585 ASSERT(static_cast<uintptr_t>(byte_offset) <= \
11586 static_cast<uintptr_t>(LengthInBytes()) - sizeof(type)); \
11587 StoreUnaligned(reinterpret_cast<type*>(untag()->data_ + byte_offset), \
11588 value); \
11589 }
11590
11591 TYPED_GETTER_SETTER(Int8, int8_t)
11592 TYPED_GETTER_SETTER(Uint8, uint8_t)
11593 TYPED_GETTER_SETTER(Int16, int16_t)
11594 TYPED_GETTER_SETTER(Uint16, uint16_t)
11595 TYPED_GETTER_SETTER(Int32, int32_t)
11596 TYPED_GETTER_SETTER(Uint32, uint32_t)
11597 TYPED_GETTER_SETTER(Int64, int64_t)
11598 TYPED_GETTER_SETTER(Uint64, uint64_t)
11599 TYPED_GETTER_SETTER(Float32, float)
11600 TYPED_GETTER_SETTER(Float64, double)
11604
11605#undef TYPED_GETTER_SETTER
11606
11607 protected:
11608 void SetLength(intptr_t value) const {
11610 untag()->set_length(Smi::New(value));
11611 }
11612
11613 virtual uint8_t* Validate(uint8_t* data) const {
11615 }
11616
11617 private:
11618 friend class Class;
11619
11620 static intptr_t element_size(intptr_t index) {
11621 ASSERT(0 <= index && index < kNumElementSizes);
11622 intptr_t size = element_size_table[index];
11623 ASSERT(size != 0);
11624 return size;
11625 }
11626 static constexpr intptr_t kNumElementSizes =
11629 static const intptr_t element_size_table[kNumElementSizes];
11630
11632};
11633
11634class TypedData : public TypedDataBase {
11635 public:
11636 virtual bool CanonicalizeEquals(const Instance& other) const;
11637 virtual uint32_t CanonicalizeHash() const;
11638
11639#define TYPED_GETTER_SETTER(name, type) \
11640 type Get##name(intptr_t byte_offset) const { \
11641 ASSERT(static_cast<uintptr_t>(byte_offset) <= \
11642 static_cast<uintptr_t>(LengthInBytes()) - sizeof(type)); \
11643 return LoadUnaligned( \
11644 reinterpret_cast<const type*>(untag()->data() + byte_offset)); \
11645 } \
11646 void Set##name(intptr_t byte_offset, type value) const { \
11647 ASSERT(static_cast<uintptr_t>(byte_offset) <= \
11648 static_cast<uintptr_t>(LengthInBytes()) - sizeof(type)); \
11649 return StoreUnaligned( \
11650 reinterpret_cast<type*>(untag()->data() + byte_offset), value); \
11651 }
11652
11653 TYPED_GETTER_SETTER(Int8, int8_t)
11654 TYPED_GETTER_SETTER(Uint8, uint8_t)
11655 TYPED_GETTER_SETTER(Int16, int16_t)
11656 TYPED_GETTER_SETTER(Uint16, uint16_t)
11657 TYPED_GETTER_SETTER(Int32, int32_t)
11658 TYPED_GETTER_SETTER(Uint32, uint32_t)
11659 TYPED_GETTER_SETTER(Int64, int64_t)
11660 TYPED_GETTER_SETTER(Uint64, uint64_t)
11661 TYPED_GETTER_SETTER(Float32, float)
11662 TYPED_GETTER_SETTER(Float64, double)
11663 TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
11664 TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
11665 TYPED_GETTER_SETTER(Float64x2, simd128_value_t)
11666
11667#undef TYPED_GETTER_SETTER
11668
11669 static intptr_t payload_offset() {
11671 }
11672
11673 static intptr_t InstanceSize() {
11674 ASSERT(sizeof(UntaggedTypedData) ==
11676 return 0;
11677 }
11678
11679 static intptr_t InstanceSize(intptr_t lengthInBytes) {
11680 ASSERT(0 <= lengthInBytes && lengthInBytes <= kSmiMax);
11681 return RoundedAllocationSize(sizeof(UntaggedTypedData) + lengthInBytes);
11682 }
11683
11684 static intptr_t MaxElements(intptr_t class_id) {
11685 ASSERT(IsTypedDataClassId(class_id));
11686 return (kSmiMax / ElementSizeInBytes(class_id));
11687 }
11688
11689 static intptr_t MaxNewSpaceElements(intptr_t class_id) {
11690 ASSERT(IsTypedDataClassId(class_id));
11691 return (kNewAllocatableSize - sizeof(UntaggedTypedData)) /
11692 ElementSizeInBytes(class_id);
11693 }
11694
11695 static TypedDataPtr New(intptr_t class_id,
11696 intptr_t len,
11697 Heap::Space space = Heap::kNew);
11698
11699 static TypedDataPtr Grow(const TypedData& current,
11700 intptr_t len,
11701 Heap::Space space = Heap::kNew);
11702
11703 static bool IsTypedData(const Instance& obj) {
11704 ASSERT(!obj.IsNull());
11705 intptr_t cid = obj.ptr()->GetClassId();
11706 return IsTypedDataClassId(cid);
11707 }
11708
11709 protected:
11710 void RecomputeDataField() { ptr()->untag()->RecomputeDataField(); }
11711
11712 private:
11713 // Provides const access to non-pointer, non-aligned data within the object.
11714 // Such access does not need a write barrier, but it is *not* GC-safe, since
11715 // the object might move.
11716 //
11717 // Therefore this method is private and the call-sites in this class need to
11718 // ensure the returned pointer does not escape.
11719 template <typename FieldType>
11720 const FieldType* ReadOnlyDataAddr(intptr_t byte_offset) const {
11721 return reinterpret_cast<const FieldType*>((untag()->data()) + byte_offset);
11722 }
11723
11724 FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedData, TypedDataBase);
11725 friend class Class;
11726 friend class ExternalTypedData;
11727 friend class TypedDataView;
11728};
11729
11731 public:
11732 // Alignment of data when serializing ExternalTypedData in a clustered
11733 // snapshot. Should be independent of word size.
11734 static constexpr int kDataSerializationAlignment = 8;
11735
11738 intptr_t external_size) const;
11739
11740 static intptr_t InstanceSize() {
11742 }
11743
11744 static intptr_t MaxElements(intptr_t class_id) {
11746 return (kSmiMax / ElementSizeInBytes(class_id));
11747 }
11748
11749 static ExternalTypedDataPtr New(
11750 intptr_t class_id,
11751 uint8_t* data,
11752 intptr_t len,
11753 Heap::Space space = Heap::kNew,
11754 bool perform_eager_msan_initialization_check = true);
11755
11756 static ExternalTypedDataPtr NewFinalizeWithFree(uint8_t* data, intptr_t len);
11757
11758 static bool IsExternalTypedData(const Instance& obj) {
11759 ASSERT(!obj.IsNull());
11760 intptr_t cid = obj.ptr()->GetClassId();
11762 }
11763
11764 protected:
11765 virtual uint8_t* Validate(uint8_t* data) const { return data; }
11766
11767 void SetLength(intptr_t value) const {
11769 untag()->set_length(Smi::New(value));
11770 }
11771
11772 void SetData(uint8_t* data) const {
11774 reinterpret_cast<uword>(data)));
11775 StoreNonPointer(&untag()->data_, data);
11776 }
11777
11778 private:
11780 friend class Class;
11781};
11782
11784 public:
11785 static TypedDataViewPtr New(intptr_t class_id,
11786 Heap::Space space = Heap::kNew);
11787 static TypedDataViewPtr New(intptr_t class_id,
11788 const TypedDataBase& typed_data,
11789 intptr_t offset_in_bytes,
11790 intptr_t length,
11791 Heap::Space space = Heap::kNew);
11792
11793 static intptr_t InstanceSize() {
11795 }
11796
11797 static InstancePtr Data(const TypedDataView& view) {
11798 return view.typed_data();
11799 }
11800
11801 static SmiPtr OffsetInBytes(const TypedDataView& view) {
11802 return view.offset_in_bytes();
11803 }
11804
11805 static bool IsExternalTypedDataView(const TypedDataView& view_obj) {
11806 const auto& data = Instance::Handle(Data(view_obj));
11807 intptr_t cid = data.ptr()->GetClassId();
11810 }
11811
11812 static intptr_t typed_data_offset() {
11813 return OFFSET_OF(UntaggedTypedDataView, typed_data_);
11814 }
11815
11816 static intptr_t offset_in_bytes_offset() {
11817 return OFFSET_OF(UntaggedTypedDataView, offset_in_bytes_);
11818 }
11819
11820 TypedDataBasePtr typed_data() const { return untag()->typed_data(); }
11821
11822 void InitializeWith(const TypedDataBase& typed_data,
11823 intptr_t offset_in_bytes,
11824 intptr_t length) {
11825 const classid_t cid = typed_data.GetClassId();
11827 untag()->set_typed_data(typed_data.ptr());
11828 untag()->set_length(Smi::New(length));
11829 untag()->set_offset_in_bytes(Smi::New(offset_in_bytes));
11830
11831 // Update the inner pointer.
11832 RecomputeDataField();
11833 }
11834
11835 SmiPtr offset_in_bytes() const { return untag()->offset_in_bytes(); }
11836
11837 protected:
11838 virtual uint8_t* Validate(uint8_t* data) const { return data; }
11839
11840 private:
11841 void RecomputeDataField() const { ptr()->untag()->RecomputeDataField(); }
11842
11843 void Clear() {
11844 untag()->set_length(Smi::New(0));
11845 untag()->set_offset_in_bytes(Smi::New(0));
11846 StoreNonPointer(&untag()->data_, nullptr);
11847 untag()->set_typed_data(TypedDataBase::RawCast(Object::null()));
11848 }
11849
11850 FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedDataView, TypedDataBase);
11851 friend class Class;
11852 friend class DeferredObject;
11853 friend class Object;
11855};
11856
11857class ByteBuffer : public AllStatic {
11858 public:
11859 static constexpr bool ContainsCompressedPointers() {
11861 }
11862
11863 static InstancePtr Data(const Instance& view_obj) {
11864 ASSERT(!view_obj.IsNull());
11865 return reinterpret_cast<CompressedInstancePtr*>(
11866 reinterpret_cast<uword>(view_obj.untag()) + data_offset())
11867 ->Decompress(view_obj.untag()->heap_base());
11868 }
11869
11870 static intptr_t NumberOfFields() { return kNumFields; }
11871
11872 static intptr_t data_offset() {
11873 return sizeof(UntaggedObject) + (kCompressedWordSize * kDataIndex);
11874 }
11875
11876 private:
11877 enum {
11878 kDataIndex = 0,
11879 kNumFields = 1,
11880 };
11881};
11882
11883class Pointer : public Instance {
11884 public:
11885 static PointerPtr New(uword native_address, Heap::Space space = Heap::kNew);
11886
11887 static intptr_t InstanceSize() {
11888 return RoundedAllocationSize(sizeof(UntaggedPointer));
11889 }
11890
11891 static bool IsPointer(const Instance& obj);
11892
11893 size_t NativeAddress() const {
11894 return reinterpret_cast<size_t>(untag()->data_);
11895 }
11896
11897 void SetNativeAddress(size_t address) const {
11898 uint8_t* value = reinterpret_cast<uint8_t*>(address);
11899 StoreNonPointer(&untag()->data_, value);
11900 }
11901
11902 static intptr_t type_arguments_offset() {
11903 return OFFSET_OF(UntaggedPointer, type_arguments_);
11904 }
11905
11906 static constexpr intptr_t kNativeTypeArgPos = 0;
11907
11908 // Fetches the NativeType type argument.
11909 AbstractTypePtr type_argument() const {
11910 TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
11912 }
11913
11914 private:
11916
11917 friend class Class;
11918};
11919
11920class DynamicLibrary : public Instance {
11921 public:
11922 static DynamicLibraryPtr New(void* handle,
11923 bool canBeClosed,
11924 Heap::Space space = Heap::kNew);
11925
11926 static intptr_t InstanceSize() {
11928 }
11929
11930 static bool IsDynamicLibrary(const Instance& obj) {
11931 ASSERT(!obj.IsNull());
11932 intptr_t cid = obj.ptr()->GetClassId();
11934 }
11935
11936 void* GetHandle() const {
11937 ASSERT(!IsNull());
11938 return untag()->handle_;
11939 }
11940
11941 void SetHandle(void* value) const {
11943 }
11944
11945 bool CanBeClosed() const {
11946 ASSERT(!IsNull());
11947 return untag()->canBeClosed_;
11948 }
11949
11950 void SetCanBeClosed(bool value) const {
11951 ASSERT(!IsNull());
11952 StoreNonPointer(&untag()->canBeClosed_, value);
11953 }
11954
11955 bool IsClosed() const {
11956 ASSERT(!IsNull());
11957 return untag()->isClosed_;
11958 }
11959
11960 void SetClosed(bool value) const {
11961 StoreNonPointer(&untag()->isClosed_, value);
11962 }
11963
11964 private:
11966
11967 friend class Class;
11968};
11969
11970class LinkedHashBase : public Instance {
11971 public:
11972 // Keep consistent with _indexSizeToHashMask in compact_hash.dart.
11973 static intptr_t IndexSizeToHashMask(intptr_t index_size) {
11974 ASSERT(index_size >= kInitialIndexSize);
11975 intptr_t index_bits = Utils::BitLength(index_size) - 2;
11976#if defined(HAS_SMI_63_BITS)
11977 return (1 << (32 - index_bits)) - 1;
11978#else
11979 return (1 << (Object::kHashBits - index_bits)) - 1;
11980#endif
11981 }
11982 static intptr_t InstanceSize() {
11984 }
11985
11986 static intptr_t type_arguments_offset() {
11987 return OFFSET_OF(UntaggedLinkedHashBase, type_arguments_);
11988 }
11989
11990 static intptr_t index_offset() {
11991 return OFFSET_OF(UntaggedLinkedHashBase, index_);
11992 }
11993
11994 static intptr_t data_offset() {
11995 return OFFSET_OF(UntaggedLinkedHashBase, data_);
11996 }
11997
11998 static intptr_t hash_mask_offset() {
11999 return OFFSET_OF(UntaggedLinkedHashBase, hash_mask_);
12000 }
12001
12002 static intptr_t used_data_offset() {
12003 return OFFSET_OF(UntaggedLinkedHashBase, used_data_);
12004 }
12005
12006 static intptr_t deleted_keys_offset() {
12007 return OFFSET_OF(UntaggedLinkedHashBase, deleted_keys_);
12008 }
12009
12010 static const LinkedHashBase& Cast(const Object& obj) {
12011 ASSERT(obj.IsMap() || obj.IsSet());
12012 return static_cast<const LinkedHashBase&>(obj);
12013 }
12014
12015 bool IsImmutable() const {
12016 return GetClassId() == kConstMapCid || GetClassId() == kConstSetCid;
12017 }
12018
12019 virtual TypeArgumentsPtr GetTypeArguments() const {
12020 return untag()->type_arguments();
12021 }
12022 virtual void SetTypeArguments(const TypeArguments& value) const {
12023 const intptr_t num_type_args = IsMap() ? 2 : 1;
12024 ASSERT(value.IsNull() ||
12025 ((value.Length() >= num_type_args) &&
12026 value.IsInstantiated() /*&& value.IsCanonical()*/));
12027 // TODO(asiva): Values read from a message snapshot are not properly marked
12028 // as canonical. See for example tests/isolate/message3_test.dart.
12029 untag()->set_type_arguments(value.ptr());
12030 }
12031
12032 TypedDataPtr index() const { return untag()->index(); }
12033 void set_index(const TypedData& value) const {
12034 ASSERT(!value.IsNull());
12035 untag()->set_index(value.ptr());
12036 }
12037
12038 ArrayPtr data() const { return untag()->data(); }
12039 void set_data(const Array& value) const { untag()->set_data(value.ptr()); }
12040
12041 SmiPtr hash_mask() const { return untag()->hash_mask(); }
12042 void set_hash_mask(intptr_t value) const {
12043 untag()->set_hash_mask(Smi::New(value));
12044 }
12045
12046 SmiPtr used_data() const { return untag()->used_data(); }
12047 void set_used_data(intptr_t value) const {
12048 untag()->set_used_data(Smi::New(value));
12049 }
12050
12051 SmiPtr deleted_keys() const { return untag()->deleted_keys(); }
12052 void set_deleted_keys(intptr_t value) const {
12053 untag()->set_deleted_keys(Smi::New(value));
12054 }
12055
12056 intptr_t Length() const {
12057 // The map or set may be uninitialized.
12058 if (untag()->used_data() == Object::null()) return 0;
12059 if (untag()->deleted_keys() == Object::null()) return 0;
12060
12061 intptr_t used = Smi::Value(untag()->used_data());
12062 if (IsMap()) {
12063 used >>= 1;
12064 }
12065 const intptr_t deleted = Smi::Value(untag()->deleted_keys());
12066 return used - deleted;
12067 }
12068
12069 // We do not compute the indices in the VM, but we do precompute the hash
12070 // mask to avoid a load acquire barrier on reading the combination of index
12071 // and hash mask.
12072 void ComputeAndSetHashMask() const;
12073
12074 virtual bool CanonicalizeEquals(const Instance& other) const;
12075 virtual uint32_t CanonicalizeHash() const;
12076 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
12077
12078 protected:
12079 // Keep this in sync with Dart implementation (lib/compact_hash.dart).
12080 static constexpr intptr_t kInitialIndexBits = 2;
12081 static constexpr intptr_t kInitialIndexSize = 1 << (kInitialIndexBits + 1);
12082
12083 private:
12084 LinkedHashBasePtr ptr() const { return static_cast<LinkedHashBasePtr>(ptr_); }
12085 UntaggedLinkedHashBase* untag() const {
12086 ASSERT(ptr() != null());
12087 return const_cast<UntaggedLinkedHashBase*>(ptr()->untag());
12088 }
12089
12090 friend class Class;
12092 friend class LinkedHashBaseDeserializationCluster;
12093};
12094
12096 public:
12097 static constexpr bool ContainsCompressedPointers() {
12099 }
12100
12101 static intptr_t data_offset() { return LinkedHashBase::data_offset(); }
12102};
12103
12104// Corresponds to
12105// - _Map in dart:collection
12106// - "new Map()",
12107// - non-const map literals, and
12108// - the default constructor of LinkedHashMap in dart:collection.
12109class Map : public LinkedHashBase {
12110 public:
12111 static intptr_t InstanceSize() {
12112 return RoundedAllocationSize(sizeof(UntaggedMap));
12113 }
12114
12115 // Allocates a map with some default capacity, just like "new Map()".
12116 static MapPtr NewDefault(intptr_t class_id = kMapCid,
12117 Heap::Space space = Heap::kNew);
12118 static MapPtr New(intptr_t class_id,
12119 const Array& data,
12120 const TypedData& index,
12121 intptr_t hash_mask,
12122 intptr_t used_data,
12123 intptr_t deleted_keys,
12124 Heap::Space space = Heap::kNew);
12125
12126 // This iterator differs somewhat from its Dart counterpart (_CompactIterator
12127 // in runtime/lib/compact_hash.dart):
12128 // - There are no checks for concurrent modifications.
12129 // - Accessing a key or value before the first call to MoveNext and after
12130 // MoveNext returns false will result in crashes.
12131 class Iterator : public ValueObject {
12132 public:
12133 explicit Iterator(const Map& map)
12134 : data_(Array::Handle(map.data())),
12135 scratch_(Object::Handle()),
12136 offset_(-2),
12137 length_(Smi::Value(map.used_data())) {}
12138
12139 bool MoveNext() {
12140 while (true) {
12141 offset_ += 2;
12142 if (offset_ >= length_) {
12143 return false;
12144 }
12145 scratch_ = data_.At(offset_);
12146 if (scratch_.ptr() != data_.ptr()) {
12147 // Slot is not deleted (self-reference indicates deletion).
12148 return true;
12149 }
12150 }
12151 }
12152
12153 ObjectPtr CurrentKey() const { return data_.At(offset_); }
12154
12155 ObjectPtr CurrentValue() const { return data_.At(offset_ + 1); }
12156
12157 private:
12158 const Array& data_;
12159 Object& scratch_;
12160 intptr_t offset_;
12161 const intptr_t length_;
12162 };
12163
12164 private:
12166
12167 // Allocate a map, but leave all fields set to null.
12168 // Used during deserialization (since map might contain itself as key/value).
12169 static MapPtr NewUninitialized(intptr_t class_id,
12170 Heap::Space space = Heap::kNew);
12171
12172 friend class Class;
12173 friend class ConstMap;
12175};
12176
12177// Corresponds to
12178// - _ConstMap in dart:collection
12179// - const map literals
12180class ConstMap : public AllStatic {
12181 public:
12182 static constexpr bool ContainsCompressedPointers() {
12184 }
12185
12186 static ConstMapPtr NewDefault(Heap::Space space = Heap::kNew);
12187
12188 static ConstMapPtr NewUninitialized(Heap::Space space = Heap::kNew);
12189
12190 static const ClassId kClassId = kConstMapCid;
12191
12192 static intptr_t InstanceSize() { return Map::InstanceSize(); }
12193
12194 private:
12195 static intptr_t NextFieldOffset() {
12196 // Indicates this class cannot be extended by dart code.
12197 return -kWordSize;
12198 }
12199
12200 static ConstMapPtr raw(const Map& map) {
12201 return static_cast<ConstMapPtr>(map.ptr());
12202 }
12203
12204 friend class Class;
12205};
12206
12207// Corresponds to
12208// - _Set in dart:collection,
12209// - "new Set()",
12210// - non-const set literals, and
12211// - the default constructor of LinkedHashSet in dart:collection.
12212class Set : public LinkedHashBase {
12213 public:
12214 static intptr_t InstanceSize() {
12215 return RoundedAllocationSize(sizeof(UntaggedSet));
12216 }
12217
12218 // Allocates a set with some default capacity, just like "new Set()".
12219 static SetPtr NewDefault(intptr_t class_id = kSetCid,
12220 Heap::Space space = Heap::kNew);
12221 static SetPtr New(intptr_t class_id,
12222 const Array& data,
12223 const TypedData& index,
12224 intptr_t hash_mask,
12225 intptr_t used_data,
12226 intptr_t deleted_keys,
12227 Heap::Space space = Heap::kNew);
12228
12229 // This iterator differs somewhat from its Dart counterpart (_CompactIterator
12230 // in runtime/lib/compact_hash.dart):
12231 // - There are no checks for concurrent modifications.
12232 // - Accessing a key or value before the first call to MoveNext and after
12233 // MoveNext returns false will result in crashes.
12234 class Iterator : public ValueObject {
12235 public:
12236 explicit Iterator(const Set& set)
12237 : data_(Array::Handle(set.data())),
12238 scratch_(Object::Handle()),
12239 offset_(-1),
12240 length_(Smi::Value(set.used_data())) {}
12241
12242 bool MoveNext() {
12243 while (true) {
12244 offset_++;
12245 if (offset_ >= length_) {
12246 return false;
12247 }
12248 scratch_ = data_.At(offset_);
12249 if (scratch_.ptr() != data_.ptr()) {
12250 // Slot is not deleted (self-reference indicates deletion).
12251 return true;
12252 }
12253 }
12254 }
12255
12256 ObjectPtr CurrentKey() const { return data_.At(offset_); }
12257
12258 private:
12259 const Array& data_;
12260 Object& scratch_;
12261 intptr_t offset_;
12262 const intptr_t length_;
12263 };
12264
12265 private:
12267
12268 // Allocate a set, but leave all fields set to null.
12269 // Used during deserialization (since set might contain itself as key/value).
12270 static SetPtr NewUninitialized(intptr_t class_id,
12271 Heap::Space space = Heap::kNew);
12272
12273 friend class Class;
12274 friend class ConstSet;
12276};
12277
12278// Corresponds to
12279// - _ConstSet in dart:collection
12280// - const set literals
12281class ConstSet : public AllStatic {
12282 public:
12283 static constexpr bool ContainsCompressedPointers() {
12285 }
12286
12287 static ConstSetPtr NewDefault(Heap::Space space = Heap::kNew);
12288
12289 static ConstSetPtr NewUninitialized(Heap::Space space = Heap::kNew);
12290
12291 static const ClassId kClassId = kConstSetCid;
12292
12293 static intptr_t InstanceSize() { return Set::InstanceSize(); }
12294
12295 private:
12296 static intptr_t NextFieldOffset() {
12297 // Indicates this class cannot be extended by dart code.
12298 return -kWordSize;
12299 }
12300
12301 static ConstSetPtr raw(const Set& map) {
12302 return static_cast<ConstSetPtr>(map.ptr());
12303 }
12304
12305 friend class Class;
12306};
12307
12308class Closure : public Instance {
12309 public:
12310#if defined(DART_PRECOMPILED_RUNTIME)
12311 uword entry_point() const { return untag()->entry_point_; }
12312 void set_entry_point(uword entry_point) const {
12313 StoreNonPointer(&untag()->entry_point_, entry_point);
12314 }
12315 static intptr_t entry_point_offset() {
12316 return OFFSET_OF(UntaggedClosure, entry_point_);
12317 }
12318#endif
12319
12320 TypeArgumentsPtr instantiator_type_arguments() const {
12321 return untag()->instantiator_type_arguments();
12322 }
12324 untag()->set_instantiator_type_arguments(args.ptr());
12325 }
12327 return OFFSET_OF(UntaggedClosure, instantiator_type_arguments_);
12328 }
12329
12330 TypeArgumentsPtr function_type_arguments() const {
12331 return untag()->function_type_arguments();
12332 }
12334 untag()->set_function_type_arguments(args.ptr());
12335 }
12337 return OFFSET_OF(UntaggedClosure, function_type_arguments_);
12338 }
12339
12340 TypeArgumentsPtr delayed_type_arguments() const {
12341 return untag()->delayed_type_arguments();
12342 }
12344 untag()->set_delayed_type_arguments(args.ptr());
12345 }
12347 return OFFSET_OF(UntaggedClosure, delayed_type_arguments_);
12348 }
12349
12350 FunctionPtr function() const { return untag()->function(); }
12351 static intptr_t function_offset() {
12352 return OFFSET_OF(UntaggedClosure, function_);
12353 }
12354 static FunctionPtr FunctionOf(ClosurePtr closure) {
12355 return closure.untag()->function();
12356 }
12357
12358 ObjectPtr RawContext() const { return untag()->context(); }
12359
12360 ContextPtr GetContext() const {
12362 return Context::RawCast(RawContext());
12363 }
12364
12365 InstancePtr GetImplicitClosureReceiver() const {
12367 return Instance::RawCast(RawContext());
12368 }
12369
12370 static intptr_t context_offset() {
12371 return OFFSET_OF(UntaggedClosure, context_);
12372 }
12373
12374 // Returns whether the closure is generic, that is, it has a generic closure
12375 // function and no delayed type arguments.
12376 bool IsGeneric() const {
12377 return delayed_type_arguments() == Object::empty_type_arguments().ptr();
12378 }
12379
12380 SmiPtr hash() const { return untag()->hash(); }
12381 static intptr_t hash_offset() { return OFFSET_OF(UntaggedClosure, hash_); }
12382
12383 static intptr_t InstanceSize() {
12384 return RoundedAllocationSize(sizeof(UntaggedClosure));
12385 }
12386
12387 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
12388 virtual bool CanonicalizeEquals(const Instance& other) const;
12389 virtual uint32_t CanonicalizeHash() const {
12390 return Function::Handle(function()).Hash();
12391 }
12392 uword ComputeHash() const;
12393
12394 static ClosurePtr New(const TypeArguments& instantiator_type_arguments,
12395 const TypeArguments& function_type_arguments,
12396 const Function& function,
12397 const Object& context,
12398 Heap::Space space = Heap::kNew);
12399
12400 static ClosurePtr New(const TypeArguments& instantiator_type_arguments,
12401 const TypeArguments& function_type_arguments,
12402 const TypeArguments& delayed_type_arguments,
12403 const Function& function,
12404 const Object& context,
12405 Heap::Space space = Heap::kNew);
12406
12407 FunctionTypePtr GetInstantiatedSignature(Zone* zone) const;
12408
12409 private:
12411 friend class Class;
12412};
12413
12414// Corresponds to _Capability in dart:isolate.
12415class Capability : public Instance {
12416 public:
12417 uint64_t Id() const { return untag()->id_; }
12418
12419 static intptr_t InstanceSize() {
12421 }
12422 static CapabilityPtr New(uint64_t id, Heap::Space space = Heap::kNew);
12423
12424 private:
12426 friend class Class;
12427};
12428
12429// Corresponds to _RawReceivePort in dart:isolate.
12430class ReceivePort : public Instance {
12431 public:
12432 SendPortPtr send_port() const { return untag()->send_port(); }
12433 static intptr_t send_port_offset() {
12435 }
12436 Dart_Port Id() const { return send_port()->untag()->id_; }
12437
12438 InstancePtr handler() const { return untag()->handler(); }
12439 void set_handler(const Instance& value) const {
12440 untag()->set_handler(value.ptr());
12441 }
12442 static intptr_t handler_offset() {
12443 return OFFSET_OF(UntaggedReceivePort, handler_);
12444 }
12445
12446 bool is_open() const {
12447 return IsOpen::decode(Smi::Value(untag()->bitfield()));
12448 }
12449 void set_is_open(bool value) const {
12450 const auto updated = IsOpen::update(value, Smi::Value(untag()->bitfield()));
12451 untag()->set_bitfield(Smi::New(updated));
12452 }
12453
12454 bool keep_isolate_alive() const {
12455 return IsKeepIsolateAlive::decode(Smi::Value(untag()->bitfield()));
12456 }
12458 const auto updated =
12459 IsKeepIsolateAlive::update(value, Smi::Value(untag()->bitfield()));
12460 untag()->set_bitfield(Smi::New(updated));
12461 }
12462
12463#if !defined(PRODUCT)
12464 StackTracePtr allocation_location() const {
12465 return untag()->allocation_location();
12466 }
12467
12468 StringPtr debug_name() const { return untag()->debug_name(); }
12469#endif
12470
12471 static intptr_t InstanceSize() {
12473 }
12474 static ReceivePortPtr New(Dart_Port id,
12475 const String& debug_name,
12476 Heap::Space space = Heap::kNew);
12477
12478 private:
12479 class IsOpen : public BitField<intptr_t, bool, 0, 1> {};
12480 class IsKeepIsolateAlive
12481 : public BitField<intptr_t, bool, IsOpen::kNextBit, 1> {};
12482
12483 FINAL_HEAP_OBJECT_IMPLEMENTATION(ReceivePort, Instance);
12484 friend class Class;
12485};
12486
12487// Corresponds to _SendPort in dart:isolate.
12488class SendPort : public Instance {
12489 public:
12490 Dart_Port Id() const { return untag()->id_; }
12491
12492 Dart_Port origin_id() const { return untag()->origin_id_; }
12493 void set_origin_id(Dart_Port id) const {
12494 ASSERT(origin_id() == 0);
12495 StoreNonPointer(&(untag()->origin_id_), id);
12496 }
12497
12498 static intptr_t InstanceSize() {
12500 }
12501 static SendPortPtr New(Dart_Port id, Heap::Space space = Heap::kNew);
12502 static SendPortPtr New(Dart_Port id,
12503 Dart_Port origin_id,
12504 Heap::Space space = Heap::kNew);
12505
12506 private:
12508 friend class Class;
12509};
12510
12511// This is allocated when new instance of TransferableTypedData is created in
12512// [TransferableTypedData::New].
12514 public:
12515 // [data] backing store should be malloc'ed, not new'ed.
12517 : data_(data), length_(length), handle_(nullptr) {}
12518
12520
12521 uint8_t* data() const { return data_; }
12522 intptr_t length() const { return length_; }
12525
12526 void ClearData() {
12527 data_ = nullptr;
12528 length_ = 0;
12529 handle_ = nullptr;
12530 }
12531
12532 private:
12533 uint8_t* data_;
12534 intptr_t length_;
12536
12538};
12539
12541 public:
12542 static TransferableTypedDataPtr New(uint8_t* data, intptr_t len);
12543
12544 static intptr_t InstanceSize() {
12546 }
12547
12548 private:
12550 friend class Class;
12551};
12552
12553class DebuggerStackTrace;
12554
12555// Internal stacktrace object used in exceptions for printing stack traces.
12556class StackTrace : public Instance {
12557 public:
12558 static constexpr int kPreallocatedStackdepth = 90;
12559
12560 intptr_t Length() const;
12561
12562 StackTracePtr async_link() const { return untag()->async_link(); }
12563 void set_async_link(const StackTrace& async_link) const;
12564 void set_expand_inlined(bool value) const;
12565
12566 ArrayPtr code_array() const { return untag()->code_array(); }
12567 ObjectPtr CodeAtFrame(intptr_t frame_index) const;
12568 void SetCodeAtFrame(intptr_t frame_index, const Object& code) const;
12569
12570 TypedDataPtr pc_offset_array() const { return untag()->pc_offset_array(); }
12571 uword PcOffsetAtFrame(intptr_t frame_index) const;
12572 void SetPcOffsetAtFrame(intptr_t frame_index, uword pc_offset) const;
12573
12574 bool skip_sync_start_in_parent_stack() const;
12575 void set_skip_sync_start_in_parent_stack(bool value) const;
12576
12577 // The number of frames that should be cut off the top of an async stack trace
12578 // if it's appended to a synchronous stack trace along a sync-async call.
12579 //
12580 // Without cropping, the border would look like:
12581 //
12582 // <async function>
12583 // ---------------------------
12584 // <asynchronous gap marker>
12585 // <async function>
12586 //
12587 // Since it's not actually an async call, we crop off the last two
12588 // frames when concatenating the sync and async stacktraces.
12589 static constexpr intptr_t kSyncAsyncCroppedFrames = 2;
12590
12591 static intptr_t InstanceSize() {
12593 }
12594 static StackTracePtr New(const Array& code_array,
12595 const TypedData& pc_offset_array,
12596 Heap::Space space = Heap::kNew);
12597
12598 static StackTracePtr New(const Array& code_array,
12599 const TypedData& pc_offset_array,
12600 const StackTrace& async_link,
12601 bool skip_sync_start_in_parent_stack,
12602 Heap::Space space = Heap::kNew);
12603
12604 private:
12605 void set_code_array(const Array& code_array) const;
12606 void set_pc_offset_array(const TypedData& pc_offset_array) const;
12607 bool expand_inlined() const;
12608
12610 friend class Class;
12612};
12613
12614class SuspendState : public Instance {
12615 public:
12616 // :suspend_state local variable index
12617 static constexpr intptr_t kSuspendStateVarIndex = 0;
12618
12619 static intptr_t HeaderSize() { return sizeof(UntaggedSuspendState); }
12620 static intptr_t UnroundedSize(SuspendStatePtr ptr) {
12621 return UnroundedSize(ptr->untag()->frame_capacity());
12622 }
12623 static intptr_t UnroundedSize(intptr_t frame_capacity) {
12624 return HeaderSize() + frame_capacity;
12625 }
12626 static intptr_t InstanceSize() {
12629 return 0;
12630 }
12631 static intptr_t InstanceSize(intptr_t frame_capacity) {
12632 return RoundedAllocationSize(UnroundedSize(frame_capacity));
12633 }
12634
12635 // Number of extra words reserved for growth of frame size
12636 // during SuspendState allocation. Frames do not grow in AOT.
12637 static intptr_t FrameSizeGrowthGap() {
12639 }
12640
12641#if !defined(DART_PRECOMPILED_RUNTIME)
12642 static intptr_t frame_capacity_offset() {
12643 return OFFSET_OF(UntaggedSuspendState, frame_capacity_);
12644 }
12645#endif
12646 static intptr_t frame_size_offset() {
12647 return OFFSET_OF(UntaggedSuspendState, frame_size_);
12648 }
12649 static intptr_t pc_offset() { return OFFSET_OF(UntaggedSuspendState, pc_); }
12650 static intptr_t function_data_offset() {
12651 return OFFSET_OF(UntaggedSuspendState, function_data_);
12652 }
12653 static intptr_t then_callback_offset() {
12654 return OFFSET_OF(UntaggedSuspendState, then_callback_);
12655 }
12656 static intptr_t error_callback_offset() {
12657 return OFFSET_OF(UntaggedSuspendState, error_callback_);
12658 }
12659 static intptr_t payload_offset() {
12661 }
12662
12663 static SuspendStatePtr New(intptr_t frame_size,
12664 const Instance& function_data,
12665 Heap::Space space = Heap::kNew);
12666
12667 // Makes a copy of [src] object.
12668 // The object should be holding a suspended frame.
12669 static SuspendStatePtr Clone(Thread* thread,
12670 const SuspendState& src,
12671 Heap::Space space = Heap::kNew);
12672
12673 uword pc() const { return untag()->pc_; }
12674
12675 intptr_t frame_size() const { return untag()->frame_size_; }
12676
12677 InstancePtr function_data() const { return untag()->function_data(); }
12678
12679 ClosurePtr then_callback() const { return untag()->then_callback(); }
12680
12681 ClosurePtr error_callback() const { return untag()->error_callback(); }
12682
12683 // Returns Code object corresponding to the suspended function.
12684 CodePtr GetCodeObject() const;
12685
12686 private:
12687#if !defined(DART_PRECOMPILED_RUNTIME)
12688 void set_frame_capacity(intptr_t frame_capcity) const;
12689#endif
12690 void set_frame_size(intptr_t frame_size) const;
12691 void set_pc(uword pc) const;
12692 void set_function_data(const Instance& function_data) const;
12693 void set_then_callback(const Closure& then_callback) const;
12694 void set_error_callback(const Closure& error_callback) const;
12695
12696 uint8_t* payload() const { return untag()->payload(); }
12697
12698 FINAL_HEAP_OBJECT_IMPLEMENTATION(SuspendState, Instance);
12699 friend class Class;
12700};
12701
12703 public:
12704 // Flags are passed to a regex object as follows:
12705 // 'i': ignore case, 'g': do global matches, 'm': pattern is multi line,
12706 // 'u': pattern is full Unicode, not just BMP, 's': '.' in pattern matches
12707 // all characters including line terminators.
12708 enum Flags {
12710 kGlobal = 1,
12711 kIgnoreCase = 2,
12712 kMultiLine = 4,
12713 kUnicode = 8,
12714 kDotAll = 16,
12715 };
12716
12717 static constexpr int kDefaultFlags = 0;
12718
12719 RegExpFlags() : value_(kDefaultFlags) {}
12720 explicit RegExpFlags(int value) : value_(value) {}
12721
12722 inline bool IsGlobal() const { return (value_ & kGlobal) != 0; }
12723 inline bool IgnoreCase() const { return (value_ & kIgnoreCase) != 0; }
12724 inline bool IsMultiLine() const { return (value_ & kMultiLine) != 0; }
12725 inline bool IsUnicode() const { return (value_ & kUnicode) != 0; }
12726 inline bool IsDotAll() const { return (value_ & kDotAll) != 0; }
12727
12729 // Both unicode and ignore_case flags are set. We need to use ICU to find
12730 // the closure over case equivalents.
12731 return IsUnicode() && IgnoreCase();
12732 }
12733
12734 void SetGlobal() { value_ |= kGlobal; }
12735 void SetIgnoreCase() { value_ |= kIgnoreCase; }
12736 void SetMultiLine() { value_ |= kMultiLine; }
12737 void SetUnicode() { value_ |= kUnicode; }
12738 void SetDotAll() { value_ |= kDotAll; }
12739
12740 const char* ToCString() const;
12741
12742 int value() const { return value_; }
12743
12744 bool operator==(const RegExpFlags& other) const {
12745 return value_ == other.value_;
12746 }
12747 bool operator!=(const RegExpFlags& other) const {
12748 return value_ != other.value_;
12749 }
12750
12751 private:
12752 int value_;
12753};
12754
12755// Internal JavaScript regular expression object.
12756class RegExp : public Instance {
12757 public:
12758 // Meaning of RegExType:
12759 // kUninitialized: the type of th regexp has not been initialized yet.
12760 // kSimple: A simple pattern to match against, using string indexOf operation.
12761 // kComplex: A complex pattern to match.
12763 kUninitialized = 0,
12764 kSimple = 1,
12765 kComplex = 2,
12766 };
12767
12768 enum {
12769 kTypePos = 0,
12770 kTypeSize = 2,
12771 kFlagsPos = 2,
12772 kFlagsSize = 5,
12773 };
12774
12775 class TypeBits : public BitField<int8_t, RegExType, kTypePos, kTypeSize> {};
12776 class GlobalBit : public BitField<int8_t, bool, kFlagsPos, 1> {};
12777 class IgnoreCaseBit : public BitField<int8_t, bool, GlobalBit::kNextBit, 1> {
12778 };
12780 : public BitField<int8_t, bool, IgnoreCaseBit::kNextBit, 1> {};
12781 class UnicodeBit : public BitField<int8_t, bool, MultiLineBit::kNextBit, 1> {
12782 };
12783 class DotAllBit : public BitField<int8_t, bool, UnicodeBit::kNextBit, 1> {};
12784
12785 class FlagsBits : public BitField<int8_t, int8_t, kFlagsPos, kFlagsSize> {};
12786
12787 bool is_initialized() const { return (type() != kUninitialized); }
12788 bool is_simple() const { return (type() == kSimple); }
12789 bool is_complex() const { return (type() == kComplex); }
12790
12791 intptr_t num_registers(bool is_one_byte) const {
12792 return LoadNonPointer<intptr_t, std::memory_order_relaxed>(
12793 is_one_byte ? &untag()->num_one_byte_registers_
12794 : &untag()->num_two_byte_registers_);
12795 }
12796
12797 StringPtr pattern() const { return untag()->pattern(); }
12798 intptr_t num_bracket_expressions() const {
12799 return untag()->num_bracket_expressions_;
12800 }
12801 ArrayPtr capture_name_map() const { return untag()->capture_name_map(); }
12802
12803 TypedDataPtr bytecode(bool is_one_byte, bool sticky) const {
12804 if (sticky) {
12805 return TypedData::RawCast(
12806 is_one_byte ? untag()->one_byte_sticky<std::memory_order_acquire>()
12807 : untag()->two_byte_sticky<std::memory_order_acquire>());
12808 } else {
12809 return TypedData::RawCast(
12810 is_one_byte ? untag()->one_byte<std::memory_order_acquire>()
12811 : untag()->two_byte<std::memory_order_acquire>());
12812 }
12813 }
12814
12815 static intptr_t function_offset(intptr_t cid, bool sticky) {
12816 if (sticky) {
12817 switch (cid) {
12818 case kOneByteStringCid:
12819 return OFFSET_OF(UntaggedRegExp, one_byte_sticky_);
12820 case kTwoByteStringCid:
12821 return OFFSET_OF(UntaggedRegExp, two_byte_sticky_);
12822 }
12823 } else {
12824 switch (cid) {
12825 case kOneByteStringCid:
12826 return OFFSET_OF(UntaggedRegExp, one_byte_);
12827 case kTwoByteStringCid:
12828 return OFFSET_OF(UntaggedRegExp, two_byte_);
12829 }
12830 }
12831
12832 UNREACHABLE();
12833 return -1;
12834 }
12835
12836 FunctionPtr function(intptr_t cid, bool sticky) const {
12837 if (sticky) {
12838 switch (cid) {
12839 case kOneByteStringCid:
12840 return static_cast<FunctionPtr>(untag()->one_byte_sticky());
12841 case kTwoByteStringCid:
12842 return static_cast<FunctionPtr>(untag()->two_byte_sticky());
12843 }
12844 } else {
12845 switch (cid) {
12846 case kOneByteStringCid:
12847 return static_cast<FunctionPtr>(untag()->one_byte());
12848 case kTwoByteStringCid:
12849 return static_cast<FunctionPtr>(untag()->two_byte());
12850 }
12851 }
12852
12853 UNREACHABLE();
12854 return Function::null();
12855 }
12856
12857 void set_pattern(const String& pattern) const;
12858 void set_function(intptr_t cid, bool sticky, const Function& value) const;
12859 void set_bytecode(bool is_one_byte,
12860 bool sticky,
12861 const TypedData& bytecode) const;
12862
12865 void set_num_bracket_expressions(intptr_t value) const;
12866 void set_capture_name_map(const Array& array) const;
12867 void set_is_global() const {
12868 untag()->type_flags_.UpdateBool<GlobalBit>(true);
12869 }
12870 void set_is_ignore_case() const {
12871 untag()->type_flags_.UpdateBool<IgnoreCaseBit>(true);
12872 }
12873 void set_is_multi_line() const {
12874 untag()->type_flags_.UpdateBool<MultiLineBit>(true);
12875 }
12876 void set_is_unicode() const {
12877 untag()->type_flags_.UpdateBool<UnicodeBit>(true);
12878 }
12879 void set_is_dot_all() const {
12880 untag()->type_flags_.UpdateBool<DotAllBit>(true);
12881 }
12882 void set_is_simple() const { set_type(kSimple); }
12883 void set_is_complex() const { set_type(kComplex); }
12884 void set_num_registers(bool is_one_byte, intptr_t value) const {
12885 StoreNonPointer<intptr_t, intptr_t, std::memory_order_relaxed>(
12886 is_one_byte ? &untag()->num_one_byte_registers_
12887 : &untag()->num_two_byte_registers_,
12888 value);
12889 }
12890
12892 return RegExpFlags(untag()->type_flags_.Read<FlagsBits>());
12893 }
12895 untag()->type_flags_.Update<FlagsBits>(flags.value());
12896 }
12897
12898 virtual bool CanonicalizeEquals(const Instance& other) const;
12899 virtual uint32_t CanonicalizeHash() const;
12900
12901 static intptr_t InstanceSize() {
12902 return RoundedAllocationSize(sizeof(UntaggedRegExp));
12903 }
12904
12905 static RegExpPtr New(Zone* zone, Heap::Space space = Heap::kNew);
12906
12907 private:
12908 void set_type(RegExType type) const {
12909 untag()->type_flags_.Update<TypeBits>(type);
12910 }
12911 RegExType type() const { return untag()->type_flags_.Read<TypeBits>(); }
12912
12913 FINAL_HEAP_OBJECT_IMPLEMENTATION(RegExp, Instance);
12914 friend class Class;
12915};
12916
12917// Corresponds to _WeakProperty in dart:core.
12918class WeakProperty : public Instance {
12919 public:
12920 ObjectPtr key() const { return untag()->key(); }
12921 void set_key(const Object& key) const { untag()->set_key(key.ptr()); }
12922 static intptr_t key_offset() { return OFFSET_OF(UntaggedWeakProperty, key_); }
12923
12924 ObjectPtr value() const { return untag()->value(); }
12925 void set_value(const Object& value) const { untag()->set_value(value.ptr()); }
12926 static intptr_t value_offset() {
12927 return OFFSET_OF(UntaggedWeakProperty, value_);
12928 }
12929
12930 static WeakPropertyPtr New(Heap::Space space = Heap::kNew);
12931
12932 static intptr_t InstanceSize() {
12934 }
12935
12936 private:
12938 friend class Class;
12939};
12940
12941// Corresponds to _WeakReference in dart:core.
12942class WeakReference : public Instance {
12943 public:
12944 ObjectPtr target() const { return untag()->target(); }
12945 void set_target(const Object& target) const {
12946 untag()->set_target(target.ptr());
12947 }
12948 static intptr_t target_offset() {
12949 return OFFSET_OF(UntaggedWeakReference, target_);
12950 }
12951
12952 static intptr_t type_arguments_offset() {
12953 return OFFSET_OF(UntaggedWeakReference, type_arguments_);
12954 }
12955
12956 static WeakReferencePtr New(Heap::Space space = Heap::kNew);
12957
12958 static intptr_t InstanceSize() {
12960 }
12961
12962 private:
12964 friend class Class;
12965};
12966
12967class FinalizerBase;
12968class FinalizerEntry : public Instance {
12969 public:
12970 ObjectPtr value() const { return untag()->value(); }
12971 void set_value(const Object& value) const { untag()->set_value(value.ptr()); }
12972 static intptr_t value_offset() {
12973 return OFFSET_OF(UntaggedFinalizerEntry, value_);
12974 }
12975
12976 ObjectPtr detach() const { return untag()->detach(); }
12977 void set_detach(const Object& value) const {
12978 untag()->set_detach(value.ptr());
12979 }
12980 static intptr_t detach_offset() {
12981 return OFFSET_OF(UntaggedFinalizerEntry, detach_);
12982 }
12983
12984 ObjectPtr token() const { return untag()->token(); }
12985 void set_token(const Object& value) const { untag()->set_token(value.ptr()); }
12986 static intptr_t token_offset() {
12987 return OFFSET_OF(UntaggedFinalizerEntry, token_);
12988 }
12989
12990 FinalizerBasePtr finalizer() const { return untag()->finalizer(); }
12991 void set_finalizer(const FinalizerBase& value) const;
12992 static intptr_t finalizer_offset() {
12993 return OFFSET_OF(UntaggedFinalizerEntry, finalizer_);
12994 }
12995
12996 FinalizerEntryPtr next() const { return untag()->next(); }
12997 void set_next(const FinalizerEntry& value) const {
12998 untag()->set_next(value.ptr());
12999 }
13000 static intptr_t next_offset() {
13001 return OFFSET_OF(UntaggedFinalizerEntry, next_);
13002 }
13003
13004 intptr_t external_size() const { return untag()->external_size(); }
13005 void set_external_size(intptr_t value) const {
13006 untag()->set_external_size(value);
13007 }
13008 static intptr_t external_size_offset() {
13009 return OFFSET_OF(UntaggedFinalizerEntry, external_size_);
13010 }
13011
13012 static intptr_t InstanceSize() {
13014 }
13015
13016 // Allocates a new FinalizerEntry, initializing the external size (to 0) and
13017 // finalizer.
13018 //
13019 // Should only be used for object tests.
13020 //
13021 // Does not initialize `value`, `token`, and `detach` to allow for flexible
13022 // testing code setting those manually.
13023 //
13024 // Does _not_ add the entry to the finalizer. We could add the entry to
13025 // finalizer.all_entries.data, but we have no way of initializing the hashset
13026 // index.
13027 static FinalizerEntryPtr New(const FinalizerBase& finalizer,
13028 Heap::Space space = Heap::kNew);
13029
13030 private:
13032 friend class Class;
13033};
13034
13035class FinalizerBase : public Instance {
13036 public:
13037 static intptr_t isolate_offset() {
13038 return OFFSET_OF(UntaggedFinalizerBase, isolate_);
13039 }
13040 Isolate* isolate() const { return untag()->isolate_; }
13041 void set_isolate(Isolate* value) const { untag()->isolate_ = value; }
13042
13043 static intptr_t detachments_offset() {
13044 return OFFSET_OF(UntaggedFinalizerBase, detachments_);
13045 }
13046
13047 SetPtr all_entries() const { return untag()->all_entries(); }
13048 void set_all_entries(const Set& value) const {
13049 untag()->set_all_entries(value.ptr());
13050 }
13051 static intptr_t all_entries_offset() {
13052 return OFFSET_OF(UntaggedFinalizerBase, all_entries_);
13053 }
13054
13055 FinalizerEntryPtr entries_collected() const {
13056 return untag()->entries_collected();
13057 }
13059 untag()->set_entries_collected(value.ptr());
13060 }
13061 static intptr_t entries_collected_offset() {
13062 return OFFSET_OF(UntaggedFinalizer, entries_collected_);
13063 }
13064
13065 private:
13067 friend class Class;
13068};
13069
13070class Finalizer : public FinalizerBase {
13071 public:
13072 static intptr_t type_arguments_offset() {
13073 return OFFSET_OF(UntaggedFinalizer, type_arguments_);
13074 }
13075
13076 ObjectPtr callback() const { return untag()->callback(); }
13077 static intptr_t callback_offset() {
13079 }
13080
13081 static intptr_t InstanceSize() {
13083 }
13084
13085 static FinalizerPtr New(Heap::Space space = Heap::kNew);
13086
13087 private:
13089 friend class Class;
13090};
13091
13093 public:
13094 typedef void (*Callback)(void*);
13095
13096 PointerPtr callback() const { return untag()->callback(); }
13097 void set_callback(const Pointer& value) const {
13098 untag()->set_callback(value.ptr());
13099 }
13100 static intptr_t callback_offset() {
13102 }
13103
13104 static intptr_t InstanceSize() {
13106 }
13107
13108 static NativeFinalizerPtr New(Heap::Space space = Heap::kNew);
13109
13110 void RunCallback(const FinalizerEntry& entry,
13111 const char* trace_context) const;
13112
13113 private:
13115 friend class Class;
13116};
13117
13119 public:
13120 ObjectPtr referent() const { return untag()->referent(); }
13121
13122 void set_referent(const Object& referent) const {
13123 untag()->set_referent(referent.ptr());
13124 }
13125
13126 AbstractTypePtr GetAbstractTypeReferent() const;
13127
13128 ClassPtr GetClassReferent() const;
13129
13130 FieldPtr GetFieldReferent() const;
13131
13132 FunctionPtr GetFunctionReferent() const;
13133
13134 FunctionTypePtr GetFunctionTypeReferent() const;
13135
13136 LibraryPtr GetLibraryReferent() const;
13137
13138 TypeParameterPtr GetTypeParameterReferent() const;
13139
13140 static MirrorReferencePtr New(const Object& referent,
13141 Heap::Space space = Heap::kNew);
13142
13143 static intptr_t InstanceSize() {
13145 }
13146
13147 private:
13149 friend class Class;
13150};
13151
13152class UserTag : public Instance {
13153 public:
13154 uword tag() const { return untag()->tag(); }
13155 void set_tag(uword t) const {
13158 StoreNonPointer(&untag()->tag_, t);
13159 }
13160
13161 bool streamable() const { return untag()->streamable(); }
13162 void set_streamable(bool streamable) {
13163 StoreNonPointer(&untag()->streamable_, streamable);
13164 }
13165
13166 static intptr_t tag_offset() { return OFFSET_OF(UntaggedUserTag, tag_); }
13167
13168 StringPtr label() const { return untag()->label(); }
13169
13170 UserTagPtr MakeActive() const;
13171
13172 static intptr_t InstanceSize() {
13173 return RoundedAllocationSize(sizeof(UntaggedUserTag));
13174 }
13175
13176 static UserTagPtr New(const String& label, Heap::Space space = Heap::kOld);
13177 static UserTagPtr DefaultTag();
13178
13179 static bool TagTableIsFull(Thread* thread);
13180 static UserTagPtr FindTagById(const Isolate* isolate, uword tag_id);
13181 static UserTagPtr FindTagInIsolate(Isolate* isolate,
13182 Thread* thread,
13183 const String& label);
13184
13185 private:
13186 static UserTagPtr FindTagInIsolate(Thread* thread, const String& label);
13187 static void AddTagToIsolate(Thread* thread, const UserTag& tag);
13188
13189 void set_label(const String& tag_label) const {
13190 untag()->set_label(tag_label.ptr());
13191 }
13192
13193 FINAL_HEAP_OBJECT_IMPLEMENTATION(UserTag, Instance);
13194 friend class Class;
13195};
13196
13197// Represents abstract FutureOr class in dart:async.
13198class FutureOr : public Instance {
13199 public:
13200 static intptr_t InstanceSize() {
13202 }
13203
13204 virtual TypeArgumentsPtr GetTypeArguments() const {
13205 return untag()->type_arguments();
13206 }
13207 static intptr_t type_arguments_offset() {
13208 return OFFSET_OF(UntaggedFutureOr, type_arguments_);
13209 }
13210
13211 private:
13213
13214 friend class Class;
13215};
13216
13217// Breaking cycles and loops.
13218ClassPtr Object::clazz() const {
13219 uword raw_value = static_cast<uword>(ptr_);
13220 if ((raw_value & kSmiTagMask) == kSmiTag) {
13221 return Smi::Class();
13222 }
13224}
13225
13226DART_FORCE_INLINE
13227void Object::setPtr(ObjectPtr value, intptr_t default_cid) {
13228 ptr_ = value;
13229 intptr_t cid = value->GetClassIdMayBeSmi();
13230 // Free-list elements cannot be wrapped in a handle.
13233 if (cid == kNullCid) {
13234 cid = default_cid;
13235 } else if (cid >= kNumPredefinedCids) {
13236 cid = kInstanceCid;
13237 }
13238 set_vtable(builtin_vtables_[cid]);
13239}
13240
13241intptr_t Field::HostOffset() const {
13242 ASSERT(is_instance()); // Valid only for dart instance fields.
13243 return (Smi::Value(untag()->host_offset_or_field_id()) * kCompressedWordSize);
13244}
13245
13246intptr_t Field::TargetOffset() const {
13247 ASSERT(is_instance()); // Valid only for dart instance fields.
13248#if !defined(DART_PRECOMPILED_RUNTIME)
13249 return (untag()->target_offset_ * compiler::target::kCompressedWordSize);
13250#else
13251 return HostOffset();
13252#endif // !defined(DART_PRECOMPILED_RUNTIME)
13253}
13254
13255inline intptr_t Field::TargetOffsetOf(const FieldPtr field) {
13256#if !defined(DART_PRECOMPILED_RUNTIME)
13257 return field->untag()->target_offset_;
13258#else
13259 return Smi::Value(field->untag()->host_offset_or_field_id());
13260#endif // !defined(DART_PRECOMPILED_RUNTIME)
13261}
13262
13263void Field::SetOffset(intptr_t host_offset_in_bytes,
13264 intptr_t target_offset_in_bytes) const {
13265 ASSERT(is_instance()); // Valid only for dart instance fields.
13267 untag()->set_host_offset_or_field_id(
13268 Smi::New(host_offset_in_bytes / kCompressedWordSize));
13269#if !defined(DART_PRECOMPILED_RUNTIME)
13272 &untag()->target_offset_,
13273 target_offset_in_bytes / compiler::target::kCompressedWordSize);
13274#else
13275 ASSERT(host_offset_in_bytes == target_offset_in_bytes);
13276#endif // !defined(DART_PRECOMPILED_RUNTIME)
13277}
13278
13280 ASSERT(is_static()); // Valid only for static dart fields.
13281 return Isolate::Current()->field_table()->At(field_id());
13282}
13283
13284inline intptr_t Field::field_id() const {
13285 return Smi::Value(untag()->host_offset_or_field_id());
13286}
13287
13288void Field::set_field_id(intptr_t field_id) const {
13290 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
13291 set_field_id_unsafe(field_id);
13292}
13293
13294void Field::set_field_id_unsafe(intptr_t field_id) const {
13295 ASSERT(is_static());
13296 untag()->set_host_offset_or_field_id(Smi::New(field_id));
13297}
13298
13299intptr_t WeakArray::LengthOf(const WeakArrayPtr array) {
13300 return Smi::Value(array->untag()->length());
13301}
13302
13303void Context::SetAt(intptr_t index, const Object& value) const {
13304 untag()->set_element(index, value.ptr());
13305}
13306
13307intptr_t Instance::GetNativeField(int index) const {
13308 ASSERT(IsValidNativeIndex(index));
13309 NoSafepointScope no_safepoint;
13310 TypedDataPtr native_fields = static_cast<TypedDataPtr>(
13311 NativeFieldsAddr()->Decompress(untag()->heap_base()));
13312 if (native_fields == TypedData::null()) {
13313 return 0;
13314 }
13315 return reinterpret_cast<intptr_t*>(native_fields->untag()->data())[index];
13316}
13317
13318void Instance::GetNativeFields(uint16_t num_fields,
13319 intptr_t* field_values) const {
13320 NoSafepointScope no_safepoint;
13321 ASSERT(num_fields == NumNativeFields());
13322 ASSERT(field_values != nullptr);
13323 TypedDataPtr native_fields = static_cast<TypedDataPtr>(
13324 NativeFieldsAddr()->Decompress(untag()->heap_base()));
13325 if (native_fields == TypedData::null()) {
13326 for (intptr_t i = 0; i < num_fields; i++) {
13327 field_values[i] = 0;
13328 }
13329 }
13330 intptr_t* fields =
13331 reinterpret_cast<intptr_t*>(native_fields->untag()->data());
13332 for (intptr_t i = 0; i < num_fields; i++) {
13333 field_values[i] = fields[i];
13334 }
13335}
13336
13337bool String::Equals(const String& str) const {
13338 if (ptr() == str.ptr()) {
13339 return true; // Both handles point to the same raw instance.
13340 }
13341 if (str.IsNull()) {
13342 return false;
13343 }
13344 if (IsCanonical() && str.IsCanonical()) {
13345 return false; // Two symbols that aren't identical aren't equal.
13346 }
13347 if (HasHash() && str.HasHash() && (Hash() != str.Hash())) {
13348 return false; // Both sides have hash codes and they do not match.
13349 }
13350 return Equals(str, 0, str.Length());
13351}
13352
13353intptr_t Library::UrlHash() const {
13354 intptr_t result = String::GetCachedHash(url());
13355 ASSERT(result != 0);
13356 return result;
13357}
13358
13359void MegamorphicCache::SetEntry(const Array& array,
13360 intptr_t index,
13361 const Smi& class_id,
13362 const Object& target) {
13363 ASSERT(target.IsNull() || target.IsFunction() || target.IsSmi());
13364 array.SetAt((index * kEntryLength) + kClassIdIndex, class_id);
13365 array.SetAt((index * kEntryLength) + kTargetFunctionIndex, target);
13366}
13367
13368ObjectPtr MegamorphicCache::GetClassId(const Array& array, intptr_t index) {
13369 return array.At((index * kEntryLength) + kClassIdIndex);
13370}
13371
13372ObjectPtr MegamorphicCache::GetTargetFunction(const Array& array,
13373 intptr_t index) {
13374 return array.At((index * kEntryLength) + kTargetFunctionIndex);
13375}
13376
13378 ASSERT(IsFinalized());
13379 intptr_t result = Smi::Value(untag()->hash());
13380 if (result != 0) {
13381 return result;
13382 }
13383 return ComputeHash();
13384}
13385
13386inline void AbstractType::SetHash(intptr_t value) const {
13387 // This is only safe because we create a new Smi, which does not cause
13388 // heap allocation.
13389 untag()->set_hash(Smi::New(value));
13390}
13391
13392inline intptr_t RecordType::NumFields() const {
13393 return Array::LengthOf(field_types());
13394}
13395
13397 if (IsNull()) return kAllDynamicHash;
13398 intptr_t result = Smi::Value(untag()->hash());
13399 if (result != 0) {
13400 return result;
13401 }
13402 return ComputeHash();
13403}
13404
13405inline void TypeArguments::SetHash(intptr_t value) const {
13406 // This is only safe because we create a new Smi, which does not cause
13407 // heap allocation.
13408 untag()->set_hash(Smi::New(value));
13409}
13410
13411inline uint16_t String::CharAt(StringPtr str, intptr_t index) {
13412 switch (str->GetClassId()) {
13413 case kOneByteStringCid:
13414 return OneByteString::CharAt(static_cast<OneByteStringPtr>(str), index);
13415 case kTwoByteStringCid:
13416 return TwoByteString::CharAt(static_cast<TwoByteStringPtr>(str), index);
13417 }
13418 UNREACHABLE();
13419 return 0;
13420}
13421
13422// A view on an [Array] as a list of tuples, optionally starting at an offset.
13423//
13424// Example: We store a list of (kind, function, code) tuples into the
13425// [Code::static_calls_target_table] array of type [Array].
13426//
13427// This helper class can then be used via
13428//
13429// using CallTableView = ArrayOfTuplesView<
13430// Code::Kind, std::tuple<Smi, Function, Code>>;
13431//
13432// auto& array = Array::Handle(code.static_calls_targets_table());
13433// CallTableView static_calls(array);
13434//
13435// // Using convenient for loop.
13436// auto& function = Function::Handle();
13437// for (auto& call : static_calls) {
13438// function = call.Get<Code::kSCallTableFunctionTarget>();
13439// call.Set<Code::kSCallTableFunctionTarget>(function);
13440// }
13441//
13442// // Using manual loop.
13443// auto& function = Function::Handle();
13444// for (intptr_t i = 0; i < static_calls.Length(); ++i) {
13445// auto call = static_calls[i];
13446// function = call.Get<Code::kSCallTableFunctionTarget>();
13447// call.Set<Code::kSCallTableFunctionTarget>(function);
13448// }
13449//
13450//
13451// Template parameters:
13452//
13453// * [EnumType] must be a normal enum which enumerates the entries of the
13454// tuple
13455//
13456// * [kStartOffset] is the offset at which the first tuple in the array
13457// starts (can be 0).
13458//
13459// * [TupleT] must be a std::tuple<...> where "..." are the heap object handle
13460// classes (e.g. 'Code', 'Smi', 'Object')
13461template <typename EnumType, typename TupleT, int kStartOffset = 0>
13463 public:
13464 static constexpr intptr_t EntrySize = std::tuple_size<TupleT>::value;
13465
13466 class Iterator;
13467
13469 public:
13470 TupleView(const Array& array, intptr_t index)
13471 : array_(array), index_(index) {}
13472
13473 template <EnumType kElement,
13474 std::memory_order order = std::memory_order_relaxed>
13475 typename std::tuple_element<kElement, TupleT>::type::ObjectPtrType Get()
13476 const {
13477 using object_type = typename std::tuple_element<kElement, TupleT>::type;
13478 return object_type::RawCast(array_.At<order>(index_ + kElement));
13479 }
13480
13481 template <EnumType kElement,
13482 std::memory_order order = std::memory_order_relaxed>
13484 const {
13485 array_.SetAt<order>(index_ + kElement, value);
13486 }
13487
13488 intptr_t index() const { return (index_ - kStartOffset) / EntrySize; }
13489
13490 private:
13491 const Array& array_;
13492 intptr_t index_;
13493
13494 friend class Iterator;
13495 };
13496
13497 class Iterator {
13498 public:
13499 Iterator(const Array& array, intptr_t index) : entry_(array, index) {}
13500
13501 bool operator==(const Iterator& other) {
13502 return entry_.index_ == other.entry_.index_;
13503 }
13504 bool operator!=(const Iterator& other) {
13505 return entry_.index_ != other.entry_.index_;
13506 }
13507
13508 const TupleView& operator*() const { return entry_; }
13509
13511 entry_.index_ += EntrySize;
13512 return *this;
13513 }
13514
13515 private:
13516 TupleView entry_;
13517 };
13518
13519 explicit ArrayOfTuplesView(const Array& array) : array_(array) {
13520 ASSERT(!array.IsNull());
13521 ASSERT(array.Length() >= kStartOffset);
13522 ASSERT(array.Length() % EntrySize == kStartOffset);
13523 }
13524
13525 intptr_t Length() const {
13526 return (array_.Length() - kStartOffset) / EntrySize;
13527 }
13528
13529 TupleView At(intptr_t i) const {
13530 return TupleView(array_, kStartOffset + i * EntrySize);
13531 }
13532
13533 TupleView operator[](intptr_t i) const { return At(i); }
13534
13535 Iterator begin() const { return Iterator(array_, kStartOffset); }
13536
13537 Iterator end() const {
13538 return Iterator(array_, kStartOffset + Length() * EntrySize);
13539 }
13540
13541 private:
13542 const Array& array_;
13543};
13544
13547
13549
13551 std::tuple<Object,
13558 Bool>>;
13559
13562
13565 std::tuple<Object, TypeArguments, TypeArguments>,
13567
13568void DumpTypeTable(Isolate* isolate);
13569void DumpTypeParameterTable(Isolate* isolate);
13570void DumpTypeArgumentsTable(Isolate* isolate);
13571
13573 const Object& metadata_obj,
13574 const String& pragma_name,
13575 bool multiple = false,
13576 Object* options = nullptr);
13577
13579 const Array& metadata,
13580 Field* reusable_field_handle,
13581 Object* reusable_object_handle);
13582
13584ErrorPtr EntryPointFieldInvocationError(const String& getter_name);
13585
13587ErrorPtr EntryPointMemberInvocationError(const Object& member);
13588
13589#undef PRECOMPILER_WSR_FIELD_DECLARATION
13590
13591} // namespace dart
13592
13593#endif // RUNTIME_VM_OBJECT_H_
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static constexpr uint64_t kBits
Definition: DrawPass.cpp:54
static struct Initializer initializer
int count
Definition: FontMgrTest.cpp:50
static constexpr size_t kHeaderSize
@ kInvalid
static void operation(T operation, uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint8_t s, uint32_t t)
Definition: SkMD5.cpp:144
static void encode(uint8_t output[16], const uint32_t input[4])
Definition: SkMD5.cpp:240
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.
static uint32_t hash(const SkShaderBase::GradientInfo &v)
void Dump(const SkPath &path)
SI F table(const skcms_Curve *curve, F v)
static size_t element_size(Layout layout, SkSLType type)
#define UNREACHABLE()
Definition: assert.h:248
#define DEBUG_ASSERT(cond)
Definition: assert.h:321
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
GLenum type
#define CLASS_LIST(V)
Definition: class_id.h:208
bool IsNullableObjectType() const
Definition: object.h:9204
bool IsNonNullable() const
Definition: object.h:9071
UntaggedAbstractType::TypeState type_state() const
Definition: object.h:9351
bool IsMintType() const
Definition: object.h:9249
bool IsFinalized() const
Definition: object.h:9053
static intptr_t flags_offset()
Definition: object.h:9046
virtual bool HasTypeClass() const
Definition: object.h:9083
void SetHash(intptr_t value) const
Definition: object.h:13386
static intptr_t type_test_stub_entry_point_offset()
Definition: object.h:9297
bool IsSmiType() const
Definition: object.h:9246
bool IsVoidType() const
Definition: object.h:9189
static intptr_t NextFieldOffset()
Definition: object.h:9333
uword type_test_stub_entry_point() const
Definition: object.h:9301
Nullability nullability() const
Definition: object.h:9060
virtual bool Equals(const Instance &other) const
Definition: object.h:9094
static intptr_t InstanceSize()
Definition: object.h:9329
bool IsObjectType() const
Definition: object.h:9201
bool IsNumberType() const
Definition: object.h:9243
virtual uint32_t CanonicalizeHash() const
Definition: object.h:9093
bool IsCatchAllType() const
Definition: object.h:9276
bool IsFutureOrType() const
Definition: object.h:9267
CodePtr type_test_stub() const
Definition: object.h:9304
uword Hash() const
Definition: object.h:13377
HEAP_OBJECT_IMPLEMENTATION(AbstractType, Instance)
void UpdateTypeTestingStubEntryPoint() const
Definition: object.h:9322
bool IsNullable() const
Definition: object.h:9066
bool IsBoolType() const
Definition: object.h:9222
static intptr_t hash_offset()
Definition: object.h:9049
bool IsDynamicType() const
Definition: object.h:9186
virtual InstancePtr CanonicalizeLocked(Thread *thread) const
Definition: object.h:9138
virtual bool CanonicalizeEquals(const Instance &other) const
Definition: object.h:9090
StringPtr message() const
Definition: object.h:8059
static intptr_t InstanceSize()
Definition: object.h:8061
Iterator(const Array &array, intptr_t index)
Definition: object.h:13499
const TupleView & operator*() const
Definition: object.h:13508
bool operator==(const Iterator &other)
Definition: object.h:13501
bool operator!=(const Iterator &other)
Definition: object.h:13504
std::tuple_element< kElement, TupleT >::type::ObjectPtrType Get() const
Definition: object.h:13475
void Set(const typename std::tuple_element< kElement, TupleT >::type &value) const
Definition: object.h:13483
TupleView(const Array &array, intptr_t index)
Definition: object.h:13470
ArrayOfTuplesView(const Array &array)
Definition: object.h:13519
Iterator end() const
Definition: object.h:13537
intptr_t Length() const
Definition: object.h:13525
TupleView operator[](intptr_t i) const
Definition: object.h:13533
TupleView At(intptr_t i) const
Definition: object.h:13529
Iterator begin() const
Definition: object.h:13535
static intptr_t type_arguments_offset()
Definition: object.h:10928
static intptr_t InstanceSize()
Definition: object.h:10936
void SetAt(intptr_t index, const Object &value, Thread *thread) const
Definition: object.h:10885
static intptr_t index_at_offset(intptr_t offset_in_bytes)
Definition: object.h:10842
static CompressedObjectPtr * DataOf(ArrayPtr array)
Definition: object.h:10870
static bool Equals(ArrayPtr a, ArrayPtr b)
Definition: object.h:10854
ObjectPtr AtAcquire(intptr_t index) const
Definition: object.h:10891
static intptr_t element_offset(intptr_t index)
Definition: object.h:10838
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.h:10959
static constexpr intptr_t InstanceSize(intptr_t len)
Definition: object.h:10949
void SetAtRelease(intptr_t index, const Object &value) const
Definition: object.h:10895
virtual TypeArgumentsPtr GetTypeArguments() const
Definition: object.h:10905
static constexpr bool UseCardMarkingForAllocation(const intptr_t array_length)
Definition: object.h:10818
static constexpr bool IsValidLength(intptr_t len)
Definition: object.h:10932
bool IsImmutable() const
Definition: object.h:10900
virtual void SetTypeArguments(const TypeArguments &value) const
Definition: object.h:10908
static intptr_t LengthOf(const ArrayPtr array)
Definition: object.h:10830
ObjectPtr At(intptr_t index) const
Definition: object.h:10875
intptr_t Length() const
Definition: object.h:10829
static ArrayPtr NewUninitialized(intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.h:10964
ArrayPtr Copy() const
Definition: object.h:10997
static constexpr intptr_t UnroundedSize(intptr_t len)
Definition: object.h:10942
static intptr_t data_offset()
Definition: object.h:10835
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:10880
static intptr_t length_offset()
Definition: object.h:10834
bool Equals(const Array &other) const
Definition: object.h:10865
static constexpr T decode(S value)
Definition: bitfield.h:171
static constexpr bool is_valid(ClassIdTagType value)
Definition: bitfield.h:146
static intptr_t InstanceSize()
Definition: object.h:10793
virtual uint32_t CanonicalizeHash() const
Definition: object.h:10805
static const Bool & False()
Definition: object.h:10799
static const Bool & Get(bool value)
Definition: object.h:10801
static const Bool & True()
Definition: object.h:10797
bool value() const
Definition: object.h:10791
static InstancePtr Data(const Instance &view_obj)
Definition: object.h:11863
static constexpr bool ContainsCompressedPointers()
Definition: object.h:11859
static intptr_t NumberOfFields()
Definition: object.h:11870
static intptr_t data_offset()
Definition: object.h:11872
intptr_t CountWithTypeArgs() const
Definition: object.cc:16485
intptr_t CountWithoutTypeArgs() const
Definition: object.cc:16490
static intptr_t target_name_offset()
Definition: object.h:2385
intptr_t SizeWithoutTypeArgs() const
Definition: object.cc:16495
StringPtr target_name() const
Definition: object.h:2372
friend class ICData
Definition: object.h:2399
intptr_t SizeWithTypeArgs() const
Definition: object.cc:16500
static intptr_t arguments_descriptor_offset()
Definition: object.h:2389
intptr_t TypeArgsLen() const
Definition: object.cc:16480
ArrayPtr arguments_descriptor() const
Definition: object.h:2373
static intptr_t InstanceSize()
Definition: object.h:12419
uint64_t Id() const
Definition: object.h:12417
void Register(const Class &cls)
Definition: class_table.cc:65
ClassPtr At(intptr_t cid) const
Definition: class_table.h:362
static intptr_t target_instance_size(ClassPtr clazz)
Definition: object.h:1159
void PatchFieldsAndFunctions() const
void CopyDeclarationType(const Class &old_cls) const
void AddFields(const GrowableArray< const Field * > &fields) const
Definition: object.cc:5013
static intptr_t id_offset()
Definition: object.h:1238
bool has_dynamically_extendable_subtypes() const
Definition: object.h:2196
TypeArgumentsPtr DefaultTypeArguments(Zone *zone) const
Definition: object.cc:3658
void AddFunction(const Function &function) const
Definition: object.cc:3296
void set_is_implemented_unsafe() const
Definition: object.cc:5618
bool is_sealed() const
Definition: object.h:1759
void set_num_type_arguments(intptr_t value) const
Definition: object.cc:3109
void set_is_transformed_mixin_application() const
Definition: object.cc:5665
bool is_base_class() const
Definition: object.h:1765
static intptr_t host_instance_size(ClassPtr clazz)
Definition: object.h:1156
void set_is_implemented() const
Definition: object.cc:5613
FieldPtr LookupInstanceField(const String &name) const
Definition: object.cc:6344
intptr_t kernel_offset() const
Definition: object.h:1804
void set_has_pragma(bool value) const
Definition: object.cc:3129
const char * NameCString(NameVisibility name_visibility) const
Definition: object.cc:3006
void set_is_finalized_unsafe() const
Definition: object.cc:5720
intptr_t FindImplicitClosureFunctionIndex(const Function &needle) const
Definition: object.cc:3364
intptr_t NumTypeParameters() const
Definition: object.h:1344
const char * ScrubbedNameCString() const
Definition: object.cc:2985
FunctionPtr LookupFunctionAllowPrivate(const String &name) const
Definition: object.cc:6167
ObjectPtr InvokeSetter(const String &selector, const Instance &argument, bool respect_reflectable=true, bool check_is_entrypoint=false) const
Definition: object.cc:4577
CodePtr allocation_stub() const
Definition: object.h:1800
void set_is_deeply_immutable(bool value) const
Definition: object.cc:3144
FunctionPtr LookupDynamicFunctionAllowPrivate(const String &name) const
Definition: object.cc:6133
void set_instance_size(intptr_t host_value_in_bytes, intptr_t target_value_in_bytes) const
Definition: object.h:1167
LibraryPtr library() const
Definition: object.h:1333
void set_is_isolate_unsendable_due_to_pragma(bool value) const
Definition: object.cc:3138
void set_super_type(const Type &value) const
Definition: object.cc:3684
bool TraceAllocation(IsolateGroup *isolate_group) const
Definition: object.cc:4434
FunctionPtr InvocationDispatcherFunctionFromIndex(intptr_t idx) const
Definition: object.cc:3419
void set_is_allocate_finalized() const
Definition: object.cc:5725
FunctionPtr LookupConstructorAllowPrivate(const String &name) const
Definition: object.cc:6153
static ClassPtr NewTypedDataViewClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition: object.cc:5278
void set_is_enum_class() const
Definition: object.cc:5655
void set_is_synthesized_class() const
Definition: object.cc:5646
ObjectPtr Invoke(const String &selector, const Array &arguments, const Array &argument_names, bool respect_reflectable=true, bool check_is_entrypoint=false) const
Definition: object.cc:4684
FunctionPtr LookupGetterFunction(const String &name) const
Definition: object.cc:6308
void CopyCanonicalConstants(const Class &old_cls) const
void Finalize() const
Definition: object.cc:4307
static uint16_t NumNativeFieldsOf(ClassPtr clazz)
Definition: object.h:1792
static int32_t target_next_field_offset_in_words(const ClassPtr cls)
Definition: object.h:1959
static int32_t host_next_field_offset_in_words(const ClassPtr cls)
Definition: object.h:1955
bool IsRecordClass() const
Definition: object.h:1583
bool IsInFullSnapshot() const
Definition: object.cc:3030
ObjectPtr InvokeGetter(const String &selector, bool throw_nsm_if_absent, bool respect_reflectable=true, bool check_is_entrypoint=false) const
Definition: object.cc:4517
FieldPtr LookupInstanceFieldAllowPrivate(const String &name) const
Definition: object.cc:6434
void set_is_allocated_unsafe(bool value) const
Definition: object.cc:5705
bool can_be_future() const
Definition: object.h:2188
void AddDirectImplementor(const Class &subclass, bool is_mixin) const
Definition: object.cc:5746
TypePtr GetInstantiationOf(Zone *zone, const Class &cls) const
Definition: object.cc:12728
bool is_declaration_loaded() const
Definition: object.h:1703
intptr_t target_type_arguments_field_offset() const
Definition: object.h:1384
uint32_t Hash() const
Definition: object.cc:5597
static intptr_t super_type_offset()
Definition: object.h:1436
void SetFields(const Array &value) const
Definition: object.cc:4984
void set_is_prefinalized() const
Definition: object.cc:5732
bool is_const() const
Definition: object.h:1745
void set_is_interface_class() const
Definition: object.cc:5685
bool IsDartFunctionClass() const
Definition: object.cc:5903
void set_next_field_offset_in_words(intptr_t host_value, intptr_t target_value) const
Definition: object.h:1207
StringPtr ScrubbedName() const
Definition: object.cc:2981
static intptr_t InstanceSize()
Definition: object.h:1685
GrowableObjectArrayPtr direct_subclasses() const
Definition: object.h:1537
GrowableObjectArrayPtr direct_implementors_unsafe() const
Definition: object.h:1525
bool is_mixin_class() const
Definition: object.h:1762
TypeArgumentsPtr GetDeclarationInstanceTypeArguments() const
Definition: object.cc:3476
TypePtr super_type() const
Definition: object.h:1431
FunctionPtr GetInvocationDispatcher(const String &target_name, const Array &args_desc, UntaggedFunction::Kind kind, bool create_if_absent) const
Definition: object.cc:3847
intptr_t host_next_field_offset() const
Definition: object.h:1190
FunctionPtr LookupStaticFunction(const String &name) const
Definition: object.cc:6137
intptr_t id() const
Definition: object.h:1233
static intptr_t UnboxedFieldSizeInBytesByCid(intptr_t cid)
Definition: object.cc:3702
void set_is_declaration_loaded() const
Definition: object.cc:5627
bool is_final() const
Definition: object.h:1773
static ClassPtr NewExternalTypedDataClass(intptr_t class_id, IsolateGroup *isolate)
Definition: object.cc:5318
void set_num_type_arguments_unsafe(intptr_t value) const
Definition: object.cc:3125
intptr_t target_instance_size() const
Definition: object.h:1147
void set_is_fields_marked_nullable() const
Definition: object.cc:5695
intptr_t NumTypeArguments() const
Definition: object.cc:3640
void set_is_abstract() const
Definition: object.cc:5622
static intptr_t host_type_arguments_field_offset_in_words_offset()
Definition: object.h:1426
void set_is_mixin_class() const
Definition: object.cc:5675
FunctionPtr LookupConstructor(const String &name) const
Definition: object.cc:6147
void set_type_arguments_field_offset_in_words(intptr_t host_value, intptr_t target_value) const
Definition: object.h:1414
void set_num_native_fields(uint16_t value) const
Definition: object.h:1789
static ClassPtr NewTypedDataClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition: object.cc:5259
void set_type_arguments_field_offset(intptr_t host_value_in_bytes, intptr_t target_value_in_bytes) const
Definition: object.h:1397
WeakArrayPtr dependent_code() const
Definition: object.cc:4420
static bool is_valid_id(intptr_t value)
Definition: object.h:1230
void set_dependent_code(const WeakArray &array) const
Definition: object.cc:4426
intptr_t target_next_field_offset() const
Definition: object.h:1193
static int32_t host_type_arguments_field_offset_in_words(const ClassPtr cls)
Definition: object.h:1967
bool is_isolate_unsendable() const
Definition: object.h:2163
ObjectPtr EvaluateCompiledExpression(const ExternalTypedData &kernel_buffer, const Array &type_definitions, const Array &param_values, const TypeArguments &type_param_values) const
Definition: object.cc:4821
FunctionPtr LookupSetterFunction(const String &name) const
Definition: object.cc:6312
bool is_loaded() const
Definition: object.h:1785
bool IsPrivate() const
Definition: object.cc:6125
FunctionPtr GetRecordFieldGetter(const String &getter_name) const
Definition: object.cc:4078
void set_is_sealed() const
Definition: object.cc:5670
TypePtr RareType() const
Definition: object.cc:3036
void set_direct_subclasses(const GrowableObjectArray &subclasses) const
Definition: object.cc:5799
static intptr_t declaration_type_offset()
Definition: object.h:1315
intptr_t host_type_arguments_field_offset() const
Definition: object.h:1375
static bool IsIsolateUnsendable(ClassPtr clazz)
Definition: object.h:1795
ArrayPtr interfaces() const
Definition: object.h:1447
bool IsObjectClass() const
Definition: object.h:1565
bool InjectCIDFields() const
Definition: object.cc:5059
void set_interfaces(const Array &value) const
Definition: object.cc:5739
bool is_type_finalized() const
Definition: object.h:1709
void SetUserVisibleNameInClassTable()
Definition: object.cc:5383
static int32_t target_type_arguments_field_offset_in_words(const ClassPtr cls)
Definition: object.h:1971
InstancePtr InsertCanonicalConstant(Zone *zone, const Instance &constant) const
Definition: object.cc:6485
void set_script(const Script &value) const
Definition: object.cc:5555
ArrayPtr fields() const
Definition: object.h:1615
bool is_deeply_immutable() const
Definition: object.h:2174
static bool IsSubtypeOf(const Class &cls, const TypeArguments &type_arguments, Nullability nullability, const AbstractType &other, Heap::Space space, FunctionTypeMapping *function_type_equivalence=nullptr)
Definition: object.cc:5920
void DisableAllocationStub() const
Definition: object.cc:5879
void SetTraceAllocation(bool trace_allocation) const
Definition: object.cc:4443
ArrayPtr constants() const
Definition: object.cc:5806
bool HasInstanceFields() const
Definition: object.cc:3211
void set_is_future_subtype(bool value) const
Definition: object.cc:3149
void set_is_declaration_loaded_unsafe() const
Definition: object.cc:5632
InstancePtr LookupCanonicalInstance(Zone *zone, const Instance &value) const
Definition: object.cc:6472
uint16_t num_native_fields() const
Definition: object.h:1788
void MigrateImplicitStaticClosures(ProgramReloadContext *context, const Class &new_cls) const
intptr_t implementor_cid() const
Definition: object.h:1245
void set_is_finalized() const
Definition: object.cc:5714
ArrayPtr OffsetToFieldMap(ClassTable *class_table=nullptr) const
Definition: object.cc:3183
intptr_t host_instance_size() const
Definition: object.h:1143
static bool IsDeeplyImmutable(ClassPtr clazz)
Definition: object.h:2177
void DisableAllCHAOptimizedCode()
Definition: object.cc:4416
FunctionPtr LookupFunctionReadLocked(const String &name) const
Definition: object.cc:6171
void AddField(const Field &field) const
Definition: object.cc:5002
void DisableCHAOptimizedCode(const Class &subclass)
Definition: object.cc:4402
bool HasCompressedPointers() const
Definition: object.cc:2946
static intptr_t num_type_arguments_offset()
Definition: object.h:1252
void set_is_allocated(bool value) const
Definition: object.cc:5700
void set_allocation_stub(const Code &value) const
Definition: object.cc:5870
int32_t SourceFingerprint() const
Definition: object.cc:5604
static int32_t host_instance_size_in_words(const ClassPtr cls)
Definition: object.h:1943
FunctionPtr LookupDynamicFunctionUnsafe(const String &name) const
Definition: object.cc:6129
bool is_abstract() const
Definition: object.h:1696
bool IsDynamicClass() const
Definition: object.h:1556
bool IsGeneric() const
Definition: object.h:1358
bool IsClosureClass() const
Definition: object.h:1577
StringPtr Name() const
Definition: object.cc:2977
InvocationDispatcherEntry
Definition: object.h:1135
@ kInvocationDispatcherArgsDesc
Definition: object.h:1137
@ kInvocationDispatcherName
Definition: object.h:1136
@ kInvocationDispatcherFunction
Definition: object.h:1138
@ kInvocationDispatcherEntrySize
Definition: object.h:1139
static bool IsInFullSnapshot(ClassPtr cls)
Definition: object.h:1585
static constexpr intptr_t kNoTypeArguments
Definition: object.h:1374
FunctionPtr LookupStaticFunctionAllowPrivate(const String &name) const
Definition: object.cc:6143
void set_token_pos(TokenPosition value) const
Definition: object.cc:5565
TypePtr DeclarationType() const
Definition: object.cc:5827
FieldPtr LookupStaticFieldAllowPrivate(const String &name) const
Definition: object.cc:6442
bool is_dynamically_extendable() const
Definition: object.h:2191
FunctionPtr LookupFactory(const String &name) const
Definition: object.cc:6157
TokenPosition token_pos() const
Definition: object.h:1279
void set_instance_size_in_words(intptr_t host_value, intptr_t target_value) const
Definition: object.h:1174
ErrorPtr EnsureIsFinalized(Thread *thread) const
Definition: object.cc:4924
bool IsVoidClass() const
Definition: object.h:1559
void set_is_synthesized_class_unsafe() const
Definition: object.cc:5651
bool FindInstantiationOf(Zone *zone, const Class &cls, GrowableArray< const Type * > *path, bool consider_only_super_classes=false) const
Definition: object.cc:12675
void set_is_base_class() const
Definition: object.cc:5680
static ClassPtr New(IsolateGroup *isolate_group, bool register_class=true)
Definition: object.cc:3053
bool is_prefinalized() const
Definition: object.h:1738
void RegisterCHACode(const Code &code)
Definition: object.cc:4390
bool IsFutureClass() const
Definition: object.cc:5907
GrowableObjectArrayPtr direct_subclasses_unsafe() const
Definition: object.h:1542
KernelProgramInfoPtr KernelProgramInfo() const
Definition: object.cc:5560
TokenPosition end_token_pos() const
Definition: object.h:1291
bool is_future_subtype() const
Definition: object.h:2182
FieldPtr LookupField(const String &name) const
Definition: object.cc:6352
friend class Intrinsifier
Definition: object.h:2241
void CopyStaticFieldValues(ProgramReloadContext *reload_context, const Class &old_cls) const
void set_kernel_offset(intptr_t value) const
Definition: object.h:1812
void set_library(const Library &value) const
Definition: object.cc:3438
void set_end_token_pos(TokenPosition value) const
Definition: object.cc:5570
ErrorPtr EnsureIsAllocateFinalized(Thread *thread) const
Definition: object.cc:4954
void DisableCHAImplementorUsers()
Definition: object.h:1917
bool is_fields_marked_nullable() const
Definition: object.h:1776
FunctionPtr LookupFactoryAllowPrivate(const String &name) const
Definition: object.cc:6163
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
Definition: object.cc:3665
void set_is_loaded(bool value) const
Definition: object.cc:5709
static ClassPtr NewStringClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition: object.cc:5232
void set_constants(const Array &value) const
Definition: object.cc:5810
intptr_t FindFieldIndex(const Field &needle) const
Definition: object.cc:5030
StringPtr UserVisibleName() const
Definition: object.cc:2989
void AddInvocationDispatcher(const String &target_name, const Array &args_desc, const Function &dispatcher) const
Definition: object.cc:3831
bool FindInstantiationOf(Zone *zone, const Class &cls, bool consider_only_super_classes=false) const
Definition: object.h:1468
void AddDirectSubclass(const Class &subclass) const
Definition: object.cc:5778
void set_id(intptr_t value) const
Definition: object.h:1234
bool FindInstantiationOf(Zone *zone, const Type &type, bool consider_only_super_classes=false) const
Definition: object.h:1491
bool IsTopLevel() const
Definition: object.cc:6121
static intptr_t GetClassId(ClassPtr cls)
Definition: object.h:1591
FieldPtr FieldFromIndex(intptr_t idx) const
Definition: object.cc:5051
static int32_t target_instance_size_in_words(const ClassPtr cls)
Definition: object.h:1947
bool is_enum_class() const
Definition: object.h:1720
bool IsNeverClass() const
Definition: object.h:1562
void set_has_dynamically_extendable_subtypes(bool value) const
Definition: object.cc:3164
bool NoteImplementor(const Class &implementor) const
Definition: object.cc:5580
TypeParametersPtr type_parameters() const
Definition: object.h:1338
bool IsNullClass() const
Definition: object.h:1553
void set_is_type_finalized() const
Definition: object.cc:5638
const char * UserVisibleNameCString() const
Definition: object.cc:2998
void MarkFieldBoxedDuringReload(ClassTable *class_table, const Field &field) const
void set_is_final() const
Definition: object.cc:5690
GrowableObjectArrayPtr direct_implementors() const
Definition: object.h:1520
intptr_t FindFunctionIndex(const Function &needle) const
Definition: object.cc:3321
bool is_implemented() const
Definition: object.h:1692
TypeParameterPtr TypeParameterAt(intptr_t index, Nullability nullability=Nullability::kNonNullable) const
Definition: object.cc:3689
static ClassPtr NewPointerClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition: object.cc:5338
void set_next_field_offset(intptr_t host_value_in_bytes, intptr_t target_value_in_bytes) const
Definition: object.h:1201
bool has_pragma() const
Definition: object.h:2159
void set_is_const() const
Definition: object.cc:5660
bool is_allocate_finalized() const
Definition: object.h:1732
bool is_transformed_mixin_application() const
Definition: object.h:1754
FunctionPtr ImplicitClosureFunctionFromIndex(intptr_t idx) const
Definition: object.cc:3354
FunctionPtr FunctionFromIndex(intptr_t idx) const
Definition: object.cc:3343
bool IsFutureOrClass() const
Definition: object.h:1574
UntaggedClass::ClassLoadingState class_loading_state() const
Definition: object.h:1699
bool is_allocated() const
Definition: object.h:1781
static ClassPtr NewNativeWrapper(const Library &library, const String &name, int num_fields)
Definition: object.cc:5189
void SetFunctions(const Array &value) const
Definition: object.cc:3264
void set_type_parameters(const TypeParameters &value) const
Definition: object.cc:3442
bool is_synthesized_class() const
Definition: object.h:1714
static ClassPtr NewUnmodifiableTypedDataViewClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition: object.cc:5298
DART_WARN_UNUSED_RESULT ErrorPtr VerifyEntryPoint() const
Definition: object.cc:27370
void CheckReload(const Class &replacement, ProgramReloadContext *context) const
FieldPtr LookupFieldAllowPrivate(const String &name, bool instance_only=false) const
Definition: object.cc:6403
ClassPtr Mixin() const
Definition: object.cc:3020
bool is_isolate_unsendable_due_to_pragma() const
Definition: object.h:2169
bool is_interface_class() const
Definition: object.h:1768
void set_direct_implementors(const GrowableObjectArray &implementors) const
Definition: object.cc:5772
intptr_t FindInvocationDispatcherFunctionIndex(const Function &needle) const
Definition: object.cc:3392
static bool IsClosureClass(ClassPtr cls)
Definition: object.h:1578
bool is_finalized() const
Definition: object.h:1723
ArrayPtr current_functions() const
Definition: object.h:1641
ArrayPtr functions() const
Definition: object.h:1646
FieldPtr LookupStaticField(const String &name) const
Definition: object.cc:6348
ScriptPtr script() const
Definition: object.h:1272
void EnsureDeclarationLoaded() const
Definition: object.cc:4913
virtual StringPtr DictionaryName() const
Definition: object.h:1270
TypeArgumentsPtr GetInstanceTypeArguments(Thread *thread, const TypeArguments &type_arguments, bool canonicalize=true) const
Definition: object.cc:3524
void set_is_isolate_unsendable(bool value) const
Definition: object.cc:3133
void set_is_dynamically_extendable(bool value) const
Definition: object.cc:3159
void set_can_be_future(bool value) const
Definition: object.cc:3154
static intptr_t packed_fields_offset()
Definition: object.h:4320
static intptr_t InstanceSize()
Definition: object.h:4316
ObjectPtr RawContext() const
Definition: object.h:12358
ContextPtr GetContext() const
Definition: object.h:12360
static intptr_t delayed_type_arguments_offset()
Definition: object.h:12346
static intptr_t function_offset()
Definition: object.h:12351
virtual uint32_t CanonicalizeHash() const
Definition: object.h:12389
void set_delayed_type_arguments(const TypeArguments &args) const
Definition: object.h:12343
SmiPtr hash() const
Definition: object.h:12380
static intptr_t instantiator_type_arguments_offset()
Definition: object.h:12326
bool IsGeneric() const
Definition: object.h:12376
static intptr_t function_type_arguments_offset()
Definition: object.h:12336
TypeArgumentsPtr instantiator_type_arguments() const
Definition: object.h:12320
TypeArgumentsPtr delayed_type_arguments() const
Definition: object.h:12340
TypeArgumentsPtr function_type_arguments() const
Definition: object.h:12330
static intptr_t hash_offset()
Definition: object.h:12381
void set_function_type_arguments(const TypeArguments &args) const
Definition: object.h:12333
static intptr_t InstanceSize()
Definition: object.h:12383
InstancePtr GetImplicitClosureReceiver() const
Definition: object.h:12365
static FunctionPtr FunctionOf(ClosurePtr closure)
Definition: object.h:12354
FunctionPtr function() const
Definition: object.h:12350
void set_instantiator_type_arguments(const TypeArguments &args) const
Definition: object.h:12323
static intptr_t context_offset()
Definition: object.h:12370
static intptr_t InstanceSize()
Definition: object.h:6229
static intptr_t HeaderSize()
Definition: object.h:6224
void PrintToJSONObject(JSONObject *jsobj, bool ref) const
uint8_t * Data() const
Definition: object.h:6242
uint32_t Hash() const
Definition: object.h:6252
intptr_t Length() const
Definition: object.h:6241
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:6234
static intptr_t UnroundedSize(CodeSourceMapPtr map)
Definition: object.h:6225
static intptr_t UnroundedSize(intptr_t len)
Definition: object.h:6228
bool Equals(const CodeSourceMap &other) const
Definition: object.h:6244
static intptr_t instructions_offset()
Definition: object.h:6779
void set_exception_handlers(const ExceptionHandlers &handlers) const
Definition: object.h:7119
FunctionPtr function() const
Definition: object.h:7130
uword EntryPoint() const
Definition: object.h:6864
void GetInlinedFunctionsAtReturnAddress(intptr_t pc_offset, GrowableArray< const Function * > *functions, GrowableArray< TokenPosition > *token_positions) const
Definition: object.h:7085
LocalVarDescriptorsPtr var_descriptors() const
Definition: object.h:7096
void Enable() const
Definition: object.h:7252
uword UncheckedEntryPoint() const
Definition: object.h:6878
ArrayPtr deopt_info_array() const
Definition: object.h:6943
void set_code_source_map(const CodeSourceMap &code_source_map) const
Definition: object.h:6937
uword Size() const
Definition: object.h:6903
static uword PayloadSizeOf(const CodePtr code)
Definition: object.h:6904
static bool IsDisabled(CodePtr code)
Definition: object.h:7258
static intptr_t owner_offset()
Definition: object.h:7149
NOT_IN_PRODUCT(void PrintJSONInlineIntervals(JSONObject *object) const)
void set_pc_descriptors(const PcDescriptors &descriptors) const
Definition: object.h:6928
int32_t GetPointerOffsetAt(int index) const
Definition: object.h:7215
bool is_alive() const
Definition: object.h:6830
PcDescriptorsPtr pc_descriptors() const
Definition: object.h:6927
bool is_optimized() const
Definition: object.h:6817
classid_t OwnerClassId() const
Definition: object.h:7140
CodeSourceMapPtr code_source_map() const
Definition: object.h:6933
static uword EntryPointOf(const CodePtr code)
Definition: object.h:6865
bool is_force_optimized() const
Definition: object.h:6825
static bool ContainsInstructionAt(const CodePtr code, uword pc)
Definition: object.h:6920
ObjectPoolPtr object_pool() const
Definition: object.h:6808
static intptr_t InstanceSize()
Definition: object.h:7163
static uword UncheckedEntryPointOf(const CodePtr code)
Definition: object.h:6873
void set_var_descriptors(const LocalVarDescriptors &value) const
Definition: object.h:7104
static intptr_t active_instructions_offset()
Definition: object.h:6783
static InstructionsPtr InstructionsOf(const CodePtr code)
Definition: object.h:6775
bool ContainsInstructionAt(uword addr) const
Definition: object.h:6915
bool IsDisabled() const
Definition: object.h:7257
static uword PayloadStartOf(const CodePtr code)
Definition: object.h:6851
uword MonomorphicUncheckedEntryPoint() const
Definition: object.h:6894
bool HasMonomorphicEntry() const
Definition: object.h:6839
PoolAttachment
Definition: object.h:6987
ObjectPtr owner() const
Definition: object.h:7135
ArrayPtr static_calls_target_table() const
Definition: object.h:6999
static bool IsDiscarded(const CodePtr code)
Definition: object.h:6834
uword MonomorphicEntryPoint() const
Definition: object.h:6886
void set_object_pool(ObjectPoolPtr object_pool) const
Definition: object.h:7268
static intptr_t entry_point_offset(EntryKind kind=EntryKind::kNormal)
Definition: object.h:6793
SCallTableEntry
Definition: object.h:6980
static intptr_t object_pool_offset()
Definition: object.h:6809
static bool IsOptimized(CodePtr code)
Definition: object.h:6821
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:7168
intptr_t pointer_offsets_length() const
Definition: object.h:6813
static classid_t OwnerClassIdOf(CodePtr raw)
Definition: object.h:7141
InstructionsPtr active_instructions() const
Definition: object.h:6764
ObjectPtr return_address_metadata() const
Definition: object.h:7055
CompressedStackMapsPtr compressed_stackmaps() const
Definition: object.h:6963
bool IsUnknownDartCode() const
Definition: object.h:7245
bool is_discarded() const
Definition: object.h:6833
CallEntryPoint
Definition: object.h:6975
@ kDefaultEntry
Definition: object.h:6976
@ kUncheckedEntry
Definition: object.h:6977
InstructionsPtr instructions() const
Definition: object.h:6774
uword PayloadStart() const
Definition: object.h:6850
ExceptionHandlersPtr exception_handlers() const
Definition: object.h:7116
static bool HasMonomorphicEntry(const CodePtr code)
Definition: object.h:6840
int64_t compile_timestamp() const
Definition: object.h:7230
Iterator(const Iterator &it)
Definition: object.h:6393
bool Find(uint32_t pc_offset)
Definition: object.h:6457
Iterator(const PayloadHandle &maps, const PayloadHandle &global_table)
Definition: object.h:6384
bool IsObject(intptr_t bit_index) const
Definition: object.h:6488
intptr_t SpillSlotBitCount() const
Definition: object.h:6482
RawPayloadHandle(const RawPayloadHandle &)=default
RawPayloadHandle & operator=(const CompressedStackMaps &maps)
Definition: object.h:6349
RawPayloadHandle & operator=(CompressedStackMapsPtr maps)
Definition: object.h:6355
const UntaggedCompressedStackMaps::Payload * payload() const
Definition: object.h:6338
RawPayloadHandle & operator=(const RawPayloadHandle &)=default
RawPayloadHandle & operator=(const UntaggedCompressedStackMaps::Payload *payload)
Definition: object.h:6343
bool IsGlobalTable() const
Definition: object.h:6310
const uint8_t * data() const
Definition: object.h:6275
static intptr_t UnroundedSize(intptr_t length)
Definition: object.h:6296
bool Equals(const CompressedStackMaps &other) const
Definition: object.h:6278
static bool IsGlobalTable(const CompressedStackMapsPtr raw)
Definition: object.h:6311
static CompressedStackMapsPtr NewUsingTable(const void *payload, intptr_t size)
Definition: object.h:6320
static CompressedStackMapsPtr NewInlined(const void *payload, intptr_t size)
Definition: object.h:6316
static CompressedStackMapsPtr NewGlobalTable(const void *payload, intptr_t size)
Definition: object.h:6326
static intptr_t HeaderSize()
Definition: object.h:6289
static intptr_t InstanceSize()
Definition: object.h:6299
uintptr_t payload_size() const
Definition: object.h:6269
bool UsesGlobalTable() const
Definition: object.h:6304
static intptr_t UnroundedSize(CompressedStackMapsPtr maps)
Definition: object.h:6293
static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw)
Definition: object.h:6270
static intptr_t InstanceSize(intptr_t length)
Definition: object.h:6300
static bool UsesGlobalTable(const CompressedStackMapsPtr raw)
Definition: object.h:6305
static intptr_t InstanceSize()
Definition: object.h:12192
static constexpr bool ContainsCompressedPointers()
Definition: object.h:12182
static intptr_t InstanceSize()
Definition: object.h:12293
static constexpr bool ContainsCompressedPointers()
Definition: object.h:12283
static intptr_t InstanceSize()
Definition: object.h:7535
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:7541
intptr_t num_variables() const
Definition: object.h:7484
static intptr_t NumVariables(const ContextPtr context)
Definition: object.h:7418
static intptr_t num_variables_offset()
Definition: object.h:7415
static bool IsValidLength(intptr_t len)
Definition: object.h:7444
static intptr_t variable_offset(intptr_t context_index)
Definition: object.h:7439
static intptr_t parent_offset()
Definition: object.h:7410
void set_parent(const Context &parent) const
Definition: object.h:7407
void SetAt(intptr_t context_index, const Object &value) const
Definition: object.h:13303
static intptr_t InstanceSize()
Definition: object.h:7448
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:7454
ObjectPtr At(intptr_t context_index) const
Definition: object.h:7422
intptr_t num_variables() const
Definition: object.h:7414
ContextPtr parent() const
Definition: object.h:7406
static uword AllocateReadOnlyHandle()
Definition: dart.cc:1131
bool HasNext() const
Definition: object.h:5049
static intptr_t value_offset()
Definition: object.h:10139
static intptr_t InstanceSize()
Definition: object.h:10135
double value() const
Definition: object.h:10115
static double Value(DoublePtr dbl)
Definition: object.h:10116
bool IsClosed() const
Definition: object.h:11955
void SetClosed(bool value) const
Definition: object.h:11960
static bool IsDynamicLibrary(const Instance &obj)
Definition: object.h:11930
void * GetHandle() const
Definition: object.h:11936
bool CanBeClosed() const
Definition: object.h:11945
static intptr_t InstanceSize()
Definition: object.h:11926
void SetCanBeClosed(bool value) const
Definition: object.h:11950
void SetHandle(void *value) const
Definition: object.h:11941
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:6611
static intptr_t InstanceSize()
Definition: object.h:6606
static intptr_t InstanceSize()
Definition: object.h:11740
virtual uint8_t * Validate(uint8_t *data) const
Definition: object.h:11765
void SetData(uint8_t *data) const
Definition: object.h:11772
void SetLength(intptr_t value) const
Definition: object.h:11767
static bool IsExternalTypedData(const Instance &obj)
Definition: object.h:11758
static intptr_t MaxElements(intptr_t class_id)
Definition: object.h:11744
static intptr_t InstanceSize()
Definition: object.h:4376
ObjectPtr At(intptr_t index, bool concurrent_use=false) const
Definition: field_table.h:62
bool is_final() const
Definition: object.h:4442
uint16_t kind_bits() const
Definition: object.h:4435
FunctionPtr InitializerFunction() const
Definition: object.h:4804
bool has_initializer() const
Definition: object.h:4613
intptr_t kernel_offset() const
Definition: object.h:4495
void set_has_nontrivial_initializer_unsafe(bool has_nontrivial_initializer) const
Definition: object.h:4600
bool is_unboxed() const
Definition: object.h:4712
void set_is_reflectable(bool value) const
Definition: object.h:4455
static intptr_t guarded_cid_offset()
Definition: object.h:4669
static intptr_t static_type_exactness_state_offset()
Definition: object.h:4651
void set_is_nullable_unsafe(bool val) const
Definition: object.h:4762
void set_is_late(bool value) const
Definition: object.h:4731
bool IsOriginal() const
Definition: object.h:4418
bool NeedsInitializationCheckOnLoad() const
Definition: object.h:4706
bool has_pragma() const
Definition: object.h:4470
static intptr_t kind_bits_offset()
Definition: object.h:4585
void set_is_unboxed(bool b) const
Definition: object.h:4720
bool is_reflectable() const
Definition: object.h:4454
void set_is_extension_type_member(bool value) const
Definition: object.h:4739
void set_has_initializer(bool has_initializer) const
Definition: object.h:4623
@ kUnknownFixedLength
Definition: object.h:4728
bool needs_length_check() const
Definition: object.h:4697
intptr_t TargetOffset() const
Definition: object.h:13246
bool is_late() const
Definition: object.h:4444
void set_static_type_exactness_state(StaticTypeExactnessState state) const
Definition: object.h:4639
void set_is_shared(bool value) const
Definition: object.h:4490
static intptr_t guarded_list_length_in_object_offset_offset()
Definition: object.h:4693
void set_is_generic_covariant_impl(bool value) const
Definition: object.h:4485
bool is_static() const
Definition: object.h:4440
StaticTypeExactnessState static_type_exactness_state() const
Definition: object.h:4633
bool is_extension_member() const
Definition: object.h:4445
static intptr_t host_offset_or_field_id_offset()
Definition: object.h:4523
static intptr_t InstanceSize()
Definition: object.h:4558
void SetOffset(intptr_t host_offset_in_bytes, intptr_t target_offset_in_bytes) const
Definition: object.h:13263
void set_initializer_changed_after_initialization(bool value) const
Definition: object.h:4464
void set_is_extension_member(bool value) const
Definition: object.h:4735
StringPtr name() const
Definition: object.h:4430
void set_has_pragma(bool value) const
Definition: object.h:4471
void set_guarded_cid(intptr_t cid) const
Definition: object.h:4660
void set_guarded_list_length_in_object_offset(intptr_t offset) const
Definition: object.h:4688
ObjectPtr StaticValue() const
Definition: object.h:13279
bool needs_load_guard() const
Definition: object.h:4451
bool has_trivial_initializer() const
Definition: object.h:4629
bool is_covariant() const
Definition: object.h:4476
void set_needs_load_guard(bool value) const
Definition: object.h:4743
void set_has_initializer_unsafe(bool has_initializer) const
Definition: object.h:4617
void set_is_covariant(bool value) const
Definition: object.h:4477
bool is_generic_covariant_impl() const
Definition: object.h:4482
void set_has_nontrivial_initializer(bool has_nontrivial_initializer) const
Definition: object.h:4607
bool is_nullable_unsafe() const
Definition: object.h:4758
intptr_t field_id() const
Definition: object.h:13284
void set_guarded_cid_unsafe(intptr_t cid) const
Definition: object.h:4665
intptr_t HostOffset() const
Definition: object.h:13241
void set_is_nullable(bool val) const
Definition: object.h:4753
void set_field_id(intptr_t field_id) const
Definition: object.h:13288
static intptr_t initializer_function_offset()
Definition: object.h:4809
AbstractTypePtr type() const
Definition: object.h:4550
void set_kernel_offset(intptr_t value) const
Definition: object.h:4503
static intptr_t TargetOffsetOf(FieldPtr field)
Definition: object.h:13255
bool is_instance() const
Definition: object.h:4441
virtual StringPtr DictionaryName() const
Definition: object.h:4433
bool is_extension_type_member() const
Definition: object.h:4448
void set_is_unboxed_unsafe(bool b) const
Definition: object.h:4716
bool is_const() const
Definition: object.h:4443
void set_field_id_unsafe(intptr_t field_id) const
Definition: object.h:13294
void set_guarded_list_length(intptr_t list_length) const
Definition: object.h:4678
TokenPosition end_token_pos() const
Definition: object.h:4590
TokenPosition token_pos() const
Definition: object.h:4589
static intptr_t is_nullable_offset()
Definition: object.h:4766
bool has_nontrivial_initializer() const
Definition: object.h:4596
void set_static_type_exactness_state_unsafe(StaticTypeExactnessState state) const
Definition: object.h:4645
static intptr_t guarded_list_length_offset()
Definition: object.h:4683
bool initializer_changed_after_initialization() const
Definition: object.h:4461
bool is_shared() const
Definition: object.h:4493
FinalizerEntryPtr entries_collected() const
Definition: object.h:13055
void set_isolate(Isolate *value) const
Definition: object.h:13041
SetPtr all_entries() const
Definition: object.h:13047
static intptr_t entries_collected_offset()
Definition: object.h:13061
static intptr_t all_entries_offset()
Definition: object.h:13051
Isolate * isolate() const
Definition: object.h:13040
void set_all_entries(const Set &value) const
Definition: object.h:13048
static intptr_t detachments_offset()
Definition: object.h:13043
static intptr_t isolate_offset()
Definition: object.h:13037
void set_entries_collected(const FinalizerEntry &value) const
Definition: object.h:13058
void set_value(const Object &value) const
Definition: object.h:12971
FinalizerBasePtr finalizer() const
Definition: object.h:12990
static intptr_t external_size_offset()
Definition: object.h:13008
void set_next(const FinalizerEntry &value) const
Definition: object.h:12997
ObjectPtr token() const
Definition: object.h:12984
void set_token(const Object &value) const
Definition: object.h:12985
void set_detach(const Object &value) const
Definition: object.h:12977
ObjectPtr detach() const
Definition: object.h:12976
static intptr_t InstanceSize()
Definition: object.h:13012
static intptr_t token_offset()
Definition: object.h:12986
static intptr_t next_offset()
Definition: object.h:13000
static intptr_t value_offset()
Definition: object.h:12972
static intptr_t detach_offset()
Definition: object.h:12980
ObjectPtr value() const
Definition: object.h:12970
FinalizerEntryPtr next() const
Definition: object.h:12996
void set_external_size(intptr_t value) const
Definition: object.h:13005
static intptr_t finalizer_offset()
Definition: object.h:12992
intptr_t external_size() const
Definition: object.h:13004
static intptr_t callback_offset()
Definition: object.h:13077
static intptr_t type_arguments_offset()
Definition: object.h:13072
static intptr_t InstanceSize()
Definition: object.h:13081
ObjectPtr callback() const
Definition: object.h:13076
static intptr_t value_offset()
Definition: object.h:11197
static intptr_t InstanceSize()
Definition: object.h:11193
static intptr_t InstanceSize()
Definition: object.h:11262
static intptr_t value_offset()
Definition: object.h:11266
static intptr_t NumOptionalParametersOf(FunctionTypePtr ptr)
Definition: object.h:9621
TypeParametersPtr type_parameters() const
Definition: object.h:9727
intptr_t NumOptionalNamedParameters() const
Definition: object.h:9641
intptr_t num_implicit_parameters() const
Definition: object.h:9585
static intptr_t parameter_types_offset()
Definition: object.h:9680
static bool HasOptionalPositionalParameters(FunctionTypePtr ptr)
Definition: object.h:9614
AbstractTypePtr result_type() const
Definition: object.h:9670
intptr_t NumOptionalPositionalParameters() const
Definition: object.h:9634
static bool HasOptionalParameters(FunctionTypePtr ptr)
Definition: object.h:9598
static intptr_t packed_parameter_counts_offset()
Definition: object.h:9654
ArrayPtr named_parameter_names() const
Definition: object.h:9689
static intptr_t NumFixedParametersOf(FunctionTypePtr ptr)
Definition: object.h:9591
intptr_t NumParentTypeArguments() const
Definition: object.h:9570
static intptr_t NumParentTypeArgumentsOf(FunctionTypePtr ptr)
Definition: object.h:9565
intptr_t NumTypeArguments() const
Definition: object.h:9583
static intptr_t NumTypeArgumentsOf(FunctionTypePtr ptr)
Definition: object.h:9580
bool HasOptionalNamedParameters() const
Definition: object.h:9609
static intptr_t named_parameter_names_offset()
Definition: object.h:9693
bool HasOptionalParameters() const
Definition: object.h:9603
bool HasOptionalPositionalParameters() const
Definition: object.h:9617
bool HasGenericParent() const
Definition: object.h:9750
static intptr_t NameArrayLengthIncludingFlags(intptr_t num_parameters)
static intptr_t NumParametersOf(FunctionTypePtr ptr)
Definition: object.h:9645
intptr_t NumParameters() const
Definition: object.h:9648
static intptr_t NumOptionalNamedParametersOf(FunctionTypePtr ptr)
Definition: object.h:9638
static bool HasOptionalNamedParameters(FunctionTypePtr ptr)
Definition: object.h:9605
static bool IsGeneric(FunctionTypePtr ptr)
Definition: object.h:9744
intptr_t num_fixed_parameters() const
Definition: object.h:9595
bool IsGeneric() const
Definition: object.h:9747
static intptr_t NumTypeParametersOf(FunctionTypePtr ptr)
Definition: object.h:9574
intptr_t NumTypeParameters() const
Definition: object.h:9578
virtual classid_t type_class_id() const
Definition: object.h:9530
static intptr_t InstanceSize()
Definition: object.h:9776
virtual bool HasTypeClass() const
Definition: object.h:9528
static intptr_t type_parameters_offset()
Definition: object.h:9731
uint16_t packed_type_parameter_counts() const
Definition: object.h:9657
intptr_t NumOptionalParameters() const
Definition: object.h:9625
ArrayPtr parameter_types() const
Definition: object.h:9678
uint32_t packed_parameter_counts() const
Definition: object.h:9650
static intptr_t NumOptionalPositionalParametersOf(FunctionTypePtr ptr)
Definition: object.h:9631
static intptr_t packed_type_parameter_counts_offset()
Definition: object.h:9661
bool IsSyncGenerator() const
Definition: object.h:3967
bool is_unboxed_integer_parameter_at(intptr_t index) const
Definition: object.h:3783
bool IsRecognized() const
Definition: object.h:3624
bool has_unboxed_return() const
Definition: object.h:3803
bool HasUnboxedParameters() const
Definition: object.h:3836
COMPILE_ASSERT(MethodRecognizer::kNumRecognizedMethods<(1<< kRecognizedTagSize))
CodePtr CurrentCode() const
Definition: object.h:3177
virtual StringPtr DictionaryName() const
Definition: object.h:3005
static uword EntryPointOf(const FunctionPtr function)
Definition: object.h:3199
bool IsDispatcherOrImplicitAccessor() const
Definition: object.h:3842
bool HasParent() const
Definition: object.h:3930
bool IsIrregexpFunction() const
Definition: object.h:3898
COMPILE_ASSERT(kNumTagBits<=(kBitsPerByte *sizeof(decltype(UntaggedFunction::kind_tag_))))
bool WasExecuted() const
Definition: object.h:4122
void set_unboxed_integer_return() const
Definition: object.h:3741
bool has_unboxed_double_return() const
Definition: object.h:3819
bool IsImplicitInstanceClosureFunction() const
Definition: object.h:3924
void SetOptimizedInstructionCountClamped(uintptr_t value) const
Definition: object.h:3572
bool IsImplicitClosureFunction() const
Definition: object.h:3903
void set_kernel_offset(intptr_t value) const
Definition: object.h:3558
bool IsNoSuchMethodDispatcher() const
Definition: object.h:3288
static bool IsFfiCallbackTrampoline(FunctionPtr function)
Definition: object.h:3941
bool IsRegularFunction() const
Definition: object.h:3280
bool IsImplicitGetterOrSetter() const
Definition: object.h:3318
static bool is_visible(FunctionPtr f)
Definition: object.h:4185
bool has_unboxed_integer_return() const
Definition: object.h:3811
void set_end_token_pos(TokenPosition value) const
Definition: object.h:3462
static intptr_t code_offset()
Definition: object.h:3196
bool IsDynamicClosureCallDispatcher() const
Definition: object.h:3308
ArrayPtr parameter_types() const
Definition: object.h:3107
bool MakesCopyOfParameters() const
Definition: object.h:3514
bool IsFieldInitializer() const
Definition: object.h:3885
bool NeedsTypeArgumentTypeChecks() const
Definition: object.h:3432
bool has_unboxed_record_return() const
Definition: object.h:3827
bool IsStaticFunction() const
Definition: object.h:3402
bool IsDynamicFunction(bool allow_abstract=false) const
Definition: object.h:3374
ObjectPtr RawOwner() const
Definition: object.h:3083
void set_unboxed_double_parameter_at(intptr_t index) const
Definition: object.h:3728
bool IsSuspendableFunction() const
Definition: object.h:3957
static intptr_t InstanceSize()
Definition: object.h:3985
void SetUsageCounter(intptr_t value) const
Definition: object.h:4115
bool IsImplicitGetterFunction() const
Definition: object.h:3862
void set_unboxed_integer_parameter_at(intptr_t index) const
Definition: object.h:3716
static constexpr intptr_t maximum_unboxed_parameter_count()
Definition: object.h:3704
bool IsGetterFunction() const
Definition: object.h:3857
bool HasAwaiterLink() const
Definition: object.h:3239
StringPtr name() const
Definition: object.h:2992
TokenPosition token_pos() const
Definition: object.h:3446
static intptr_t kind_tag_offset()
Definition: object.h:4128
uword entry_point() const
Definition: object.h:3198
PRECOMPILER_WSR_FIELD_DECLARATION(FunctionType, signature)
uint32_t packed_fields() const
Definition: object.h:3482
bool IsClosureFunction() const
Definition: object.h:3891
bool IsFfiCallbackTrampoline() const
Definition: object.h:3938
bool IsImplicitStaticGetterFunction() const
Definition: object.h:3868
static bool IsImplicitClosureFunction(FunctionPtr func)
Definition: object.h:3906
void set_unboxed_record_return() const
Definition: object.h:3762
intptr_t kernel_offset() const
Definition: object.h:3550
static CodePtr CurrentCodeOf(const FunctionPtr function)
Definition: object.h:3181
static intptr_t signature_offset()
Definition: object.h:3049
bool is_unboxed_parameter_at(intptr_t index) const
Definition: object.h:3773
void SetOptimizedCallSiteCountClamped(uintptr_t value) const
Definition: object.h:3577
bool IsRecordFieldGetter() const
Definition: object.h:3292
bool IsAsyncFunction() const
Definition: object.h:3962
bool IsInvokeFieldDispatcher() const
Definition: object.h:3296
void reset_unboxed_parameters_and_return() const
Definition: object.h:3709
bool IsAsyncGenerator() const
Definition: object.h:3972
bool IsNonImplicitClosureFunction() const
Definition: object.h:3911
bool HasSavedArgumentsDescriptor() const
Definition: object.h:3273
bool IsImplicitStaticClosureFunction() const
Definition: object.h:3917
bool IsMethodExtractor() const
Definition: object.h:3284
CodePtr unoptimized_code() const
Definition: object.h:3185
static intptr_t entry_point_offset(CodeEntryKind entry_kind=CodeEntryKind::kNormal)
Definition: object.h:3203
bool HasThisParameter() const
Definition: object.h:3369
bool is_unboxed_double_parameter_at(intptr_t index) const
Definition: object.h:3793
bool is_optimizable() const
Definition: object.h:4200
bool IsFactory() const
Definition: object.h:3367
bool HasGenericParent() const
Definition: object.h:3143
void SetWasExecuted(bool value) const
Definition: object.h:4124
bool HasUnboxedReturnValue() const
Definition: object.h:3839
static UntaggedFunction::Kind KindOf(FunctionPtr func)
Definition: object.h:3350
UntaggedFunction::AsyncModifier modifier() const
Definition: object.h:3354
TypeParametersPtr type_parameters() const
Definition: object.h:3129
bool NeedsArgumentTypeChecks() const
Definition: object.h:3436
bool IsLocalFunction() const
Definition: object.h:3933
bool IsGenerativeConstructor() const
Definition: object.h:3363
bool IsDynamicInvocationForwarder() const
Definition: object.h:3314
UntaggedFunction::Kind kind() const
Definition: object.h:3349
TokenPosition end_token_pos() const
Definition: object.h:3455
static intptr_t unchecked_entry_point_offset()
Definition: object.h:3215
bool IsImplicitSetterFunction() const
Definition: object.h:3878
static intptr_t data_offset()
Definition: object.h:4126
bool IsDynamicInvokeFieldDispatcher() const
Definition: object.h:3300
void set_is_optimizable(bool value) const
Definition: object.h:4207
void set_unboxed_double_return() const
Definition: object.h:3751
MethodRecognizer::Kind recognized_kind() const
Definition: object.h:3619
bool IsConstructor() const
Definition: object.h:3360
bool HasImplicitClosureFunction() const
Definition: object.h:3326
bool IsSetterFunction() const
Definition: object.h:3873
AbstractTypePtr result_type() const
Definition: object.h:3099
static intptr_t InstanceSize()
Definition: object.h:13200
static intptr_t type_arguments_offset()
Definition: object.h:13207
virtual TypeArgumentsPtr GetTypeArguments() const
Definition: object.h:13204
virtual InstancePtr CanonicalizeLocked(Thread *thread) const
Definition: object.h:11124
void SetData(const Array &value) const
Definition: object.h:11083
void SetLength(intptr_t value) const
Definition: object.h:11076
static SmiPtr NoSafepointLength(const GrowableObjectArrayPtr array)
Definition: object.h:11152
virtual void SetTypeArguments(const TypeArguments &value) const
Definition: object.h:11107
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition: object.h:11144
static ArrayPtr NoSafepointData(const GrowableObjectArrayPtr array)
Definition: object.h:11156
static intptr_t type_arguments_offset()
Definition: object.h:11129
virtual TypeArgumentsPtr GetTypeArguments() const
Definition: object.h:11104
static intptr_t InstanceSize()
Definition: object.h:11140
static intptr_t data_offset()
Definition: object.h:11136
intptr_t Length() const
Definition: object.h:11072
ObjectPtr At(intptr_t index) const
Definition: object.h:11085
virtual bool CanonicalizeEquals(const Instance &other) const
Definition: object.h:11118
ArrayPtr data() const
Definition: object.h:11082
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:11091
intptr_t Capacity() const
Definition: object.h:11067
static intptr_t length_offset()
Definition: object.h:11133
@ kNew
Definition: heap.h:38
@ kOld
Definition: heap.h:39
static intptr_t ExactnessIndexFor(intptr_t num_args)
Definition: object.h:2755
static intptr_t owner_offset()
Definition: object.h:2594
static intptr_t CodeIndexFor(intptr_t num_args)
Definition: object.h:2753
static intptr_t TargetIndexFor(intptr_t num_args)
Definition: object.h:2752
bool receiver_cannot_be_smi() const
Definition: object.h:2787
static intptr_t NumArgsTestedMask()
Definition: object.h:2586
intptr_t deopt_id() const
Definition: object.h:2468
ICDataPtr AsUnaryClassChecks() const
Definition: object.h:2691
static intptr_t entries_offset()
Definition: object.h:2590
static intptr_t state_bits_offset()
Definition: object.h:2580
static intptr_t CountIndexFor(intptr_t num_args)
Definition: object.h:2749
static intptr_t NumArgsTestedShift()
Definition: object.h:2584
bool IsOriginal() const
Definition: object.h:2464
ArrayPtr entries() const
Definition: object.h:2783
bool IsValidEntryIndex(intptr_t index) const
Definition: object.h:2572
@ kNumRebindRules
Definition: object.h:2549
static intptr_t InstanceSize()
Definition: object.h:2576
void Clear(const CallSiteResetter &proof_of_reload) const
Definition: object.h:2603
bool is_tracking_exactness() const
Definition: object.h:2483
AbstractTypePtr receivers_static_type() const
Definition: object.h:2480
void set_receiver_cannot_be_smi(bool value) const
Definition: object.h:2791
static intptr_t receivers_static_type_offset()
Definition: object.h:2597
void set_is_megamorphic(bool value) const
Definition: object.h:2555
bool HasDeoptReasons() const
Definition: object.h:2528
static intptr_t EntryPointIndexFor(intptr_t num_args)
Definition: object.h:2750
static intptr_t InstanceSize()
Definition: object.h:11046
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:11048
static constexpr bool ContainsCompressedPointers()
Definition: object.h:11038
static constexpr bool ContainsCompressedPointers()
Definition: object.h:12097
static intptr_t data_offset()
Definition: object.h:12101
intptr_t GetNativeField(int index) const
Definition: object.h:13307
static intptr_t NextFieldOffset()
Definition: object.h:8355
uint16_t NumNativeFields() const
Definition: object.h:8280
static intptr_t InstanceSize()
Definition: object.h:8337
static intptr_t NativeFieldsOffset()
Definition: object.h:8357
void GetNativeFields(uint16_t num_fields, intptr_t *field_values) const
Definition: object.h:13318
static intptr_t UnroundedSize()
Definition: object.h:8336
intptr_t SizeFromClass() const
Definition: object.h:8216
bool IsValidNativeIndex(int index) const
Definition: object.h:8270
static intptr_t InstanceSize(intptr_t size)
Definition: object.h:5941
static intptr_t HeaderSize()
Definition: object.h:5949
static intptr_t InstanceSize()
Definition: object.h:5935
static intptr_t Size(const InstructionsSectionPtr instr)
Definition: object.h:5932
static intptr_t InstanceSize()
Definition: object.h:5971
bool ContainsPc(uword pc) const
Definition: object.h:5980
static uword PayloadStartAt(InstructionsTablePtr table, intptr_t index)
uword PayloadStartAt(intptr_t index) const
Definition: object.h:5996
const UntaggedInstructionsTable::Data * rodata() const
Definition: object.h:5991
static uword MonomorphicEntryPoint(const InstructionsPtr instr)
Definition: object.h:5788
uint32_t Hash() const
Definition: object.h:5874
static intptr_t InstanceSize()
Definition: object.h:5833
static InstructionsPtr FromPayloadStart(uword payload_start)
Definition: object.h:5846
static intptr_t InstanceSize(intptr_t size)
Definition: object.h:5839
uword MonomorphicEntryPoint() const
Definition: object.h:5746
uword EntryPoint() const
Definition: object.h:5747
uword PayloadStart() const
Definition: object.h:5745
static uword PayloadStart(const InstructionsPtr instr)
Definition: object.h:5748
static uint32_t Hash(const InstructionsPtr instr)
Definition: object.h:5876
static intptr_t HeaderSize()
Definition: object.h:5825
bool Equals(const Instructions &other) const
Definition: object.h:5854
static uword EntryPoint(const InstructionsPtr instr)
Definition: object.h:5797
static constexpr intptr_t kBarePayloadAlignment
Definition: object.h:5815
static intptr_t Size(const InstructionsPtr instr)
Definition: object.h:5741
intptr_t Size() const
Definition: object.h:5740
static bool Equals(InstructionsPtr a, InstructionsPtr b)
Definition: object.h:5858
static intptr_t InstanceSize()
Definition: object.h:11231
static intptr_t value_offset()
Definition: object.h:11235
static int64_t GetInt64Value(const IntegerPtr obj)
Definition: object.h:9970
static IntegerPtr New(const String &str, Heap::Space space=Heap::kNew)
Definition: object.cc:22984
virtual ObjectPtr HashCode() const
Definition: object.h:9938
virtual bool OperatorEquals(const Instance &other) const
Definition: object.h:9929
virtual int64_t AsTruncatedInt64Value() const
Definition: object.h:9945
virtual bool CanonicalizeEquals(const Instance &other) const
Definition: object.h:9932
static IsolateGroup * Current()
Definition: isolate.h:539
ClassTable * class_table() const
Definition: isolate.h:496
FieldTable * field_table() const
Definition: isolate.h:1000
static Isolate * Current()
Definition: isolate.h:986
static intptr_t InstanceSize()
Definition: object.h:5487
ArrayPtr libraries_cache() const
Definition: object.h:5526
ArrayPtr constants() const
Definition: object.h:5521
ArrayPtr scripts() const
Definition: object.h:5518
TypedDataViewPtr constants_table() const
Definition: object.h:5512
TypedDataPtr string_offsets() const
Definition: object.h:5491
TypedDataViewPtr string_data() const
Definition: object.h:5496
ArrayPtr classes_cache() const
Definition: object.h:5533
TypedDataViewPtr metadata_mappings() const
Definition: object.h:5504
TypedDataPtr canonical_names() const
Definition: object.h:5498
TypedDataBasePtr kernel_component() const
Definition: object.h:5493
TypedDataViewPtr metadata_payloads() const
Definition: object.h:5500
static intptr_t InstanceSize()
Definition: object.h:8087
Report::Kind kind() const
Definition: object.h:8080
virtual StringPtr DictionaryName() const
Definition: object.h:8452
static intptr_t InstanceSize()
Definition: object.h:8463
bool is_deferred_load() const
Definition: object.h:8461
intptr_t num_imports() const
Definition: object.h:8455
StringPtr name() const
Definition: object.h:8451
ArrayPtr imports() const
Definition: object.h:8454
LibraryPtr importer() const
Definition: object.h:8456
intptr_t num_imports() const
Definition: object.h:5219
void set_native_entry_symbol_resolver(Dart_NativeEntrySymbol native_symbol_resolver) const
Definition: object.h:5242
void set_is_dart_scheme(bool value) const
Definition: object.h:5291
bool Loaded() const
Definition: object.h:5111
bool LoadRequested() const
Definition: object.h:5103
GrowableObjectArrayPtr used_scripts() const
Definition: object.h:5211
ArrayPtr dependencies() const
Definition: object.h:5223
void set_native_entry_resolver(Dart_NativeEntryResolver value) const
Definition: object.h:5233
bool LoadNotStarted() const
Definition: object.h:5100
void set_ffi_native_resolver(Dart_FfiNativeResolver value) const
Definition: object.h:5254
bool is_in_fullsnapshot() const
Definition: object.h:5260
ClassPtr toplevel_class() const
Definition: object.h:5208
StringPtr name() const
Definition: object.h:5094
intptr_t index() const
Definition: object.h:5270
intptr_t UrlHash() const
Definition: object.h:13353
static intptr_t InstanceSize()
Definition: object.h:5119
Dart_NativeEntrySymbol native_entry_symbol_resolver() const
Definition: object.h:5238
void set_debuggable(bool value) const
Definition: object.h:5284
void set_is_in_fullsnapshot(bool value) const
Definition: object.h:5263
bool is_dart_scheme() const
Definition: object.h:5288
ArrayPtr exports() const
Definition: object.h:5217
LoadingUnitPtr loading_unit() const
Definition: object.h:5116
Dart_NativeEntryResolver native_entry_resolver() const
Definition: object.h:5229
void set_index(intptr_t value) const
Definition: object.h:5271
bool IsDebuggable() const
Definition: object.h:5281
void set_kernel_library_index(intptr_t value) const
Definition: object.h:5317
StringPtr private_key() const
Definition: object.h:5099
StringPtr url() const
Definition: object.h:5097
bool LoadInProgress() const
Definition: object.h:5106
intptr_t kernel_library_index() const
Definition: object.h:5309
Dart_FfiNativeResolver ffi_native_resolver() const
Definition: object.h:5250
KernelProgramInfoPtr kernel_program_info() const
Definition: object.h:5301
ArrayPtr imports() const
Definition: object.h:5216
static StringPtr UrlOf(LibraryPtr lib)
Definition: object.h:5098
void set_hash_mask(intptr_t value) const
Definition: object.h:12042
bool IsImmutable() const
Definition: object.h:12015
void set_data(const Array &value) const
Definition: object.h:12039
static intptr_t IndexSizeToHashMask(intptr_t index_size)
Definition: object.h:11973
static intptr_t deleted_keys_offset()
Definition: object.h:12006
TypedDataPtr index() const
Definition: object.h:12032
SmiPtr deleted_keys() const
Definition: object.h:12051
ArrayPtr data() const
Definition: object.h:12038
static intptr_t data_offset()
Definition: object.h:11994
SmiPtr hash_mask() const
Definition: object.h:12041
virtual void SetTypeArguments(const TypeArguments &value) const
Definition: object.h:12022
void set_deleted_keys(intptr_t value) const
Definition: object.h:12052
static intptr_t InstanceSize()
Definition: object.h:11982
static const LinkedHashBase & Cast(const Object &obj)
Definition: object.h:12010
static intptr_t type_arguments_offset()
Definition: object.h:11986
static intptr_t index_offset()
Definition: object.h:11990
void set_used_data(intptr_t value) const
Definition: object.h:12047
static intptr_t used_data_offset()
Definition: object.h:12002
SmiPtr used_data() const
Definition: object.h:12046
void set_index(const TypedData &value) const
Definition: object.h:12033
intptr_t Length() const
Definition: object.h:12056
static intptr_t hash_mask_offset()
Definition: object.h:11998
virtual TypeArgumentsPtr GetTypeArguments() const
Definition: object.h:12019
bool loaded() const
Definition: object.h:7990
const uint8_t * instructions_image() const
Definition: object.h:8027
intptr_t id() const
Definition: object.h:7985
LoadingUnitPtr parent() const
Definition: object.h:7980
COMPILE_ASSERT(kIllegalId==WeakTable::kNoValue)
static intptr_t InstanceSize()
Definition: object.h:7973
void set_loaded(bool value) const
Definition: object.h:7995
bool load_outstanding() const
Definition: object.h:8009
void set_instructions_image(const uint8_t *value) const
Definition: object.h:8032
bool has_instructions_image() const
Definition: object.h:8036
ArrayPtr base_objects() const
Definition: object.h:7982
void set_load_outstanding() const
Definition: object.h:8013
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:6060
static intptr_t InstanceSize()
Definition: object.h:6055
Iterator(const Map &map)
Definition: object.h:12133
ObjectPtr CurrentValue() const
Definition: object.h:12155
ObjectPtr CurrentKey() const
Definition: object.h:12153
static intptr_t InstanceSize()
Definition: object.h:12111
static intptr_t InstanceSize()
Definition: object.h:7634
static intptr_t buckets_offset()
Definition: object.h:7618
static intptr_t arguments_descriptor_offset()
Definition: object.h:7624
static intptr_t mask_offset()
Definition: object.h:7621
static intptr_t InstanceSize()
Definition: object.h:10090
virtual bool IsZero() const
Definition: object.h:10077
virtual bool IsNegative() const
Definition: object.h:10078
static int64_t Value(MintPtr mint)
Definition: object.h:10075
static intptr_t value_offset()
Definition: object.h:10074
int64_t value() const
Definition: object.h:10073
ObjectPtr referent() const
Definition: object.h:13120
static intptr_t InstanceSize()
Definition: object.h:13143
void set_referent(const Object &referent) const
Definition: object.h:13122
static intptr_t entrypoint_offset()
Definition: object.h:2361
static intptr_t expected_cid_offset()
Definition: object.h:2357
static MonomorphicSmiableCallPtr New(classid_t expected_cid, const Code &target)
Definition: object.cc:16350
static intptr_t InstanceSize()
Definition: object.h:2350
classid_t expected_cid() const
Definition: object.h:2348
ArrayPtr hide_names() const
Definition: object.h:5450
static intptr_t InstanceSize()
Definition: object.h:5453
ArrayPtr show_names() const
Definition: object.h:5449
LibraryPtr target() const
Definition: object.h:5448
LibraryPtr owner() const
Definition: object.h:5451
static intptr_t callback_offset()
Definition: object.h:13100
void set_callback(const Pointer &value) const
Definition: object.h:13097
static intptr_t InstanceSize()
Definition: object.h:13104
PointerPtr callback() const
Definition: object.h:13096
EntryType TypeAt(intptr_t index) const
Definition: object.h:5596
ObjectPtr ObjectAt(intptr_t index) const
Definition: object.h:5628
intptr_t Length() const
Definition: object.h:5572
uword RawValueAt(intptr_t index) const
Definition: object.h:5640
void SetObjectAt(intptr_t index, const Object &obj) const
Definition: object.h:5634
static uint8_t EncodeBits(EntryType type, Patchability patchable, SnapshotBehavior snapshot_behavior)
Definition: object.h:5611
SnapshotBehavior SnapshotBehaviorAt(intptr_t index) const
Definition: object.h:5606
static intptr_t InstanceSize()
Definition: object.h:5649
void SetRawValueAt(intptr_t index, uword raw_value) const
Definition: object.h:5644
static intptr_t length_offset()
Definition: object.h:5577
static intptr_t OffsetFromIndex(intptr_t index)
Definition: object.h:5688
void SetLength(intptr_t value) const
Definition: object.h:5573
static intptr_t element_offset(intptr_t index)
Definition: object.h:5583
Patchability PatchableAt(intptr_t index) const
Definition: object.h:5601
static intptr_t data_offset()
Definition: object.h:5580
static intptr_t IndexFromOffset(intptr_t offset)
Definition: object.h:5676
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:5659
void SetTypeAt(intptr_t index, EntryType type, Patchability patchable, SnapshotBehavior snapshot_behavior) const
Definition: object.h:5618
ObjectPtr Decompress(uword heap_base) const
UntaggedObject * untag() const
intptr_t GetClassId() const
Definition: raw_object.h:885
bool IsImmutable() const
Definition: object.h:338
static ObjectPtr Clone(const Object &orig, Heap::Space space, bool load_with_relaxed_atomics=false)
Definition: object.cc:2899
static ObjectPtr Allocate(intptr_t cls_id, intptr_t size, Heap::Space space, bool compressed, uword ptr_field_start_offset, uword ptr_field_end_offset)
Definition: object.cc:2759
static ClassPtr icdata_class()
Definition: object.h:563
static ClassPtr pc_descriptors_class()
Definition: object.h:540
void setPtr(ObjectPtr value, intptr_t default_cid)
Definition: object.h:13227
void StoreNonPointer(const FieldType *addr, ValueType value) const
Definition: object.h:819
static ClassPtr loadingunit_class()
Definition: object.h:566
static ClassPtr type_parameters_class()
Definition: object.h:516
@ kUserVisibleName
Definition: object.h:645
@ kInternalName
Definition: object.h:622
@ kScrubbedName
Definition: object.h:633
static void Cleanup()
Definition: object.cc:1364
type LoadPointer(type const *addr) const
Definition: object.h:771
static ClassPtr ffi_trampoline_data_class()
Definition: object.h:521
static ClassPtr class_class()
Definition: object.h:513
static ClassPtr exception_handlers_class()
Definition: object.h:546
static void InitNullAndBool(IsolateGroup *isolate_group)
Definition: object.cc:554
static ClassPtr namespace_class()
Definition: object.h:527
void ClearCanonical() const
Definition: object.h:337
void AddCommonObjectProperties(JSONObject *jsobj, const char *protocol_type, bool ref) const
static const ClassId kClassId
Definition: object.h:606
void PrintJSON(JSONStream *stream, bool ref=true) const
static ClassPtr instructions_class()
Definition: object.h:532
void StoreCompressedPointer(compressed_type const *addr, type value) const
Definition: object.h:782
static ClassPtr instructions_table_class()
Definition: object.h:536
static ClassPtr weak_serialization_reference_class()
Definition: object.h:567
static DART_FORCE_INLINE T::ObjectPtrType AllocateVariant(intptr_t class_id, Heap::Space space, intptr_t elements)
Definition: object.h:751
static DART_FORCE_INLINE T::ObjectPtrType AllocateVariant(intptr_t class_id, Heap::Space space)
Definition: object.h:742
static ObjectPtr null()
Definition: object.h:433
static Object & Handle(Zone *zone)
Definition: object.h:410
static Object & ZoneHandle(ObjectPtr ptr)
Definition: object.h:425
intptr_t GetClassId() const
Definition: object.h:341
ObjectPtr ptr() const
Definition: object.h:332
bool Contains(uword addr) const
Definition: object.h:762
static ClassPtr type_arguments_class()
Definition: object.h:517
FieldType LoadNonPointer(const FieldType *addr) const
Definition: object.h:811
static DART_FORCE_INLINE T::ObjectPtrType Allocate(Heap::Space space)
Definition: object.h:722
static Object * ReadOnlyHandle()
Definition: object.h:431
ObjectPtr ptr_
Definition: object.h:870
virtual const char * JSONType() const
Definition: object.h:380
void StorePointerUnaligned(type const *addr, type value, Thread *thread) const
Definition: object.h:787
static ClassPtr language_error_class()
Definition: object.h:553
void CheckHandle() const
Definition: object.cc:2747
bool InVMIsolateHeap() const
Definition: object.h:395
static ClassPtr megamorphic_cache_class()
Definition: object.h:564
virtual StringPtr DictionaryName() const
Definition: object.cc:2624
void set_vtable(cpp_vtable value)
Definition: object.h:706
void StorePointer(type const *addr, type value) const
Definition: object.h:776
void UnimplementedMethod() const
static ClassPtr unhandled_exception_class()
Definition: object.h:554
void StoreSmi(SmiPtr const *addr, SmiPtr value) const
Definition: object.h:795
static ClassPtr sentinel_class()
Definition: object.h:551
void Print() const
Definition: object.cc:2620
static bool ShouldHaveImmutabilityBitSet(classid_t class_id)
Definition: object.cc:2628
bool IsCanonical() const
Definition: object.h:335
static ClassPtr object_pool_class()
Definition: object.h:539
static Object & Handle(Zone *zone, ObjectPtr ptr)
Definition: object.h:416
static void FinishInit(IsolateGroup *isolate_group)
Definition: object.cc:1351
bool IsNew() const
Definition: object.h:390
static ClassPtr var_descriptors_class()
Definition: object.h:545
bool IsOld() const
Definition: object.h:391
static ClassPtr weak_array_class()
Definition: object.h:570
static DART_FORCE_INLINE uword from_offset()
Definition: object.h:879
CLASS_LIST_FOR_HANDLES(DEFINE_CLASS_TESTER)
static void FinalizeVMIsolate(IsolateGroup *isolate_group)
Definition: object.cc:1470
static ClassPtr singletargetcache_class()
Definition: object.h:558
void SetImmutable() const
Definition: object.h:339
uword raw_value() const
Definition: object.h:670
static ClassPtr context_class()
Definition: object.h:549
static ClassPtr patch_class_class()
Definition: object.h:518
static ClassPtr code_class()
Definition: object.h:531
static void InitVtables()
Definition: object.cc:615
friend class Closure
Definition: object.h:1019
static ClassPtr unlinkedcall_class()
Definition: object.h:559
friend class TwoByteString
Definition: object.h:1024
static void MakeUnusedSpaceTraversable(const Object &obj, intptr_t original_size, intptr_t used_size)
Definition: object.cc:1610
static void set_vm_isolate_snapshot_object_table(const Array &table)
Definition: object.cc:1601
void SetCanonical() const
Definition: object.h:336
static void FinalizeReadOnlyObject(ObjectPtr object)
Definition: object.cc:1556
virtual const char * ToCString() const
Definition: object.h:366
static constexpr bool ContainsCompressedPointers()
Definition: object.h:329
static ClassPtr library_class()
Definition: object.h:526
static ClassPtr unwind_error_class()
Definition: object.h:557
cpp_vtable vtable() const
Definition: object.h:700
CLASS_LIST(STORE_NON_POINTER_ILLEGAL_TYPE)
static ClassPtr field_class()
Definition: object.h:524
FieldType * UnsafeMutableNonPointer(const FieldType *addr) const
Definition: object.h:837
static DART_NOINLINE Object & HandleImpl(Zone *zone, ObjectPtr ptr, intptr_t default_cid)
Definition: object.h:674
static constexpr intptr_t RoundedAllocationSize(intptr_t size)
Definition: object.h:758
static ClassPtr script_class()
Definition: object.h:525
virtual void PrintImplementationFieldsImpl(const JSONArray &jsarr_fields) const
void StoreNonPointer(const FieldType *addr, ValueType value) const
Definition: object.h:826
friend ObjectPtr AllocateObject(intptr_t, intptr_t, intptr_t)
virtual void PrintJSONImpl(JSONStream *stream, bool ref) const
bool IsNull() const
Definition: object.h:363
static intptr_t InstanceSize()
Definition: object.h:592
static ClassPtr context_scope_class()
Definition: object.h:550
static Object & Handle()
Definition: object.h:407
static ClassPtr instructions_section_class()
Definition: object.h:533
NameDisambiguation
Definition: object.h:657
static DART_NOINLINE Object * ReadOnlyHandleImpl(intptr_t cid)
Definition: object.h:689
static ObjectPtr RawCast(ObjectPtr obj)
Definition: object.h:325
static DART_NOINLINE Object & ZoneHandleImpl(Zone *zone, ObjectPtr ptr, intptr_t default_cid)
Definition: object.h:681
static ClassPtr void_class()
Definition: object.h:515
static Object & ZoneHandle()
Definition: object.h:419
static ClassPtr dynamic_class()
Definition: object.h:514
static intptr_t tags_offset()
Definition: object.h:346
static ClassPtr function_class()
Definition: object.h:519
friend class OneByteString
Definition: object.h:1023
void operator=(ObjectPtr value)
Definition: object.h:333
static ClassPtr code_source_map_class()
Definition: object.h:541
FieldType LoadNonPointer(const FieldType *addr) const
Definition: object.h:806
static void Init(IsolateGroup *isolate_group)
Definition: object.cc:721
static void VerifyBuiltinVtable(intptr_t cid)
Definition: object.h:597
virtual ~Object()
Definition: object.h:327
static ClassPtr monomorphicsmiablecall_class()
Definition: object.h:560
static constexpr intptr_t kHashBits
Definition: object.h:323
void PrintImplementationFields(JSONStream *stream) const
static DART_FORCE_INLINE uword to_offset(intptr_t length=0)
Definition: object.h:893
static ClassPtr closure_data_class()
Definition: object.h:520
static ClassPtr api_error_class()
Definition: object.h:552
void StoreSimd128(const FieldType *addr, simd128_value_t value) const
Definition: object.h:800
static ClassPtr compressed_stackmaps_class()
Definition: object.h:542
static ClassPtr kernel_program_info_class()
Definition: object.h:528
static ClassPtr subtypetestcache_class()
Definition: object.h:565
static void VerifyBuiltinVtables()
Definition: object.cc:1634
ClassPtr clazz() const
Definition: object.h:13218
static Object & Handle(ObjectPtr ptr)
Definition: object.h:413
static Object & ZoneHandle(Zone *zone)
Definition: object.h:422
static Object & ZoneHandle(Zone *zone, ObjectPtr ptr)
Definition: object.h:428
static DART_FORCE_INLINE T::ObjectPtrType Allocate(Heap::Space space, intptr_t elements)
Definition: object.h:729
void ClearImmutable() const
Definition: object.h:340
static void SetCharAt(const String &str, intptr_t index, uint8_t code_unit)
Definition: object.h:10536
static intptr_t UnroundedSize(OneByteStringPtr str)
Definition: object.h:10558
static intptr_t data_offset()
Definition: object.h:10554
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:10569
static OneByteStringPtr New(const char *c_string, Heap::Space space=Heap::kNew)
Definition: object.h:10576
static intptr_t InstanceSize()
Definition: object.h:10564
static OneByteStringPtr null()
Definition: object.h:10624
static intptr_t UnroundedSize(intptr_t len)
Definition: object.h:10561
static uint16_t CharAt(OneByteStringPtr str, intptr_t index)
Definition: object.h:10531
static uint16_t CharAt(const String &str, intptr_t index)
Definition: object.h:10525
static PassiveObject & ZoneHandle(Zone *zone, ObjectPtr ptr)
Definition: object.h:1083
void operator=(ObjectPtr value)
Definition: object.h:1064
void operator^=(ObjectPtr value)
Definition: object.h:1065
static PassiveObject & ZoneHandle(Zone *zone)
Definition: object.h:1096
static PassiveObject & ZoneHandle(ObjectPtr ptr)
Definition: object.h:1090
static PassiveObject & Handle(Zone *zone)
Definition: object.h:1080
static PassiveObject & Handle(Zone *zone, ObjectPtr ptr)
Definition: object.h:1067
static PassiveObject & ZoneHandle()
Definition: object.h:1093
static PassiveObject & Handle(ObjectPtr ptr)
Definition: object.h:1074
static PassiveObject & Handle()
Definition: object.h:1077
ClassPtr wrapped_class() const
Definition: object.h:2270
KernelProgramInfoPtr kernel_program_info() const
Definition: object.h:2285
void set_kernel_program_info(const KernelProgramInfo &info) const
Definition: object.cc:7870
static bool IsInFullSnapshot(PatchClassPtr cls)
Definition: object.h:2294
ScriptPtr script() const
Definition: object.h:2271
void set_kernel_library_index(intptr_t index) const
Definition: object.h:2280
intptr_t kernel_library_index() const
Definition: object.h:2273
static intptr_t InstanceSize()
Definition: object.h:2291
Iterator(const PcDescriptors &descriptors, intptr_t kind_mask)
Definition: object.h:6112
intptr_t YieldIndex() const
Definition: object.h:6160
TokenPosition TokenPos() const
Definition: object.h:6156
intptr_t DeoptId() const
Definition: object.h:6155
intptr_t TryIndex() const
Definition: object.h:6159
UntaggedPcDescriptors::Kind Kind() const
Definition: object.h:6161
static intptr_t UnroundedSize(PcDescriptorsPtr desc)
Definition: object.h:6085
static intptr_t HeaderSize()
Definition: object.h:6084
intptr_t Length() const
Definition: object.cc:15779
bool Equals(const PcDescriptors &other) const
Definition: object.h:6194
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:6094
static intptr_t InstanceSize()
Definition: object.h:6089
static intptr_t UnroundedSize(intptr_t len)
Definition: object.h:6088
static intptr_t data_offset()
Definition: object.h:11505
static intptr_t type_arguments_offset()
Definition: object.h:11902
static constexpr intptr_t kNativeTypeArgPos
Definition: object.h:11906
size_t NativeAddress() const
Definition: object.h:11893
void SetNativeAddress(size_t address) const
Definition: object.h:11897
static intptr_t InstanceSize()
Definition: object.h:11887
AbstractTypePtr type_argument() const
Definition: object.h:11909
StringPtr debug_name() const
Definition: object.h:12468
StackTracePtr allocation_location() const
Definition: object.h:12464
InstancePtr handler() const
Definition: object.h:12438
static intptr_t InstanceSize()
Definition: object.h:12471
void set_handler(const Instance &value) const
Definition: object.h:12439
void set_keep_isolate_alive(bool value) const
Definition: object.h:12457
void set_is_open(bool value) const
Definition: object.h:12449
static intptr_t handler_offset()
Definition: object.h:12442
static intptr_t send_port_offset()
Definition: object.h:12433
SendPortPtr send_port() const
Definition: object.h:12432
bool is_open() const
Definition: object.h:12446
Dart_Port Id() const
Definition: object.h:12436
bool keep_isolate_alive() const
Definition: object.h:12454
static RecordShape ForUnnamed(intptr_t num_fields)
Definition: object.h:11308
bool operator!=(const RecordShape &other) const
Definition: object.h:11327
RecordShape(SmiPtr smi_value)
Definition: object.h:11300
RecordShape(intptr_t num_fields, intptr_t field_names_index)
Definition: object.h:11303
intptr_t field_names_index() const
Definition: object.h:11316
intptr_t AsInt() const
Definition: object.h:11322
intptr_t num_fields() const
Definition: object.h:11314
bool operator==(const RecordShape &other) const
Definition: object.h:11324
static constexpr intptr_t kMaxNumFields
Definition: object.h:11292
bool HasNamedFields() const
Definition: object.h:11312
RecordShape(intptr_t value)
Definition: object.h:11299
SmiPtr AsSmi() const
Definition: object.h:11320
RecordShape shape() const
Definition: object.h:11388
virtual classid_t type_class_id() const
Definition: object.h:11353
intptr_t NumFields() const
Definition: object.h:13392
static intptr_t InstanceSize()
Definition: object.h:11402
ArrayPtr field_types() const
Definition: object.h:11390
virtual bool HasTypeClass() const
Definition: object.h:11351
ArrayPtr GetFieldNames(Thread *thread) const
Definition: object.h:11493
static intptr_t InstanceSize(intptr_t num_fields)
Definition: object.h:11466
static intptr_t shape_offset()
Definition: object.h:11431
RecordShape shape() const
Definition: object.h:11430
static intptr_t InstanceSize()
Definition: object.h:11460
static intptr_t NumFields(RecordPtr ptr)
Definition: object.h:11426
intptr_t num_fields() const
Definition: object.h:11425
static intptr_t field_index_at_offset(intptr_t offset_in_bytes)
Definition: object.h:11452
void SetFieldAt(intptr_t field_index, const Object &value) const
Definition: object.h:11436
static intptr_t field_offset(intptr_t index)
Definition: object.h:11448
ObjectPtr FieldAt(intptr_t field_index) const
Definition: object.h:11433
bool NeedsUnicodeCaseEquivalents()
Definition: object.h:12728
bool operator!=(const RegExpFlags &other) const
Definition: object.h:12747
void SetDotAll()
Definition: object.h:12738
void SetGlobal()
Definition: object.h:12734
bool IsGlobal() const
Definition: object.h:12722
void SetMultiLine()
Definition: object.h:12736
bool IsMultiLine() const
Definition: object.h:12724
int value() const
Definition: object.h:12742
bool IsUnicode() const
Definition: object.h:12725
bool IsDotAll() const
Definition: object.h:12726
RegExpFlags(int value)
Definition: object.h:12720
void SetUnicode()
Definition: object.h:12737
bool operator==(const RegExpFlags &other) const
Definition: object.h:12744
bool IgnoreCase() const
Definition: object.h:12723
void SetIgnoreCase()
Definition: object.h:12735
TypedDataPtr bytecode(bool is_one_byte, bool sticky) const
Definition: object.h:12803
void set_is_simple() const
Definition: object.h:12882
bool is_complex() const
Definition: object.h:12789
void set_is_multi_line() const
Definition: object.h:12873
void set_is_unicode() const
Definition: object.h:12876
StringPtr pattern() const
Definition: object.h:12797
void set_num_bracket_expressions(const Smi &value) const
bool is_initialized() const
Definition: object.h:12787
ArrayPtr capture_name_map() const
Definition: object.h:12801
void set_is_complex() const
Definition: object.h:12883
void set_is_dot_all() const
Definition: object.h:12879
static intptr_t function_offset(intptr_t cid, bool sticky)
Definition: object.h:12815
void set_num_bracket_expressions(SmiPtr value) const
static intptr_t InstanceSize()
Definition: object.h:12901
intptr_t num_bracket_expressions() const
Definition: object.h:12798
void set_is_ignore_case() const
Definition: object.h:12870
void set_flags(RegExpFlags flags) const
Definition: object.h:12894
RegExpFlags flags() const
Definition: object.h:12891
FunctionPtr function(intptr_t cid, bool sticky) const
Definition: object.h:12836
intptr_t num_registers(bool is_one_byte) const
Definition: object.h:12791
void set_num_registers(bool is_one_byte, intptr_t value) const
Definition: object.h:12884
void set_is_global() const
Definition: object.h:12867
bool is_simple() const
Definition: object.h:12788
static intptr_t line_starts_offset()
Definition: object.h:4964
intptr_t kernel_script_index() const
Definition: object.h:4962
intptr_t col_offset() const
Definition: object.h:4944
int64_t load_timestamp() const
Definition: object.h:4950
static intptr_t InstanceSize()
Definition: object.h:5003
StringPtr url() const
Definition: object.h:4932
intptr_t line_offset() const
Definition: object.h:4943
Dart_Port Id() const
Definition: object.h:12490
static intptr_t InstanceSize()
Definition: object.h:12498
Dart_Port origin_id() const
Definition: object.h:12492
void set_origin_id(Dart_Port id) const
Definition: object.h:12493
static intptr_t InstanceSize()
Definition: object.h:7585
ObjectPtr CurrentKey() const
Definition: object.h:12256
Iterator(const Set &set)
Definition: object.h:12236
static intptr_t InstanceSize()
Definition: object.h:12214
static SingleTargetCachePtr New()
Definition: object.cc:16321
void set_target(const Code &target) const
Definition: object.cc:16313
static intptr_t InstanceSize()
Definition: object.h:2335
DEFINE_NON_POINTER_FIELD_ACCESSORS(intptr_t, lower_limit)
CodePtr target() const
Definition: object.h:2315
DEFINE_NON_POINTER_FIELD_ACCESSORS(intptr_t, upper_limit)
static intptr_t target_offset()
Definition: object.h:2317
DEFINE_NON_POINTER_FIELD_ACCESSORS(uword, entry_point)
static bool IsMatch(const Object &a, const Object &b)
Definition: object.h:10058
static uword Hash(const Object &obj)
Definition: object.h:10062
static bool ReportStats()
Definition: object.h:10056
static const char * Name()
Definition: object.h:10055
static SmiPtr New(intptr_t value)
Definition: object.h:10006
static intptr_t InstanceSize()
Definition: object.h:10004
intptr_t Value() const
Definition: object.h:9990
static constexpr intptr_t kMaxValue
Definition: object.h:9987
static intptr_t RawValue(intptr_t value)
Definition: object.h:10022
friend class Class
Definition: object.h:10047
static bool IsValid(int64_t value)
Definition: object.h:10026
virtual bool IsZero() const
Definition: object.h:9993
static ClassPtr Class()
virtual bool IsNegative() const
Definition: object.h:9994
static intptr_t Value(const SmiPtr raw_smi)
Definition: object.h:10015
void operator^=(ObjectPtr value)
Definition: object.h:10032
virtual bool FitsIntoSmi() const
Definition: object.h:10000
void operator=(SmiPtr value)
Definition: object.h:10028
TypedDataPtr pc_offset_array() const
Definition: object.h:12570
static intptr_t InstanceSize()
Definition: object.h:12591
ArrayPtr code_array() const
Definition: object.h:12566
StackTracePtr async_link() const
Definition: object.h:12562
static StaticTypeExactnessState NotTracking()
static StaticTypeExactnessState Decode(int8_t value)
void Add(const uint8_t *code_units, intptr_t len)
Definition: object.h:10502
void Add(uint16_t code_unit)
Definition: object.h:10501
intptr_t Finalize()
Definition: object.h:10517
void Add(const uint16_t *code_units, intptr_t len)
Definition: object.h:10509
CodePointIterator(const String &str)
Definition: object.h:10183
CodePointIterator(const String &str, intptr_t start, intptr_t length)
Definition: object.h:10188
virtual bool OperatorEquals(const Instance &other) const
Definition: object.h:10287
static constexpr intptr_t kSizeofRawString
Definition: object.h:10170
static constexpr intptr_t kMaxElements
Definition: object.h:10173
static StringPtr NewExternal(const uint8_t *utf8_array, intptr_t array_len, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback, Heap::Space=Heap::kNew)
bool IsOneByteString() const
Definition: object.h:10311
static uword Hash(const int32_t *characters, intptr_t len)
static uint32_t SetCachedHashIfNotSet(StringPtr obj, uint32_t hash)
Definition: object.h:10449
intptr_t Length() const
Definition: object.h:10210
virtual ObjectPtr HashCode() const
Definition: object.h:10257
static uword HashRawSymbol(const StringPtr symbol)
Definition: object.h:10247
bool HasHash() const
Definition: object.h:10229
void SetHash(intptr_t value) const
Definition: object.h:10477
static intptr_t HeaderSize()
Definition: object.h:10175
virtual uint32_t CanonicalizeHash() const
Definition: object.h:10293
void SetLength(intptr_t value) const
Definition: object.h:10471
bool Equals(const String &str) const
Definition: object.h:13337
static intptr_t length_offset()
Definition: object.h:10214
static intptr_t InstanceSize()
Definition: object.h:10177
static intptr_t hash_offset()
Definition: object.h:10234
bool IsTwoByteString() const
Definition: object.h:10315
static uint32_t SetCachedHash(StringPtr obj, uint32_t hash)
Definition: object.h:10454
static StringPtr SubString(const String &str, intptr_t begin_index, intptr_t length, Heap::Space space=Heap::kNew)
Definition: object.h:10403
uint16_t CharAt(intptr_t index) const
Definition: object.h:10259
bool StartsWith(const String &other) const
Definition: object.h:10298
bool IsSymbol() const
Definition: object.h:10309
uword Hash() const
Definition: object.h:10216
virtual bool CanonicalizeEquals(const Instance &other) const
Definition: object.h:10290
bool EqualsLatin1(const uint8_t *characters, intptr_t len) const
Definition: object.h:10274
static StringPtr NewExternal(const uint16_t *utf16_array, intptr_t array_len, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback, Heap::Space=Heap::kNew)
static uint32_t GetCachedHash(const StringPtr obj)
Definition: object.h:10445
static intptr_t LengthOf(StringPtr obj)
Definition: object.h:10211
FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance)
intptr_t num_occupied() const
Definition: object.h:7821
static intptr_t num_inputs_offset()
Definition: object.h:7816
static intptr_t cache_offset()
Definition: object.h:7811
static constexpr intptr_t MaxEntriesForCacheAllocatedFor(intptr_t count)
Definition: object.h:7843
intptr_t num_inputs() const
Definition: object.h:7819
static intptr_t InstanceSize()
Definition: object.h:7807
static intptr_t frame_size_offset()
Definition: object.h:12646
static intptr_t error_callback_offset()
Definition: object.h:12656
static intptr_t function_data_offset()
Definition: object.h:12650
ClosurePtr error_callback() const
Definition: object.h:12681
static intptr_t then_callback_offset()
Definition: object.h:12653
static intptr_t InstanceSize(intptr_t frame_capacity)
Definition: object.h:12631
static intptr_t FrameSizeGrowthGap()
Definition: object.h:12637
static intptr_t HeaderSize()
Definition: object.h:12619
static intptr_t payload_offset()
Definition: object.h:12659
static intptr_t UnroundedSize(SuspendStatePtr ptr)
Definition: object.h:12620
ClosurePtr then_callback() const
Definition: object.h:12679
static intptr_t InstanceSize()
Definition: object.h:12626
uword pc() const
Definition: object.h:12673
static intptr_t pc_offset()
Definition: object.h:12649
InstancePtr function_data() const
Definition: object.h:12677
static intptr_t frame_capacity_offset()
Definition: object.h:12642
intptr_t frame_size() const
Definition: object.h:12675
static intptr_t UnroundedSize(intptr_t frame_capacity)
Definition: object.h:12623
static Thread * Current()
Definition: thread.h:362
static TokenPosition Deserialize(int32_t value)
void set_handle(FinalizablePersistentHandle *handle)
Definition: object.h:12524
FinalizablePersistentHandle * handle() const
Definition: object.h:12523
uint8_t * data() const
Definition: object.h:12521
TransferableTypedDataPeer(uint8_t *data, intptr_t length)
Definition: object.h:12516
static intptr_t InstanceSize()
Definition: object.h:12544
static uint16_t CharAt(const String &str, intptr_t index)
Definition: object.h:10664
static intptr_t UnroundedSize(TwoByteStringPtr str)
Definition: object.h:10698
static uint16_t CharAt(TwoByteStringPtr str, intptr_t index)
Definition: object.h:10670
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:10709
static intptr_t InstanceSize()
Definition: object.h:10704
static intptr_t data_offset()
Definition: object.h:10695
static TwoByteStringPtr null()
Definition: object.h:10743
static intptr_t UnroundedSize(intptr_t len)
Definition: object.h:10701
static void SetCharAt(const String &str, intptr_t index, uint16_t ch)
Definition: object.h:10675
KeyLocation FindKeyOrUnused(const TypeArguments &instantiator_tav, const TypeArguments &function_tav) const
Definition: object.h:8865
static const Array & EmptyStorage()
Definition: object.h:8891
intptr_t NumOccupied() const
Definition: object.h:8853
bool IsLinear() const
Definition: object.h:8896
intptr_t NumEntries() const
Definition: object.h:8925
bool IsEquivalent(const TypeArguments &other, TypeEquality kind, FunctionTypeMapping *function_type_equivalence=nullptr) const
Definition: object.h:8691
static intptr_t instantiations_offset()
Definition: object.h:8981
bool IsInstantiated(Genericity genericity=kAny, intptr_t num_free_fun_type_params=kAllFree) const
Definition: object.h:8707
uword Hash() const
Definition: object.h:13396
virtual uint32_t CanonicalizeHash() const
Definition: object.h:9004
intptr_t Length() const
Definition: object.cc:7294
static intptr_t types_offset()
Definition: object.h:8589
bool Equals(const TypeArguments &other) const
Definition: object.h:8686
static intptr_t InstanceSize()
Definition: object.h:8988
static intptr_t InstanceSize(intptr_t len)
Definition: object.h:8994
static intptr_t hash_offset()
Definition: object.h:9007
AbstractTypePtr TypeAtNullSafe(intptr_t index) const
Definition: object.cc:7314
virtual InstancePtr CanonicalizeLocked(Thread *thread) const
Definition: object.h:8737
static intptr_t type_at_offset(intptr_t index)
Definition: object.h:8592
bool IsRaw(intptr_t from_index, intptr_t len) const
Definition: object.h:8646
bool IsRawWhenInstantiatedFromRaw(intptr_t len) const
Definition: object.h:8656
static intptr_t nullability_offset()
Definition: object.h:8625
static intptr_t length_offset()
Definition: object.h:8583
virtual classid_t type_class_id() const
Definition: object.h:9811
bool IsClassTypeParameter() const
Definition: object.h:9817
static intptr_t index_offset()
Definition: object.h:9823
intptr_t index() const
Definition: object.h:9821
virtual bool HasTypeClass() const
Definition: object.h:9810
virtual void EnumerateURIs(URIs *uris) const
Definition: object.h:9856
static intptr_t InstanceSize()
Definition: object.h:9877
intptr_t base() const
Definition: object.h:9819
const char * CanonicalNameCString() const
Definition: object.h:9869
bool IsFunctionTypeParameter() const
Definition: object.h:9813
static intptr_t defaults_offset()
Definition: object.h:8510
static intptr_t flags_offset()
Definition: object.h:8499
static intptr_t names_offset()
Definition: object.h:8493
static intptr_t InstanceSize()
Definition: object.h:8540
COMPILE_ASSERT(kFlagsPerSmi< kSmiBits)
static intptr_t bounds_offset()
Definition: object.h:8503
virtual void EnumerateURIs(URIs *uris) const
static TypePtr IntType()
TypeArgumentsPtr GetInstanceTypeArguments(Thread *thread, bool canonicalize=true) const
static TypePtr VoidType()
static TypePtr NullableIntType()
static TypePtr Double()
static TypePtr Number()
virtual classid_t type_class_id() const
virtual void PrintName(NameVisibility visibility, BaseTextBuffer *printer) const
TypePtr ToNullability(Nullability value, Heap::Space space) const
static TypePtr ArrayType()
static TypePtr NullableDouble()
virtual ClassPtr type_class() const
bool IsDeclarationTypeOf(const Class &cls) const
static TypePtr MintType()
static TypePtr NullType()
static intptr_t arguments_offset()
Definition: object.h:9370
virtual bool IsInstantiated(Genericity genericity=kAny, intptr_t num_free_fun_type_params=kAllFree) const
static intptr_t InstanceSize()
Definition: object.h:9422
virtual TypeArgumentsPtr arguments() const
Definition: object.h:9381
static TypePtr StringType()
static TypePtr BoolType()
static TypePtr DartFunctionType()
static TypePtr ObjectType()
virtual bool HasTypeClass() const
Definition: object.h:9373
virtual AbstractTypePtr UpdateFunctionTypes(intptr_t num_parent_type_args_adjustment, intptr_t num_free_fun_type_params, Heap::Space space, FunctionTypeMapping *function_type_mapping) const
void set_type_class(const Class &value) const
static TypePtr NeverType()
static TypePtr Int32x4()
virtual uword ComputeHash() const
void set_arguments(const TypeArguments &value) const
static TypePtr SmiType()
virtual AbstractTypePtr InstantiateFrom(const TypeArguments &instantiator_type_arguments, const TypeArguments &function_type_arguments, intptr_t num_free_fun_type_params, Heap::Space space, FunctionTypeMapping *function_type_mapping=nullptr, intptr_t num_parent_type_args_adjustment=0) const
static TypePtr Float64x2()
static TypePtr DynamicType()
virtual AbstractTypePtr Canonicalize(Thread *thread) const
static TypePtr Float32x4()
static TypePtr New(const Class &clazz, const TypeArguments &arguments, Nullability nullability=Nullability::kNonNullable, Heap::Space space=Heap::kOld)
static TypePtr NullableNumber()
static TypePtr NewNonParameterizedType(const Class &type_class)
static TypePtr DartTypeType()
virtual bool IsEquivalent(const Instance &other, TypeEquality kind, FunctionTypeMapping *function_type_equivalence=nullptr) const
SmiPtr length() const
Definition: object.h:11516
TypedDataElementType ElementType() const
Definition: object.h:11527
intptr_t Length() const
Definition: object.h:11518
virtual uint8_t * Validate(uint8_t *data) const
Definition: object.h:11613
intptr_t ElementSizeInBytes() const
Definition: object.h:11531
static TypedDataElementType ElementType(classid_t cid)
Definition: object.h:11539
static intptr_t length_offset()
Definition: object.h:11512
intptr_t LengthInBytes() const
Definition: object.h:11523
static intptr_t ElementSizeInBytes(classid_t cid)
Definition: object.h:11535
void SetLength(intptr_t value) const
Definition: object.h:11608
void * DataAddr(intptr_t byte_offset) const
Definition: object.h:11571
TypedDataBasePtr typed_data() const
Definition: object.h:11820
static intptr_t typed_data_offset()
Definition: object.h:11812
static intptr_t offset_in_bytes_offset()
Definition: object.h:11816
static SmiPtr OffsetInBytes(const TypedDataView &view)
Definition: object.h:11801
static intptr_t InstanceSize()
Definition: object.h:11793
virtual uint8_t * Validate(uint8_t *data) const
Definition: object.h:11838
static InstancePtr Data(const TypedDataView &view)
Definition: object.h:11797
void InitializeWith(const TypedDataBase &typed_data, intptr_t offset_in_bytes, intptr_t length)
Definition: object.h:11822
SmiPtr offset_in_bytes() const
Definition: object.h:11835
static bool IsExternalTypedDataView(const TypedDataView &view_obj)
Definition: object.h:11805
static intptr_t payload_offset()
Definition: object.h:11669
static bool IsTypedData(const Instance &obj)
Definition: object.h:11703
static intptr_t InstanceSize(intptr_t lengthInBytes)
Definition: object.h:11679
static intptr_t MaxNewSpaceElements(intptr_t class_id)
Definition: object.h:11689
static intptr_t MaxElements(intptr_t class_id)
Definition: object.h:11684
void RecomputeDataField()
Definition: object.h:11710
static intptr_t InstanceSize()
Definition: object.h:11673
static intptr_t stacktrace_offset()
Definition: object.h:8152
InstancePtr exception() const
Definition: object.h:8146
static intptr_t exception_offset()
Definition: object.h:8147
static intptr_t InstanceSize()
Definition: object.h:8156
InstancePtr stacktrace() const
Definition: object.h:8151
static intptr_t InstanceSize()
Definition: object.h:2409
bool can_patch_to_monomorphic() const
Definition: object.h:2405
BitField< decltype(packed_parameter_counts_), uint16_t, PackedHasNamedOptionalParameters::kNextBit, 14 > PackedNumFixedParameters
Definition: raw_object.h:2862
BitField< decltype(packed_parameter_counts_), bool, PackedNumImplicitParameters::kNextBit, 1 > PackedHasNamedOptionalParameters
Definition: raw_object.h:2857
BitField< decltype(packed_type_parameter_counts_), uint8_t, PackedNumParentTypeArguments::kNextBit, 8 > PackedNumTypeParameters
Definition: raw_object.h:2848
BitField< decltype(packed_parameter_counts_), uint8_t, 0, 1 > PackedNumImplicitParameters
Definition: raw_object.h:2852
BitField< decltype(packed_parameter_counts_), uint16_t, PackedNumFixedParameters::kNextBit, 14 > PackedNumOptionalParameters
Definition: raw_object.h:2867
BitField< decltype(packed_type_parameter_counts_), uint8_t, 0, 8 > PackedNumParentTypeArguments
Definition: raw_object.h:2843
void StoreSmi(type const *addr, type value)
Definition: raw_object.h:723
void StorePointer(type const *addr, type value)
Definition: raw_object.h:595
bool IsImmutable() const
Definition: raw_object.h:354
void Validate(IsolateGroup *isolate_group) const
Definition: raw_object.cc:42
void StoreArrayPointer(type const *addr, value_type value)
Definition: raw_object.h:645
static uword ToAddr(const UntaggedObject *raw_obj)
Definition: raw_object.h:522
bool InVMIsolateHeap() const
Definition: raw_object.cc:20
type LoadPointer(type const *addr) const
Definition: raw_object.h:576
bool Contains(uword addr) const
Definition: raw_object.h:436
void StoreCompressedPointer(compressed_type const *addr, type value)
Definition: raw_object.h:606
intptr_t GetClassId() const
Definition: raw_object.h:392
void StorePointerUnaligned(type const *addr, type value, Thread *thread)
Definition: raw_object.h:634
bool IsCanonical() const
Definition: raw_object.h:350
static constexpr bool kContainsCompressedPointers
Definition: raw_object.h:548
static intptr_t DecodeKind(uint32_t kind_and_metadata)
Definition: raw_object.h:2095
static intptr_t DecodeYieldIndex(uint32_t kind_and_metadata)
Definition: raw_object.h:2103
static intptr_t DecodeTryIndex(uint32_t kind_and_metadata)
Definition: raw_object.h:2099
static intptr_t payload_offset()
Definition: raw_object.h:3511
static intptr_t payload_offset()
Definition: raw_object.h:3114
static intptr_t InstanceSize()
Definition: object.h:8184
bool is_user_initiated() const
Definition: object.h:8179
StringPtr message() const
Definition: object.h:8182
static intptr_t tag_offset()
Definition: object.h:13166
void set_streamable(bool streamable)
Definition: object.h:13162
void set_tag(uword t) const
Definition: object.h:13155
uword tag() const
Definition: object.h:13154
bool streamable() const
Definition: object.h:13161
static intptr_t InstanceSize()
Definition: object.h:13172
StringPtr label() const
Definition: object.h:13168
static constexpr intptr_t kMaxUserTags
Definition: tags.h:110
static constexpr uword kUserTagIdOffset
Definition: tags.h:111
static constexpr uintptr_t RoundUpToPowerOfTwo(uintptr_t x)
Definition: utils.h:135
static T AddWithWrapAround(T a, T b)
Definition: utils.h:431
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:120
static constexpr size_t BitLength(int64_t value)
Definition: utils.h:213
static bool IsUint(intptr_t N, T value)
Definition: utils.h:328
static constexpr bool IsAligned(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:92
static constexpr bool IsPowerOfTwo(T x)
Definition: utils.h:76
static uword AllocateZoneHandle(Zone *zone)
Definition: handles.cc:42
static uword AllocateHandle(Zone *zone)
Definition: handles.cc:32
Definition: il.h:75
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:6723
static intptr_t InstanceSize()
Definition: object.h:6742
static intptr_t LengthOf(const WeakArrayPtr array)
Definition: object.h:13299
static constexpr intptr_t InstanceSize(intptr_t len)
Definition: object.h:6748
ObjectPtr AtAcquire(intptr_t index) const
Definition: object.h:6728
static intptr_t element_offset(intptr_t index)
Definition: object.h:6706
static intptr_t length_offset()
Definition: object.h:6700
intptr_t Length() const
Definition: object.h:6697
ObjectPtr At(intptr_t index) const
Definition: object.h:6722
static constexpr bool IsValidLength(intptr_t length)
Definition: object.h:6738
static intptr_t index_at_offset(intptr_t offset_in_bytes)
Definition: object.h:6710
static intptr_t data_offset()
Definition: object.h:6703
void SetAtRelease(intptr_t index, const Object &value) const
Definition: object.h:6731
ObjectPtr value() const
Definition: object.h:12924
static intptr_t key_offset()
Definition: object.h:12922
void set_key(const Object &key) const
Definition: object.h:12921
static intptr_t value_offset()
Definition: object.h:12926
static intptr_t InstanceSize()
Definition: object.h:12932
ObjectPtr key() const
Definition: object.h:12920
void set_value(const Object &value) const
Definition: object.h:12925
static intptr_t InstanceSize()
Definition: object.h:12958
ObjectPtr target() const
Definition: object.h:12944
static intptr_t type_arguments_offset()
Definition: object.h:12952
static intptr_t target_offset()
Definition: object.h:12948
void set_target(const Object &target) const
Definition: object.h:12945
static ObjectPtr UnwrapIfTarget(const Object &obj)
Definition: object.h:6677
static ObjectPtr Unwrap(ObjectPtr obj)
Definition: object.h:6667
static ObjectPtr UnwrapIfTarget(ObjectPtr obj)
Definition: object.h:6676
static ObjectPtr TargetOf(const WeakSerializationReferencePtr obj)
Definition: object.h:6663
static intptr_t InstanceSize()
Definition: object.h:6679
static ObjectPtr Unwrap(const Object &obj)
Definition: object.h:6675
ObjectPtr target() const
Definition: object.h:6662
static constexpr intptr_t kNoValue
Definition: weak_table.h:18
static const word kNoTypeArguments
Definition: runtime_api.h:486
static const word kMaxElements
Definition: runtime_api.h:1462
static word element_offset(intptr_t index)
int64_t Dart_Port
Definition: dart_api.h:1525
#define DART_WARN_UNUSED_RESULT
Definition: dart_api.h:66
Dart_NativeFunction(* Dart_NativeEntryResolver)(Dart_Handle name, int num_of_arguments, bool *auto_setup_scope)
Definition: dart_api.h:3234
void(* Dart_HandleFinalizer)(void *isolate_callback_data, void *peer)
Definition: dart_api.h:265
const uint8_t *(* Dart_NativeEntrySymbol)(Dart_NativeFunction nf)
Definition: dart_api.h:3255
void *(* Dart_FfiNativeResolver)(const char *name, uintptr_t args_n)
Definition: dart_api.h:3262
@ kNormal
Default priority level.
Definition: embedder.h:262
const EmbeddedViewParams * params
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
VkInstance instance
Definition: main.cc:48
SkBitmap source
Definition: examples.cpp:28
static bool b
struct MyStruct a[10]
AtkStateType state
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static void set_value(FlSettingsPortal *portal, const FlSetting *setting, GVariant *value)
uint8_t value
void PrintTo(FlValue *v, std::ostream *os)
Definition: fl_test.cc:78
GAsyncResult * result
uint32_t uint32_t * format
uint32_t * target
Dart_NativeFunction function
Definition: fuchsia.cc:51
static float max(float r, float g, float b)
Definition: hsl.cpp:49
size_t length
Win32Message message
double y
double x
ImplicitString Name
Definition: DMSrcSink.h:38
Optional< SkRect > bounds
Definition: SkRecords.h:189
SK_SPI size_t ToUTF8(SkUnichar uni, char utf8[kMaxBytesInUTF8Sequence]=nullptr)
void Decompress(const uint8_t *input, intptr_t input_len, uint8_t **output, intptr_t *output_length)
Definition: gzip.cc:15
static constexpr word kBitsPerWordLog2
Definition: runtime_api.h:290
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274
static constexpr intptr_t kCompressedWordSize
Definition: runtime_api.h:286
bool IsSmi(int64_t v)
Definition: runtime_api.cc:31
static constexpr intptr_t kObjectAlignment
Definition: runtime_api.h:313
constexpr intptr_t kSmiBits
Definition: runtime_api.h:301
bool IsDoubleType(const AbstractType &type)
Definition: runtime_api.cc:71
static constexpr int HeaderSize
def link(from_root, to_root)
Definition: dart_pkg.py:44
Definition: dart_vm.cc:33
static constexpr intptr_t kNullIdentityHash
Definition: object.h:10784
const intptr_t kOffsetOfPtr
Definition: globals.h:136
const int kNumTypedDataCidRemainders
Definition: class_id.h:265
static bool Equals(const Object &expected, const Object &actual)
static const ClassId kLastTypedDataCid
Definition: class_id.h:378
bool IsTypedDataViewClassId(intptr_t index)
Definition: class_id.h:439
bool IsTypedDataClassId(intptr_t index)
Definition: class_id.h:433
static void FindICData(const Array &ic_data_array, intptr_t deopt_id, ICData *ic_data)
static constexpr intptr_t kFalseIdentityHash
Definition: object.h:10786
constexpr intptr_t kBitsPerWordLog2
Definition: globals.h:513
constexpr intptr_t kBitsPerByteLog2
Definition: globals.h:462
const intptr_t kSmiBits
Definition: globals.h:24
bool IsFfiDynamicLibraryClassId(intptr_t index)
Definition: class_id.h:545
static const char *const names[]
Definition: symbols.cc:24
InstantiationMode
Definition: raw_object.h:1467
static constexpr intptr_t kObjectStartAlignment
ZoneGrowableHandlePtrArray< const String > URIs
Definition: object.h:1110
const char *const name
const int kTypedDataCidRemainderUnmodifiable
Definition: class_id.h:264
static bool EqualsIgnoringPrivateKey(const String &str1, const String &str2)
Definition: object.cc:24247
const intptr_t kSmiMax
Definition: globals.h:28
static constexpr const char * kNone
Definition: run_vm_tests.cc:43
constexpr intptr_t kBitsPerWord
Definition: globals.h:514
uword cpp_vtable
Definition: globals.h:163
@ kNew
Definition: heap_test.cc:891
Nullability
Definition: object.h:1112
DART_WARN_UNUSED_RESULT ErrorPtr EntryPointFieldInvocationError(const String &getter_name)
Definition: object.cc:27196
static intptr_t kInitialSize
Definition: hashmap_test.cc:13
intptr_t RawSmiValue(const SmiPtr raw_value)
static FieldPtr GetField(const Class &cls, const char *name)
uint32_t CombineHashes(uint32_t hash, uint32_t other_hash)
Definition: hash.h:12
const char *const class_name
const int kTypedDataCidRemainderInternal
Definition: class_id.h:261
FfiCallbackKind
Definition: object.h:2984
int32_t classid_t
Definition: globals.h:524
DART_WARN_UNUSED_RESULT ErrorPtr EntryPointMemberInvocationError(const Object &member)
Definition: object.cc:27212
bool IsUnmodifiableTypedDataViewClassId(intptr_t index)
Definition: class_id.h:453
ClassId
Definition: class_id.h:212
@ kForwardingCorpse
Definition: class_id.h:225
@ kIllegalCid
Definition: class_id.h:214
@ kNullCid
Definition: class_id.h:252
@ kNumPredefinedCids
Definition: class_id.h:257
@ kByteDataViewCid
Definition: class_id.h:244
@ kVoidCid
Definition: class_id.h:254
@ kDynamicCid
Definition: class_id.h:253
@ kNeverCid
Definition: class_id.h:255
@ kFreeListElement
Definition: class_id.h:224
@ kUnmodifiableByteDataViewCid
Definition: class_id.h:245
void(* callback_)(Dart_Handle)
constexpr uint32_t kMaxUint32
Definition: globals.h:484
constexpr intptr_t kBitsPerByte
Definition: globals.h:463
EntryPointPragma FindEntryPointPragma(IsolateGroup *IG, const Array &metadata, Field *reusable_field_handle, Object *pragma)
Definition: object.cc:27114
ObjectPtr Invoke(const Library &lib, const char *name)
TypedDataElementType
Definition: raw_object.h:124
unibrow::Mapping< unibrow::Ecma262Canonicalize > Canonicalize
FunctionPtr GetFunction(const Library &lib, const char *name)
constexpr uword kUwordMax
Definition: globals.h:519
DART_WARN_UNUSED_RESULT ErrorPtr VerifyEntryPoint(const Library &lib, const Object &member, const Object &annotated, std::initializer_list< EntryPointPragma > allowed_kinds)
Definition: object.cc:27151
uintptr_t uword
Definition: globals.h:501
TypeEquality
Definition: object.h:1118
const uint32_t fp
EntryPointPragma
Definition: object.h:4366
const int kTypedDataCidRemainderExternal
Definition: class_id.h:263
static const char * Concat(const char *a, const char *b)
Definition: file_test.cc:86
static const ClassId kFirstTypedDataCid
Definition: class_id.h:377
const int kTypedDataCidRemainderView
Definition: class_id.h:262
bool IsZero(char *begin, char *end)
static void EvaluateCompiledExpression(Thread *thread, JSONStream *js)
Definition: service.cc:3313
uint32_t HashBytes(const uint8_t *bytes, intptr_t size)
Definition: hash.h:31
bool FindPragmaInMetadata(Thread *T, const Object &metadata_obj, const String &pragma_name, bool multiple, Object *options)
Definition: object.cc:4092
void Validate(const Table &table)
NNBDCompiledMode
Definition: object.h:1126
constexpr intptr_t kBitsPerInt32
Definition: globals.h:466
static T LoadUnaligned(const T *ptr)
Definition: unaligned.h:14
const intptr_t cid
static constexpr intptr_t kTrueIdentityHash
Definition: object.h:10785
static constexpr intptr_t kCompressedWordSize
Definition: globals.h:42
raw_obj untag() -> num_entries()) VARIABLE_COMPRESSED_VISITOR(Array, Smi::Value(raw_obj->untag() ->length())) VARIABLE_COMPRESSED_VISITOR(TypedData, TypedData::ElementSizeInBytes(raw_obj->GetClassId()) *Smi::Value(raw_obj->untag() ->length())) VARIABLE_COMPRESSED_VISITOR(Record, RecordShape(raw_obj->untag() ->shape()).num_fields()) VARIABLE_NULL_VISITOR(CompressedStackMaps, CompressedStackMaps::PayloadSizeOf(raw_obj)) VARIABLE_NULL_VISITOR(OneByteString, Smi::Value(raw_obj->untag() ->length())) VARIABLE_NULL_VISITOR(TwoByteString, Smi::Value(raw_obj->untag() ->length())) intptr_t UntaggedField::VisitFieldPointers(FieldPtr raw_obj, ObjectPointerVisitor *visitor)
Definition: raw_object.cc:558
uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits=kBitsPerInt32)
Definition: hash.h:20
static uint32_t Hash(uint32_t key)
Definition: hashmap_test.cc:65
void DumpTypeTable(Isolate *isolate)
Definition: object.cc:27075
constexpr int32_t kMaxInt32
Definition: globals.h:483
static void DumpStackFrame(uword pc, uword fp, const char *name, uword offset)
Definition: profiler.cc:72
static void AddClass(const int32_t *elmv, intptr_t elmc, ZoneGrowableArray< CharacterRange > *ranges)
Definition: regexp.cc:4600
constexpr intptr_t kWordSize
Definition: globals.h:509
static constexpr intptr_t kObjectAlignment
void DFLRT_ExitSafepoint(NativeArguments __unusable_)
Genericity
Definition: object.h:2248
@ kFunctions
Definition: object.h:2251
@ kCurrentClass
Definition: object.h:2250
@ kAny
Definition: object.h:2249
static Dart_TypedData_Type GetType(intptr_t class_id)
const intptr_t kPreferredLoopAlignment
void DumpTypeParameterTable(Isolate *isolate)
Definition: object.cc:27098
const char *const function_name
static int8_t data[kExtLength]
static int kLength
@ kHeapObjectTag
@ kSmiTagMask
@ kSmiTagShift
void DumpTypeArgumentsTable(Isolate *isolate)
Definition: object.cc:27106
const intptr_t kSmiMin
Definition: globals.h:29
static FinalizablePersistentHandle * AddFinalizer(const Object &referent, void *peer, Dart_HandleFinalizer callback, intptr_t external_size)
Definition: object.cc:24159
static int NumEntries(const FinalizerEntry &entry, intptr_t acc=0)
static constexpr intptr_t kNewAllocatableSize
Definition: spaces.h:54
bool IsExternalTypedDataClassId(intptr_t index)
Definition: class_id.h:447
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
@ kCurrentAndEnclosingFree
Definition: object.h:2937
@ kAllFree
Definition: object.h:2940
@ kNoneFree
Definition: object.h:2926
ObjectPtr CompressedObjectPtr
static void SetName(Thread *thread, JSONStream *js)
Definition: service.cc:5710
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
Definition: switches.h:191
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via dart
Definition: switches.h:217
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
struct PathData * Data(SkPath *path)
Definition: path_ops.cc:52
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
void Reset(SkPath *path)
Definition: path_ops.cc:40
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
std::function< void()> closure
Definition: closure.h:14
dst
Definition: cp.py:12
std::string ToLowerCase(std::string_view string)
Definition: utilities.cc:62
static std::string ToString(CompilerBackend::Type type)
Definition: reflector.cc:559
std::function< void(MTLRenderPipelineDescriptor *)> Callback
TSize< Scalar > Size
Definition: size.h:137
dictionary stats
Definition: malisc.py:20
skgpu::graphite::Transform Transform
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
Definition: SkVx.h:680
#define SHARED_READONLY_HANDLES_LIST(V)
Definition: object.h:457
#define DEFINE_INSTRUCTIONS_FLAG_HANDLING(Name)
Definition: object.h:5893
#define BASE_OBJECT_IMPLEMENTATION(object, super)
Definition: object.h:106
#define ASSERT_FUNCTION_KIND_IN_RANGE(Name)
Definition: object.h:4238
#define MINT_OBJECT_IMPLEMENTATION(object, rettype, super)
Definition: object.h:303
#define REUSABLE_FORWARD_DECLARATION(name)
Definition: object.h:74
#define OBJECT_SERVICE_SUPPORT(object)
Definition: object.h:221
#define ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(object, handle)
Definition: object.h:90
#define DEFINE_CLASS_TESTER(clazz)
Definition: object.h:349
#define DEFINE_BIT(name, _)
Definition: object.h:4257
#define DECLARE_FLAG_POS(Name)
Definition: object.h:4098
#define HEAP_OBJECT_IMPLEMENTATION(object, super)
Definition: object.h:260
#define DEFINE_ACCESSORS(name, accessor_name)
Definition: object.h:4189
#define DECLARE_SHARED_READONLY_HANDLE(Type, name)
Definition: object.h:1013
#define DEOPT_REASONS(V)
Definition: object.h:2493
#define PRECOMPILER_WSR_FIELD_DECLARATION(Type, Name)
Definition: object.h:1055
#define DEFINE_FLAG_ACCESSORS(Name)
Definition: object.h:4107
#define FOR_EACH_FUNCTION_KIND_BIT(V)
Definition: object.h:4157
#define FOR_EACH_REBIND_RULE(V)
Definition: object.h:2537
#define DECLARE_FLAG_ACCESSORS(Name)
Definition: object.h:7502
#define FINAL_HEAP_OBJECT_IMPLEMENTATION(object, super)
Definition: object.h:300
#define TYPED_GETTER_SETTER(name, type)
Definition: object.h:11639
#define DECLARE_BIT(name, _)
Definition: object.h:4225
#define STORE_NON_POINTER_ILLEGAL_TYPE(type)
Definition: object.h:849
#define REBIND_ENUM_DEF(name)
Definition: object.h:2546
#define DEFINE_GETTERS_AND_SETTERS(return_type, type, name)
Definition: object.h:3532
#define OBJECT_IMPLEMENTATION(object, super)
Definition: object.h:242
#define DEFINE_FLAG_BIT(Name)
Definition: object.h:4102
#define CHECK_HANDLE()
Definition: object.h:84
#define DEFINE_FORWARD_DECLARATION(clazz)
Definition: object.h:54
#define FOR_EACH_FUNCTION_VOLATILE_KIND_BIT(V)
Definition: object.h:4175
#define DEFINE_ENUM_LIST(name)
Definition: object.h:2513
#define DEFINE_INSTRUCTIONS_FLAG(Name)
Definition: object.h:5720
#define INSTRUCTIONS_FLAGS_LIST(V)
Definition: object.h:5715
#define REUSABLE_FRIEND_DECLARATION(name)
Definition: object.h:1027
#define DEFINE_SHARED_READONLY_HANDLE_GETTER(Type, name)
Definition: object.h:503
#define STATE_BITS_LIST(V)
Definition: object.h:4090
SkScalar w
#define DART_2PART_UINT64_C(a, b)
Definition: globals.h:472
#define DEBUG_ONLY(code)
Definition: globals.h:141
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName)
Definition: globals.h:593
#define PRINTF_ATTRIBUTE(string_index, first_to_check)
Definition: globals.h:697
#define DISALLOW_ALLOCATION()
Definition: globals.h:604
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
fuchsia::ui::composition::ParentViewportWatcherHandle handle_
static DecodeResult decode(std::string path)
Definition: png_codec.cpp:124
#define T
Definition: precompiler.cc:65
#define FOR_EACH_RAW_FUNCTION_KIND(V)
Definition: raw_object.h:1240
#define JIT_FUNCTION_COUNTERS(F)
Definition: raw_object.h:1443
#define CONTEXT_SCOPE_VARIABLE_DESC_FLAG_LIST(V)
Definition: raw_object.h:2439
SeparatedVector2 offset
static intptr_t elements_start_offset()
Definition: object.h:10849
static intptr_t elements_start_offset()
Definition: object.h:7159
static intptr_t elements_start_offset()
Definition: object.h:7529
static intptr_t elements_start_offset()
Definition: object.h:7435
static intptr_t elements_start_offset()
Definition: object.h:6600
static NameFormattingParams DisambiguatedUnqualified(Object::NameVisibility visibility)
Definition: object.h:2975
static NameFormattingParams DisambiguatedWithoutClassName(Object::NameVisibility visibility)
Definition: object.h:2968
Object::NameVisibility name_visibility
Definition: object.h:2945
NameFormattingParams(Object::NameVisibility visibility, Object::NameDisambiguation name_disambiguation=Object::NameDisambiguation::kNo)
Definition: object.h:2961
static intptr_t elements_start_offset()
Definition: object.h:5589
Entry(uword value, EntryType info)
Definition: object.h:5564
const Object * obj_
Definition: object.h:5566
Entry(const Object *obj)
Definition: object.h:5562
static intptr_t elements_start_offset()
Definition: object.h:10548
static intptr_t elements_start_offset()
Definition: object.h:11444
static intptr_t elements_start_offset()
Definition: object.h:10689
static intptr_t elements_start_offset()
Definition: object.h:8598
static intptr_t elements_start_offset()
Definition: object.h:6717
BitField< uint8_t, Patchability, TypeBits::kNextBit, 1 > PatchableBit
BitField< uint8_t, SnapshotBehavior, PatchableBit::kNextBit, 3 > SnapshotBehaviorBits
BitField< uint8_t, EntryType, 0, 4 > TypeBits
#define REUSABLE_HANDLE_LIST(V)
Definition: thread.h:78
#define NOT_IN_PRECOMPILED(code)
Definition: globals.h:100
#define OFFSET_OF(type, field)
Definition: globals.h:138
#define ONLY_IN_PRECOMPILED(code)
Definition: globals.h:101
#define OFFSET_OF_RETURNED_VALUE(type, accessor)
Definition: globals.h:143