Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
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;
377 void PrintImplementationFields(JSONStream* stream) 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 }
706 void set_vtable(cpp_vtable value) {
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) {
759 return Utils::RoundUp(size, kObjectAlignment);
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>
787 void StorePointerUnaligned(type const* addr,
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:
1064 void operator=(ObjectPtr value) { ptr_ = value; }
1065 void operator^=(ObjectPtr value) { ptr_ = value; }
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 kLegacy = 2,
1116 // Adjust kNullabilityBitSize in app_snapshot.cc if adding new values.
1117};
1118
1119// Equality kind between types.
1120enum class TypeEquality {
1121 kCanonical = 0,
1122 kSyntactical = 1,
1123 kInSubtypeTest = 2,
1124};
1125
1126// The NNBDCompiledMode reflects the mode in which constants of the library were
1127// compiled by CFE.
1129 kStrong = 0,
1130 kWeak = 1,
1131 kAgnostic = 2,
1132 kInvalid = 3,
1133};
1134
1135class Class : public Object {
1136 public:
1143
1144 bool HasCompressedPointers() const;
1145 intptr_t host_instance_size() const {
1147 return (untag()->host_instance_size_in_words_ * kCompressedWordSize);
1148 }
1149 intptr_t target_instance_size() const {
1151#if defined(DART_PRECOMPILER)
1152 return (untag()->target_instance_size_in_words_ *
1153 compiler::target::kCompressedWordSize);
1154#else
1155 return host_instance_size();
1156#endif // defined(DART_PRECOMPILER)
1157 }
1158 static intptr_t host_instance_size(ClassPtr clazz) {
1159 return (clazz->untag()->host_instance_size_in_words_ * kCompressedWordSize);
1160 }
1161 static intptr_t target_instance_size(ClassPtr clazz) {
1162#if defined(DART_PRECOMPILER)
1163 return (clazz->untag()->target_instance_size_in_words_ *
1164 compiler::target::kCompressedWordSize);
1165#else
1166 return host_instance_size(clazz);
1167#endif // defined(DART_PRECOMPILER)
1168 }
1169 void set_instance_size(intptr_t host_value_in_bytes,
1170 intptr_t target_value_in_bytes) const {
1173 host_value_in_bytes / kCompressedWordSize,
1174 target_value_in_bytes / compiler::target::kCompressedWordSize);
1175 }
1176 void set_instance_size_in_words(intptr_t host_value,
1177 intptr_t target_value) const {
1178 ASSERT(
1180 StoreNonPointer(&untag()->host_instance_size_in_words_, host_value);
1181#if defined(DART_PRECOMPILER)
1182 ASSERT(
1183 Utils::IsAligned((target_value * compiler::target::kCompressedWordSize),
1184 compiler::target::kObjectAlignment));
1185 StoreNonPointer(&untag()->target_instance_size_in_words_, target_value);
1186#else
1187 // Could be different only during cross-compilation.
1188 ASSERT_EQUAL(host_value, target_value);
1189#endif // defined(DART_PRECOMPILER)
1190 }
1191
1192 intptr_t host_next_field_offset() const {
1193 return untag()->host_next_field_offset_in_words_ * kCompressedWordSize;
1194 }
1195 intptr_t target_next_field_offset() const {
1196#if defined(DART_PRECOMPILER)
1197 return untag()->target_next_field_offset_in_words_ *
1198 compiler::target::kCompressedWordSize;
1199#else
1200 return host_next_field_offset();
1201#endif // defined(DART_PRECOMPILER)
1202 }
1203 void set_next_field_offset(intptr_t host_value_in_bytes,
1204 intptr_t target_value_in_bytes) const {
1206 host_value_in_bytes / kCompressedWordSize,
1207 target_value_in_bytes / compiler::target::kCompressedWordSize);
1208 }
1209 void set_next_field_offset_in_words(intptr_t host_value,
1210 intptr_t target_value) const {
1211 // Assert that the next field offset is either negative (ie, this object
1212 // can't be extended by dart code), or rounds up to the kObjectAligned
1213 // instance size.
1214 ASSERT((host_value < 0) ||
1215 ((host_value <= untag()->host_instance_size_in_words_) &&
1216 (host_value + (kObjectAlignment / kCompressedWordSize) >
1217 untag()->host_instance_size_in_words_)));
1218 StoreNonPointer(&untag()->host_next_field_offset_in_words_, host_value);
1219#if defined(DART_PRECOMPILER)
1220 ASSERT((target_value < 0) ||
1221 ((target_value <= untag()->target_instance_size_in_words_) &&
1222 (target_value + (compiler::target::kObjectAlignment /
1223 compiler::target::kCompressedWordSize) >
1224 untag()->target_instance_size_in_words_)));
1225 StoreNonPointer(&untag()->target_next_field_offset_in_words_, target_value);
1226#else
1227 // Could be different only during cross-compilation.
1228 ASSERT_EQUAL(host_value, target_value);
1229#endif // defined(DART_PRECOMPILER)
1230 }
1231
1232 static bool is_valid_id(intptr_t value) {
1234 }
1235 intptr_t id() const { return untag()->id_; }
1236 void set_id(intptr_t value) const {
1237 ASSERT(value >= 0 && value < std::numeric_limits<classid_t>::max());
1238 StoreNonPointer(&untag()->id_, value);
1239 }
1240 static intptr_t id_offset() { return OFFSET_OF(UntaggedClass, id_); }
1241
1242#if !defined(DART_PRECOMPILED_RUNTIME)
1243 // If the interface of this class has a single concrete implementation, either
1244 // via `extends` or by `implements`, returns its CID.
1245 // If it has no implementation, returns kIllegalCid.
1246 // If it has more than one implementation, returns kDynamicCid.
1247 intptr_t implementor_cid() const { return untag()->implementor_cid_; }
1248
1249 // Returns true if the implementor tracking state changes and so must be
1250 // propagated to this class's superclass and interfaces.
1251 bool NoteImplementor(const Class& implementor) const;
1252#endif
1253
1254 static intptr_t num_type_arguments_offset() {
1255 return OFFSET_OF(UntaggedClass, num_type_arguments_);
1256 }
1257
1258 StringPtr Name() const;
1259 StringPtr ScrubbedName() const;
1260 const char* ScrubbedNameCString() const;
1261 StringPtr UserVisibleName() const;
1262 const char* UserVisibleNameCString() const;
1263
1264 const char* NameCString(NameVisibility name_visibility) const;
1265
1266 // The mixin for this class if one exists. Otherwise, returns a raw pointer
1267 // to this class.
1268 ClassPtr Mixin() const;
1269
1270 bool IsInFullSnapshot() const;
1271
1272 virtual StringPtr DictionaryName() const { return Name(); }
1273
1274 ScriptPtr script() const { return untag()->script(); }
1275 void set_script(const Script& value) const;
1276
1277#if !defined(DART_PRECOMPILED_RUNTIME)
1278 KernelProgramInfoPtr KernelProgramInfo() const;
1279#endif
1280
1282#if defined(DART_PRECOMPILED_RUNTIME)
1283 return TokenPosition::kNoSource;
1284#else
1285 return untag()->token_pos_;
1286#endif // defined(DART_PRECOMPILED_RUNTIME)
1287 }
1288
1289#if !defined(DART_PRECOMPILED_RUNTIME)
1290 void set_token_pos(TokenPosition value) const;
1291#endif // !defined(DART_PRECOMPILED_RUNTIME)
1292
1294#if defined(DART_PRECOMPILED_RUNTIME)
1295 return TokenPosition::kNoSource;
1296#else
1297 return untag()->end_token_pos_;
1298#endif // defined(DART_PRECOMPILED_RUNTIME)
1299 }
1300
1301#if !defined(DART_PRECOMPILED_RUNTIME)
1302 void set_end_token_pos(TokenPosition value) const;
1303#endif // !defined(DART_PRECOMPILED_RUNTIME)
1304
1305 uint32_t Hash() const;
1306 static uint32_t Hash(ClassPtr);
1307
1308 int32_t SourceFingerprint() const;
1309
1310 // Return the Type with type arguments instantiated to bounds.
1311 TypePtr RareType() const;
1312
1313 // Return the non-nullable Type whose arguments are the type parameters
1314 // declared by this class.
1315 TypePtr DeclarationType() const;
1316
1317 static intptr_t declaration_type_offset() {
1318 return OFFSET_OF(UntaggedClass, declaration_type_);
1319 }
1320
1321 // Returns flattened instance type arguments vector for
1322 // instance of this class, parameterized with declared
1323 // type parameters of this class.
1324 TypeArgumentsPtr GetDeclarationInstanceTypeArguments() const;
1325
1326 // Returns flattened instance type arguments vector for
1327 // instance of this type, parameterized with given type arguments.
1328 //
1329 // Length of [type_arguments] should match number of type parameters
1330 // returned by [NumTypeParameters].
1331 TypeArgumentsPtr GetInstanceTypeArguments(Thread* thread,
1332 const TypeArguments& type_arguments,
1333 bool canonicalize = true) const;
1334
1335 LibraryPtr library() const { return untag()->library(); }
1336 void set_library(const Library& value) const;
1337
1338 // The formal type parameters and their bounds (no defaults), are specified as
1339 // an object of type TypeParameters.
1340 TypeParametersPtr type_parameters() const {
1342 return untag()->type_parameters();
1343 }
1344 void set_type_parameters(const TypeParameters& value) const;
1345 intptr_t NumTypeParameters(Thread* thread) const;
1346 intptr_t NumTypeParameters() const {
1348 }
1349
1350 // Return the type parameter declared at index.
1351 TypeParameterPtr TypeParameterAt(
1352 intptr_t index,
1353 Nullability nullability = Nullability::kNonNullable) const;
1354
1355 // Length of the flattened instance type arguments vector.
1356 // Includes type arguments of the super class.
1357 intptr_t NumTypeArguments() const;
1358
1359 // Return true if this class declares type parameters.
1360 bool IsGeneric() const {
1361 // If the declaration is not loaded, fall back onto NumTypeParameters.
1362 if (!is_declaration_loaded()) {
1363 return NumTypeParameters(Thread::Current()) > 0;
1364 }
1365 return type_parameters() != Object::null();
1366 }
1367
1368 // Returns a canonicalized vector of the type parameters instantiated
1369 // to bounds (e.g., the type arguments used if no TAV is provided for class
1370 // instantiation).
1371 //
1372 // If non-generic, the empty type arguments vector is returned.
1373 TypeArgumentsPtr DefaultTypeArguments(Zone* zone) const;
1374
1375 // If this class is parameterized, each instance has a type_arguments field.
1376 static constexpr intptr_t kNoTypeArguments = -1;
1379 if (untag()->host_type_arguments_field_offset_in_words_ ==
1381 return kNoTypeArguments;
1382 }
1383 return untag()->host_type_arguments_field_offset_in_words_ *
1385 }
1387#if defined(DART_PRECOMPILER)
1389 if (untag()->target_type_arguments_field_offset_in_words_ ==
1390 compiler::target::Class::kNoTypeArguments) {
1391 return compiler::target::Class::kNoTypeArguments;
1392 }
1393 return untag()->target_type_arguments_field_offset_in_words_ *
1394 compiler::target::kCompressedWordSize;
1395#else
1397#endif // defined(DART_PRECOMPILER)
1398 }
1399 void set_type_arguments_field_offset(intptr_t host_value_in_bytes,
1400 intptr_t target_value_in_bytes) const {
1401 intptr_t host_value, target_value;
1402 if (host_value_in_bytes == kNoTypeArguments ||
1403 target_value_in_bytes == RTN::Class::kNoTypeArguments) {
1404 ASSERT(host_value_in_bytes == kNoTypeArguments &&
1405 target_value_in_bytes == RTN::Class::kNoTypeArguments);
1406 host_value = kNoTypeArguments;
1407 target_value = RTN::Class::kNoTypeArguments;
1408 } else {
1409 ASSERT(kCompressedWordSize != 0 && compiler::target::kCompressedWordSize);
1410 host_value = host_value_in_bytes / kCompressedWordSize;
1411 target_value =
1412 target_value_in_bytes / compiler::target::kCompressedWordSize;
1413 }
1414 set_type_arguments_field_offset_in_words(host_value, target_value);
1415 }
1417 intptr_t target_value) const {
1418 StoreNonPointer(&untag()->host_type_arguments_field_offset_in_words_,
1419 host_value);
1420#if defined(DART_PRECOMPILER)
1421 StoreNonPointer(&untag()->target_type_arguments_field_offset_in_words_,
1422 target_value);
1423#else
1424 // Could be different only during cross-compilation.
1425 ASSERT_EQUAL(host_value, target_value);
1426#endif // defined(DART_PRECOMPILER)
1427 }
1429 return OFFSET_OF(UntaggedClass, host_type_arguments_field_offset_in_words_);
1430 }
1431
1432 // The super type of this class, Object type if not explicitly specified.
1433 TypePtr super_type() const {
1435 return untag()->super_type();
1436 }
1437 void set_super_type(const Type& value) const;
1438 static intptr_t super_type_offset() {
1439 return OFFSET_OF(UntaggedClass, super_type_);
1440 }
1441
1442 // Asserts that the class of the super type has been resolved.
1443 // If |class_table| is provided it will be used to resolve class id to the
1444 // actual class object, instead of using current class table on the isolate
1445 // group.
1446 ClassPtr SuperClass(ClassTable* class_table = nullptr) const;
1447
1448 // Interfaces is an array of Types.
1449 ArrayPtr interfaces() const {
1451 return untag()->interfaces();
1452 }
1453 void set_interfaces(const Array& value) const;
1454
1455 // Returns whether a path from [this] to [cls] can be found, where the first
1456 // element is a direct supertype of [this], each following element is a direct
1457 // supertype of the previous element and the final element has [cls] as its
1458 // type class. If [this] and [cls] are the same class, then the path is empty.
1459 //
1460 // If [path] is not nullptr, then the elements of the path are added to it.
1461 // This path can then be used to compute type arguments of [cls] given type
1462 // arguments for an instance of [this].
1463 //
1464 // Note: There may be multiple paths to [cls], but the result of applying each
1465 // path must be equal to the other results.
1466 bool FindInstantiationOf(Zone* zone,
1467 const Class& cls,
1469 bool consider_only_super_classes = false) const;
1471 const Class& cls,
1472 bool consider_only_super_classes = false) const {
1473 return FindInstantiationOf(zone, cls, /*path=*/nullptr,
1474 consider_only_super_classes);
1475 }
1476
1477 // Returns whether a path from [this] to [type] can be found, where the first
1478 // element is a direct supertype of [this], each following element is a direct
1479 // supertype of the previous element and the final element has the same type
1480 // class as [type]. If [this] is the type class of [type], then the path is
1481 // empty.
1482 //
1483 // If [path] is not nullptr, then the elements of the path are added to it.
1484 // This path can then be used to compute type arguments of [type]'s type
1485 // class given type arguments for an instance of [this].
1486 //
1487 // Note: There may be multiple paths to [type]'s type class, but the result of
1488 // applying each path must be equal to the other results.
1489 bool FindInstantiationOf(Zone* zone,
1490 const Type& type,
1492 bool consider_only_super_classes = false) const;
1494 const Type& type,
1495 bool consider_only_super_classes = false) const {
1496 return FindInstantiationOf(zone, type, /*path=*/nullptr,
1497 consider_only_super_classes);
1498 }
1499
1500 // If [this] is a subtype of a type with type class [cls], then this
1501 // returns [cls]<X_0, ..., X_n>, where n is the number of type arguments for
1502 // [cls] and where each type argument X_k is either instantiated or has free
1503 // class type parameters corresponding to the type parameters of [this].
1504 // Thus, given an instance of [this], the result can be instantiated
1505 // with the instance type arguments to get the type of the instance.
1506 //
1507 // If [this] is not a subtype of a type with type class [cls], returns null.
1508 TypePtr GetInstantiationOf(Zone* zone, const Class& cls) const;
1509
1510 // If [this] is a subtype of [type], then this returns [cls]<X_0, ..., X_n>,
1511 // where [cls] is the type class of [type], n is the number of type arguments
1512 // for [cls], and where each type argument X_k is either instantiated or has
1513 // free class type parameters corresponding to the type parameters of [this].
1514 // Thus, given an instance of [this], the result can be instantiated with the
1515 // instance type arguments to get the type of the instance.
1516 //
1517 // If [this] is not a subtype of a type with type class [cls], returns null.
1518 TypePtr GetInstantiationOf(Zone* zone, const Type& type) const;
1519
1520#if !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
1521 // Returns the list of classes directly implementing this class.
1522 GrowableObjectArrayPtr direct_implementors() const {
1524 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
1525 return untag()->direct_implementors();
1526 }
1527 GrowableObjectArrayPtr direct_implementors_unsafe() const {
1528 return untag()->direct_implementors();
1529 }
1530#endif // !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
1531
1532#if !defined(DART_PRECOMPILED_RUNTIME)
1533 void set_direct_implementors(const GrowableObjectArray& implementors) const;
1534 void AddDirectImplementor(const Class& subclass, bool is_mixin) const;
1535#endif // !defined(DART_PRECOMPILED_RUNTIME)
1536
1537#if !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
1538 // Returns the list of classes having this class as direct superclass.
1539 GrowableObjectArrayPtr direct_subclasses() const {
1541 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
1542 return direct_subclasses_unsafe();
1543 }
1544 GrowableObjectArrayPtr direct_subclasses_unsafe() const {
1545 return untag()->direct_subclasses();
1546 }
1547#endif // !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
1548
1549#if !defined(DART_PRECOMPILED_RUNTIME)
1550 void set_direct_subclasses(const GrowableObjectArray& subclasses) const;
1551 void AddDirectSubclass(const Class& subclass) const;
1552#endif // !defined(DART_PRECOMPILED_RUNTIME)
1553
1554 // Check if this class represents the class of null.
1555 bool IsNullClass() const { return id() == kNullCid; }
1556
1557 // Check if this class represents the 'dynamic' class.
1558 bool IsDynamicClass() const { return id() == kDynamicCid; }
1559
1560 // Check if this class represents the 'void' class.
1561 bool IsVoidClass() const { return id() == kVoidCid; }
1562
1563 // Check if this class represents the 'Never' class.
1564 bool IsNeverClass() const { return id() == kNeverCid; }
1565
1566 // Check if this class represents the 'Object' class.
1567 bool IsObjectClass() const { return id() == kInstanceCid; }
1568
1569 // Check if this class represents the 'Function' class.
1570 bool IsDartFunctionClass() const;
1571
1572 // Check if this class represents the 'Future' class.
1573 bool IsFutureClass() const;
1574
1575 // Check if this class represents the 'FutureOr' class.
1576 bool IsFutureOrClass() const { return id() == kFutureOrCid; }
1577
1578 // Check if this class represents the 'Closure' class.
1579 bool IsClosureClass() const { return id() == kClosureCid; }
1580 static bool IsClosureClass(ClassPtr cls) {
1581 return GetClassId(cls) == kClosureCid;
1582 }
1583
1584 // Check if this class represents the 'Record' class.
1585 bool IsRecordClass() const { return id() == kRecordCid; }
1586
1587 static bool IsInFullSnapshot(ClassPtr cls) {
1588 NoSafepointScope no_safepoint;
1590 cls->untag()->library()->untag()->flags_);
1591 }
1592
1593 static intptr_t GetClassId(ClassPtr cls) {
1594 NoSafepointScope no_safepoint;
1595 return cls->untag()->id_;
1596 }
1597
1598 // Returns true if the type specified by cls, type_arguments, and nullability
1599 // is a subtype of the other type.
1600 static bool IsSubtypeOf(
1601 const Class& cls,
1602 const TypeArguments& type_arguments,
1603 Nullability nullability,
1604 const AbstractType& other,
1605 Heap::Space space,
1606 FunctionTypeMapping* function_type_equivalence = nullptr);
1607
1608 // Check if this is the top level class.
1609 bool IsTopLevel() const;
1610
1611 bool IsPrivate() const;
1612
1614 ErrorPtr VerifyEntryPoint() const;
1615
1616 // Returns an array of instance and static fields defined by this class.
1617 ArrayPtr fields() const {
1618 // We rely on the fact that any loads from the array are dependent loads
1619 // and avoid the load-acquire barrier here.
1620 return untag()->fields();
1621 }
1622 void SetFields(const Array& value) const;
1623 void AddField(const Field& field) const;
1624 void AddFields(const GrowableArray<const Field*>& fields) const;
1625
1626 intptr_t FindFieldIndex(const Field& needle) const;
1627 FieldPtr FieldFromIndex(intptr_t idx) const;
1628
1629 // If this is a dart:internal.ClassID class, then inject our own const
1630 // fields. Returns true if synthetic fields are injected and regular
1631 // field declarations should be ignored.
1632 bool InjectCIDFields() const;
1633
1634 // Returns an array of all instance fields of this class and its superclasses
1635 // indexed by offset in words.
1636 // If |class_table| is provided it will be used to resolve super classes by
1637 // class id, instead of the current class_table stored in the isolate.
1638 ArrayPtr OffsetToFieldMap(ClassTable* class_table = nullptr) const;
1639
1640 // Returns true if non-static fields are defined.
1641 bool HasInstanceFields() const;
1642
1643 ArrayPtr current_functions() const {
1644 // We rely on the fact that any loads from the array are dependent loads
1645 // and avoid the load-acquire barrier here.
1646 return untag()->functions();
1647 }
1648 ArrayPtr functions() const {
1650 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
1651 return current_functions();
1652 }
1653 void SetFunctions(const Array& value) const;
1654 void AddFunction(const Function& function) const;
1655 intptr_t FindFunctionIndex(const Function& needle) const;
1656 FunctionPtr FunctionFromIndex(intptr_t idx) const;
1657 intptr_t FindImplicitClosureFunctionIndex(const Function& needle) const;
1658 FunctionPtr ImplicitClosureFunctionFromIndex(intptr_t idx) const;
1659
1660 FunctionPtr LookupFunctionReadLocked(const String& name) const;
1661 FunctionPtr LookupDynamicFunctionUnsafe(const String& name) const;
1662
1663 FunctionPtr LookupDynamicFunctionAllowPrivate(const String& name) const;
1664 FunctionPtr LookupStaticFunction(const String& name) const;
1665 FunctionPtr LookupStaticFunctionAllowPrivate(const String& name) const;
1666 FunctionPtr LookupConstructor(const String& name) const;
1667 FunctionPtr LookupConstructorAllowPrivate(const String& name) const;
1668 FunctionPtr LookupFactory(const String& name) const;
1669 FunctionPtr LookupFactoryAllowPrivate(const String& name) const;
1670 FunctionPtr LookupFunctionAllowPrivate(const String& name) const;
1671 FunctionPtr LookupGetterFunction(const String& name) const;
1672 FunctionPtr LookupSetterFunction(const String& name) const;
1673 FieldPtr LookupInstanceField(const String& name) const;
1674 FieldPtr LookupStaticField(const String& name) const;
1675 FieldPtr LookupField(const String& name) const;
1676 FieldPtr LookupFieldAllowPrivate(const String& name,
1677 bool instance_only = false) const;
1678 FieldPtr LookupInstanceFieldAllowPrivate(const String& name) const;
1679 FieldPtr LookupStaticFieldAllowPrivate(const String& name) const;
1680
1681 // The methods above are more efficient than this generic one.
1682 InstancePtr LookupCanonicalInstance(Zone* zone, const Instance& value) const;
1683
1684 InstancePtr InsertCanonicalConstant(Zone* zone,
1685 const Instance& constant) const;
1686
1687 static intptr_t InstanceSize() {
1688 return RoundedAllocationSize(sizeof(UntaggedClass));
1689 }
1690
1691 // Returns true if any class implements this interface via `implements`.
1692 // Returns false if all possible implementations of this interface must be
1693 // instances of this class or its subclasses.
1694 bool is_implemented() const { return ImplementedBit::decode(state_bits()); }
1695 void set_is_implemented() const;
1696 void set_is_implemented_unsafe() const;
1697
1698 bool is_abstract() const { return AbstractBit::decode(state_bits()); }
1699 void set_is_abstract() const;
1700
1704
1708 void set_is_declaration_loaded() const;
1710
1714 void set_is_type_finalized() const;
1715
1717 return SynthesizedClassBit::decode(state_bits());
1718 }
1719 void set_is_synthesized_class() const;
1721
1722 bool is_enum_class() const { return EnumBit::decode(state_bits()); }
1723 void set_is_enum_class() const;
1724
1725 bool is_finalized() const {
1726 return ClassFinalizedBits::decode(state_bits()) ==
1728 ClassFinalizedBits::decode(state_bits()) ==
1730 }
1731 void set_is_finalized() const;
1732 void set_is_finalized_unsafe() const;
1733
1735 return ClassFinalizedBits::decode(state_bits()) ==
1737 }
1738 void set_is_allocate_finalized() const;
1739
1740 bool is_prefinalized() const {
1741 return ClassFinalizedBits::decode(state_bits()) ==
1743 }
1744
1745 void set_is_prefinalized() const;
1746
1747 bool is_const() const { return ConstBit::decode(state_bits()); }
1748 void set_is_const() const;
1749
1750 // Tests if this is a mixin application class which was desugared
1751 // to a normal class by kernel mixin transformation
1752 // (pkg/kernel/lib/transformations/mixin_full_resolution.dart).
1753 //
1754 // In such case, its mixed-in type was pulled into the end of
1755 // interfaces list.
1757 return TransformedMixinApplicationBit::decode(state_bits());
1758 }
1760
1761 bool is_sealed() const { return SealedBit::decode(state_bits()); }
1762 void set_is_sealed() const;
1763
1764 bool is_mixin_class() const { return MixinClassBit::decode(state_bits()); }
1765 void set_is_mixin_class() const;
1766
1767 bool is_base_class() const { return BaseClassBit::decode(state_bits()); }
1768 void set_is_base_class() const;
1769
1770 bool is_interface_class() const {
1771 return InterfaceClassBit::decode(state_bits());
1772 }
1773 void set_is_interface_class() const;
1774
1775 bool is_final() const { return FinalBit::decode(state_bits()); }
1776 void set_is_final() const;
1777
1779 return FieldsMarkedNullableBit::decode(state_bits());
1780 }
1781 void set_is_fields_marked_nullable() const;
1782
1783 bool is_allocated() const { return IsAllocatedBit::decode(state_bits()); }
1784 void set_is_allocated(bool value) const;
1785 void set_is_allocated_unsafe(bool value) const;
1786
1787 bool is_loaded() const { return IsLoadedBit::decode(state_bits()); }
1788 void set_is_loaded(bool value) const;
1789
1790 uint16_t num_native_fields() const { return untag()->num_native_fields_; }
1791 void set_num_native_fields(uint16_t value) const {
1792 StoreNonPointer(&untag()->num_native_fields_, value);
1793 }
1794 static uint16_t NumNativeFieldsOf(ClassPtr clazz) {
1795 return clazz->untag()->num_native_fields_;
1796 }
1797 static bool IsIsolateUnsendable(ClassPtr clazz) {
1798 return IsIsolateUnsendableBit::decode(clazz->untag()->state_bits_);
1799 }
1800
1801#if !defined(DART_PRECOMPILED_RUNTIME)
1802 CodePtr allocation_stub() const { return untag()->allocation_stub(); }
1803 void set_allocation_stub(const Code& value) const;
1804#endif // !defined(DART_PRECOMPILED_RUNTIME)
1805
1806 intptr_t kernel_offset() const {
1807#if defined(DART_PRECOMPILED_RUNTIME)
1808 return 0;
1809#else
1810 return untag()->kernel_offset_;
1811#endif
1812 }
1813
1814 void set_kernel_offset(intptr_t value) const {
1815#if defined(DART_PRECOMPILED_RUNTIME)
1816 UNREACHABLE();
1817#else
1818 ASSERT(value >= 0);
1819 StoreNonPointer(&untag()->kernel_offset_, value);
1820#endif
1821 }
1822
1823 void DisableAllocationStub() const;
1824
1825 ArrayPtr constants() const;
1826 void set_constants(const Array& value) const;
1827
1828 intptr_t FindInvocationDispatcherFunctionIndex(const Function& needle) const;
1829 FunctionPtr InvocationDispatcherFunctionFromIndex(intptr_t idx) const;
1830
1831 FunctionPtr GetInvocationDispatcher(const String& target_name,
1832 const Array& args_desc,
1834 bool create_if_absent) const;
1835
1836 FunctionPtr GetRecordFieldGetter(const String& getter_name) const;
1837
1838 void Finalize() const;
1839
1840 ObjectPtr Invoke(const String& selector,
1841 const Array& arguments,
1842 const Array& argument_names,
1843 bool respect_reflectable = true,
1844 bool check_is_entrypoint = false) const;
1845 ObjectPtr InvokeGetter(const String& selector,
1846 bool throw_nsm_if_absent,
1847 bool respect_reflectable = true,
1848 bool check_is_entrypoint = false) const;
1849 ObjectPtr InvokeSetter(const String& selector,
1850 const Instance& argument,
1851 bool respect_reflectable = true,
1852 bool check_is_entrypoint = false) const;
1853
1854 // Evaluate the given expression as if it appeared in a static method of this
1855 // class and return the resulting value, or an error object if evaluating the
1856 // expression fails. The method has the formal (type) parameters given in
1857 // (type_)param_names, and is invoked with the (type)argument values given in
1858 // (type_)param_values.
1860 const ExternalTypedData& kernel_buffer,
1861 const Array& type_definitions,
1862 const Array& param_values,
1863 const TypeArguments& type_param_values) const;
1864
1865 // Load class declaration (super type, interfaces, type parameters and
1866 // number of type arguments) if it is not loaded yet.
1867 void EnsureDeclarationLoaded() const;
1868
1869 ErrorPtr EnsureIsFinalized(Thread* thread) const;
1870 ErrorPtr EnsureIsAllocateFinalized(Thread* thread) const;
1871
1872 // Allocate a class used for VM internal objects.
1873 template <class FakeObject, class TargetFakeObject>
1874 static ClassPtr New(IsolateGroup* isolate_group, bool register_class = true);
1875
1876 // Allocate instance classes.
1877 static ClassPtr New(const Library& lib,
1878 const String& name,
1879 const Script& script,
1881 bool register_class = true);
1882 static ClassPtr NewNativeWrapper(const Library& library,
1883 const String& name,
1884 int num_fields);
1885
1886 // Allocate the raw string classes.
1887 static ClassPtr NewStringClass(intptr_t class_id,
1888 IsolateGroup* isolate_group);
1889
1890 // Allocate the raw TypedData classes.
1891 static ClassPtr NewTypedDataClass(intptr_t class_id,
1892 IsolateGroup* isolate_group);
1893
1894 // Allocate the raw TypedDataView/ByteDataView classes.
1895 static ClassPtr NewTypedDataViewClass(intptr_t class_id,
1896 IsolateGroup* isolate_group);
1897 static ClassPtr NewUnmodifiableTypedDataViewClass(
1898 intptr_t class_id,
1899 IsolateGroup* isolate_group);
1900
1901 // Allocate the raw ExternalTypedData classes.
1902 static ClassPtr NewExternalTypedDataClass(intptr_t class_id,
1903 IsolateGroup* isolate);
1904
1905 // Allocate the raw Pointer classes.
1906 static ClassPtr NewPointerClass(intptr_t class_id,
1907 IsolateGroup* isolate_group);
1908
1909#if !defined(DART_PRECOMPILED_RUNTIME)
1910 // Register code that has used CHA for optimization.
1911 // TODO(srdjan): Also register kind of CHA optimization (e.g.: leaf class,
1912 // leaf method, ...).
1913 void RegisterCHACode(const Code& code);
1914
1915 void DisableCHAOptimizedCode(const Class& subclass);
1916
1918
1920
1921 // Return the list of code objects that were compiled using CHA of this class.
1922 // These code objects will be invalidated if new subclasses of this class
1923 // are finalized.
1924 WeakArrayPtr dependent_code() const;
1925 void set_dependent_code(const WeakArray& array) const;
1926#endif // !defined(DART_PRECOMPILED_RUNTIME)
1927
1928 bool TraceAllocation(IsolateGroup* isolate_group) const;
1929 void SetTraceAllocation(bool trace_allocation) const;
1930
1931 void CopyStaticFieldValues(ProgramReloadContext* reload_context,
1932 const Class& old_cls) const;
1933 void PatchFieldsAndFunctions() const;
1935 const Class& new_cls) const;
1936 void CopyCanonicalConstants(const Class& old_cls) const;
1937 void CopyDeclarationType(const Class& old_cls) const;
1938 void CheckReload(const Class& replacement,
1939 ProgramReloadContext* context) const;
1940
1941 void AddInvocationDispatcher(const String& target_name,
1942 const Array& args_desc,
1943 const Function& dispatcher) const;
1944
1945 static int32_t host_instance_size_in_words(const ClassPtr cls) {
1946 return cls->untag()->host_instance_size_in_words_;
1947 }
1948
1949 static int32_t target_instance_size_in_words(const ClassPtr cls) {
1950#if defined(DART_PRECOMPILER)
1951 return cls->untag()->target_instance_size_in_words_;
1952#else
1953 return host_instance_size_in_words(cls);
1954#endif // defined(DART_PRECOMPILER)
1955 }
1956
1957 static int32_t host_next_field_offset_in_words(const ClassPtr cls) {
1958 return cls->untag()->host_next_field_offset_in_words_;
1959 }
1960
1961 static int32_t target_next_field_offset_in_words(const ClassPtr cls) {
1962#if defined(DART_PRECOMPILER)
1963 return cls->untag()->target_next_field_offset_in_words_;
1964#else
1966#endif // defined(DART_PRECOMPILER)
1967 }
1968
1969 static int32_t host_type_arguments_field_offset_in_words(const ClassPtr cls) {
1970 return cls->untag()->host_type_arguments_field_offset_in_words_;
1971 }
1972
1974 const ClassPtr cls) {
1975#if defined(DART_PRECOMPILER)
1976 return cls->untag()->target_type_arguments_field_offset_in_words_;
1977#else
1979#endif // defined(DART_PRECOMPILER)
1980 }
1981
1982 static intptr_t UnboxedFieldSizeInBytesByCid(intptr_t cid);
1983 void MarkFieldBoxedDuringReload(ClassTable* class_table,
1984 const Field& field) const;
1985
1986#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
1988#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
1989
1990 private:
1991 TypePtr declaration_type() const {
1992 return untag()->declaration_type<std::memory_order_acquire>();
1993 }
1994
1995 // Caches the declaration type of this class.
1996 void set_declaration_type(const Type& type) const;
1997
1998 TypeArgumentsPtr declaration_instance_type_arguments() const {
1999 return untag()
2000 ->declaration_instance_type_arguments<std::memory_order_acquire>();
2001 }
2002 void set_declaration_instance_type_arguments(
2003 const TypeArguments& value) const;
2004
2005 bool CanReloadFinalized(const Class& replacement,
2006 ProgramReloadContext* context) const;
2007 bool CanReloadPreFinalized(const Class& replacement,
2008 ProgramReloadContext* context) const;
2009
2010 // Tells whether instances need morphing for reload.
2011 bool RequiresInstanceMorphing(ClassTable* class_table,
2012 const Class& replacement) const;
2013
2014 template <class FakeInstance, class TargetFakeInstance>
2015 static ClassPtr NewCommon(intptr_t index);
2016
2017 enum MemberKind {
2018 kAny = 0,
2019 kStatic,
2020 kInstance,
2021 kInstanceAllowAbstract,
2022 kConstructor,
2023 kFactory,
2024 };
2025 enum StateBits {
2026 kConstBit = 0,
2027 kImplementedBit = 1,
2028 kClassFinalizedPos = 2,
2029 kClassFinalizedSize = 2,
2030 kClassLoadingPos = kClassFinalizedPos + kClassFinalizedSize, // = 4
2031 kClassLoadingSize = 2,
2032 kAbstractBit = kClassLoadingPos + kClassLoadingSize, // = 6
2033 kSynthesizedClassBit,
2034 kMixinAppAliasBit,
2035 kMixinTypeAppliedBit,
2036 kFieldsMarkedNullableBit,
2037 kEnumBit,
2038 kTransformedMixinApplicationBit,
2039 kIsAllocatedBit,
2040 kIsLoadedBit,
2041 kHasPragmaBit,
2042 kSealedBit,
2043 kMixinClassBit,
2044 kBaseClassBit,
2045 kInterfaceClassBit,
2046 kFinalBit,
2047 // Whether instances of the class cannot be sent across ports.
2048 //
2049 // Will be true iff
2050 // - class is marked with `@pragma('vm:isolate-unsendable')
2051 // - super class / super interface classes are marked as unsendable.
2052 // - class has native fields.
2053 kIsIsolateUnsendableBit,
2054 // True if this class has `@pragma('vm:isolate-unsendable')` annotation or
2055 // base class or implemented interfaces has this bit.
2056 kIsIsolateUnsendableDueToPragmaBit,
2057 // Will be set to 1 for the following classes:
2058 //
2059 // 1. Deeply immutable class.
2060 // a. Statically guaranteed deeply immutable classes.
2061 // `@pragma('vm:deeply-immutable')`.
2062 // b. VM recognized deeply immutable classes.
2063 // `IsDeeplyImmutableCid(intptr_t predefined_cid)`.
2064 //
2065 // See also ImmutableBit in raw_object.h.
2066 kIsDeeplyImmutableBit,
2067 // This class is a subtype of Future.
2068 kIsFutureSubtypeBit,
2069 // This class has a non-abstract subtype which is a subtype of Future.
2070 // It means that variable of static type based on this class may hold
2071 // a Future instance.
2072 kCanBeFutureBit,
2073 };
2074 class ConstBit : public BitField<uint32_t, bool, kConstBit, 1> {};
2075 class ImplementedBit : public BitField<uint32_t, bool, kImplementedBit, 1> {};
2076 class ClassFinalizedBits : public BitField<uint32_t,
2077 UntaggedClass::ClassFinalizedState,
2078 kClassFinalizedPos,
2079 kClassFinalizedSize> {};
2080 class ClassLoadingBits : public BitField<uint32_t,
2081 UntaggedClass::ClassLoadingState,
2082 kClassLoadingPos,
2083 kClassLoadingSize> {};
2084 class AbstractBit : public BitField<uint32_t, bool, kAbstractBit, 1> {};
2085 class SynthesizedClassBit
2086 : public BitField<uint32_t, bool, kSynthesizedClassBit, 1> {};
2087 class FieldsMarkedNullableBit
2088 : public BitField<uint32_t, bool, kFieldsMarkedNullableBit, 1> {};
2089 class EnumBit : public BitField<uint32_t, bool, kEnumBit, 1> {};
2090 class TransformedMixinApplicationBit
2091 : public BitField<uint32_t, bool, kTransformedMixinApplicationBit, 1> {};
2092 class IsAllocatedBit : public BitField<uint32_t, bool, kIsAllocatedBit, 1> {};
2093 class IsLoadedBit : public BitField<uint32_t, bool, kIsLoadedBit, 1> {};
2094 class HasPragmaBit : public BitField<uint32_t, bool, kHasPragmaBit, 1> {};
2095 class SealedBit : public BitField<uint32_t, bool, kSealedBit, 1> {};
2096 class MixinClassBit : public BitField<uint32_t, bool, kMixinClassBit, 1> {};
2097 class BaseClassBit : public BitField<uint32_t, bool, kBaseClassBit, 1> {};
2098 class InterfaceClassBit
2099 : public BitField<uint32_t, bool, kInterfaceClassBit, 1> {};
2100 class FinalBit : public BitField<uint32_t, bool, kFinalBit, 1> {};
2101 class IsIsolateUnsendableBit
2102 : public BitField<uint32_t, bool, kIsIsolateUnsendableBit, 1> {};
2103 class IsIsolateUnsendableDueToPragmaBit
2104 : public BitField<uint32_t, bool, kIsIsolateUnsendableDueToPragmaBit, 1> {
2105 };
2106 class IsDeeplyImmutableBit
2107 : public BitField<uint32_t, bool, kIsDeeplyImmutableBit, 1> {};
2108 class IsFutureSubtypeBit
2109 : public BitField<uint32_t, bool, kIsFutureSubtypeBit, 1> {};
2110 class CanBeFutureBit : public BitField<uint32_t, bool, kCanBeFutureBit, 1> {};
2111
2112 void set_name(const String& value) const;
2113 void set_user_name(const String& value) const;
2114 const char* GenerateUserVisibleName() const;
2115 void set_state_bits(intptr_t bits) const;
2116 void set_implementor_cid(intptr_t value) const;
2117
2118 FunctionPtr CreateInvocationDispatcher(const String& target_name,
2119 const Array& args_desc,
2120 UntaggedFunction::Kind kind) const;
2121
2122 FunctionPtr CreateRecordFieldGetter(const String& getter_name) const;
2123
2124 // Returns the bitmap of unboxed fields
2125 UnboxedFieldBitmap CalculateFieldOffsets() const;
2126
2127 // functions_hash_table is in use iff there are at least this many functions.
2128 static constexpr intptr_t kFunctionLookupHashThreshold = 16;
2129
2130 // Initial value for the cached number of type arguments.
2131 static constexpr intptr_t kUnknownNumTypeArguments = -1;
2132
2133 int16_t num_type_arguments() const {
2134 return LoadNonPointer<int16_t, std::memory_order_relaxed>(
2135 &untag()->num_type_arguments_);
2136 }
2137
2138 uint32_t state_bits() const {
2139 // Ensure any following load instructions do not get performed before this
2140 // one.
2141 return LoadNonPointer<uint32_t, std::memory_order_acquire>(
2142 &untag()->state_bits_);
2143 }
2144
2145 public:
2146 void set_num_type_arguments(intptr_t value) const;
2147 void set_num_type_arguments_unsafe(intptr_t value) const;
2148
2149 bool has_pragma() const { return HasPragmaBit::decode(state_bits()); }
2150 void set_has_pragma(bool value) const;
2151
2152 void set_is_isolate_unsendable(bool value) const;
2154 ASSERT(is_finalized()); // This bit is initialized in class finalizer.
2155 return IsIsolateUnsendableBit::decode(state_bits());
2156 }
2157
2158 void set_is_isolate_unsendable_due_to_pragma(bool value) const;
2162
2163 void set_is_deeply_immutable(bool value) const;
2164 bool is_deeply_immutable() const {
2165 return IsDeeplyImmutableBit::decode(state_bits());
2166 }
2167 static bool IsDeeplyImmutable(ClassPtr clazz) {
2168 return IsDeeplyImmutableBit::decode(clazz->untag()->state_bits_);
2169 }
2170
2171 void set_is_future_subtype(bool value) const;
2172 bool is_future_subtype() const {
2174 return IsFutureSubtypeBit::decode(state_bits());
2175 }
2176
2177 void set_can_be_future(bool value) const;
2178 bool can_be_future() const { return CanBeFutureBit::decode(state_bits()); }
2179
2180 private:
2181 void set_functions(const Array& value) const;
2182 void set_fields(const Array& value) const;
2183 void set_invocation_dispatcher_cache(const Array& cache) const;
2184
2185 ArrayPtr invocation_dispatcher_cache() const;
2186
2187 // Calculates number of type arguments of this class.
2188 // This includes type arguments of a superclass and takes overlapping
2189 // of type arguments into account.
2190 intptr_t ComputeNumTypeArguments() const;
2191
2192 // Assigns empty array to all raw class array fields.
2193 void InitEmptyFields() const;
2194
2195 static FunctionPtr CheckFunctionType(const Function& func, MemberKind kind);
2196 FunctionPtr LookupFunctionReadLocked(const String& name,
2197 MemberKind kind) const;
2198 FunctionPtr LookupFunctionAllowPrivate(const String& name,
2199 MemberKind kind) const;
2200 FieldPtr LookupField(const String& name, MemberKind kind) const;
2201
2202 FunctionPtr LookupAccessorFunction(const char* prefix,
2203 intptr_t prefix_length,
2204 const String& name) const;
2205
2206 // Allocate an instance class which has a VM implementation.
2207 template <class FakeInstance, class TargetFakeInstance>
2208 static ClassPtr New(intptr_t id,
2209 IsolateGroup* isolate_group,
2210 bool register_class = true,
2211 bool is_abstract = false);
2212
2213 // Helper that calls 'Class::New<Instance>(kIllegalCid)'.
2214 static ClassPtr NewInstanceClass();
2215
2217 friend class AbstractType;
2218 friend class Instance;
2219 friend class Object;
2220 friend class Type;
2221 friend class Intrinsifier;
2222 friend class ProgramWalker;
2223 friend class Precompiler;
2224 friend class ClassFinalizer;
2225};
2226
2227// Classification of type genericity according to type parameter owners.
2229 kAny, // Consider type params of current class and functions.
2230 kCurrentClass, // Consider type params of current class only.
2231 kFunctions, // Consider type params of current and parent functions.
2232};
2233
2234// Wrapper of a [Class] with different [Script] and kernel binary.
2235//
2236// We use this as owner of [Field]/[Function] objects that were from a different
2237// script/kernel than the actual class object.
2238//
2239// * used for corelib patches that live in different .dart files than the
2240// library itself.
2241//
2242// * used for library parts that live in different .dart files than the library
2243// itself.
2244//
2245// * used in reload to make old [Function]/[Field] objects have the old script
2246// kernel data.
2247//
2248class PatchClass : public Object {
2249 public:
2250 ClassPtr wrapped_class() const { return untag()->wrapped_class(); }
2251 ScriptPtr script() const { return untag()->script(); }
2252
2253 intptr_t kernel_library_index() const {
2254#if !defined(DART_PRECOMPILED_RUNTIME)
2255 return untag()->kernel_library_index_;
2256#else
2257 return -1;
2258#endif
2259 }
2260 void set_kernel_library_index(intptr_t index) const {
2261 NOT_IN_PRECOMPILED(StoreNonPointer(&untag()->kernel_library_index_, index));
2262 }
2263
2264#if !defined(DART_PRECOMPILED_RUNTIME)
2265 KernelProgramInfoPtr kernel_program_info() const {
2266 return untag()->kernel_program_info();
2267 }
2269#endif
2270
2271 static intptr_t InstanceSize() {
2273 }
2274 static bool IsInFullSnapshot(PatchClassPtr cls) {
2275 NoSafepointScope no_safepoint;
2276 return Class::IsInFullSnapshot(cls->untag()->wrapped_class());
2277 }
2278
2279 static PatchClassPtr New(const Class& wrapped_class,
2280 const KernelProgramInfo& info,
2281 const Script& source);
2282
2283 private:
2284 void set_wrapped_class(const Class& value) const;
2285 void set_script(const Script& value) const;
2286
2287 static PatchClassPtr New();
2288
2290 friend class Class;
2291};
2292
2294 public:
2295 CodePtr target() const { return untag()->target(); }
2296 void set_target(const Code& target) const;
2297 static intptr_t target_offset() {
2298 return OFFSET_OF(UntaggedSingleTargetCache, target_);
2299 }
2300
2301#define DEFINE_NON_POINTER_FIELD_ACCESSORS(type, name) \
2302 type name() const { return untag()->name##_; } \
2303 void set_##name(type value) const { \
2304 StoreNonPointer(&untag()->name##_, value); \
2305 } \
2306 static intptr_t name##_offset() { \
2307 return OFFSET_OF(UntaggedSingleTargetCache, name##_); \
2308 }
2309
2313#undef DEFINE_NON_POINTER_FIELD_ACCESSORS
2314
2315 static intptr_t InstanceSize() {
2317 }
2318
2319 static SingleTargetCachePtr New();
2320
2321 private:
2323 friend class Class;
2324};
2325
2327 public:
2328 classid_t expected_cid() const { return untag()->expected_cid_; }
2329
2330 static intptr_t InstanceSize() {
2332 }
2333
2334 static MonomorphicSmiableCallPtr New(classid_t expected_cid,
2335 const Code& target);
2336
2337 static intptr_t expected_cid_offset() {
2338 return OFFSET_OF(UntaggedMonomorphicSmiableCall, expected_cid_);
2339 }
2340
2341 static intptr_t entrypoint_offset() {
2342 return OFFSET_OF(UntaggedMonomorphicSmiableCall, entrypoint_);
2343 }
2344
2345 private:
2347 friend class Class;
2348};
2349
2350class CallSiteData : public Object {
2351 public:
2352 StringPtr target_name() const { return untag()->target_name(); }
2353 ArrayPtr arguments_descriptor() const { return untag()->args_descriptor(); }
2354
2355 intptr_t TypeArgsLen() const;
2356
2357 intptr_t CountWithTypeArgs() const;
2358
2359 intptr_t CountWithoutTypeArgs() const;
2360
2361 intptr_t SizeWithoutTypeArgs() const;
2362
2363 intptr_t SizeWithTypeArgs() const;
2364
2365 static intptr_t target_name_offset() {
2366 return OFFSET_OF(UntaggedCallSiteData, target_name_);
2367 }
2368
2370 return OFFSET_OF(UntaggedCallSiteData, args_descriptor_);
2371 }
2372
2373 private:
2374 void set_target_name(const String& value) const;
2375 void set_arguments_descriptor(const Array& value) const;
2376
2378
2379 friend class ICData;
2380 friend class MegamorphicCache;
2381};
2382
2384 public:
2386 return untag()->can_patch_to_monomorphic_;
2387 }
2388
2389 static intptr_t InstanceSize() {
2391 }
2392
2393 uword Hash() const;
2394 bool Equals(const UnlinkedCall& other) const;
2395
2396 static UnlinkedCallPtr New();
2397
2398 private:
2399 friend class ICData; // For set_*() methods.
2400
2401 void set_can_patch_to_monomorphic(bool value) const;
2402
2404 friend class Class;
2405};
2406
2407// Object holding information about an IC: test classes and their
2408// corresponding targets. The owner of the ICData can be either the function
2409// or the original ICData object. In case of background compilation we
2410// copy the ICData in a child object, thus freezing it during background
2411// compilation. Code may contain only original ICData objects.
2412//
2413// ICData's backing store is an array that logically contains several valid
2414// entries followed by a sentinel entry.
2415//
2416// [<entry-0>, <...>, <entry-N>, <sentinel>]
2417//
2418// Each entry has the following form:
2419//
2420// [arg0?, arg1?, argN?, count, target-function/code, exactness?]
2421//
2422// The <entry-X> need to contain valid type feedback.
2423// The <sentinel> entry and must have kIllegalCid value for all
2424// members of the entry except for the last one (`exactness` if
2425// present, otherwise `target-function/code`) - which we use as a backref:
2426//
2427// * For empty ICData we use a cached/shared backing store. So there is no
2428// unique backref, we use kIllegalCid instead.
2429// * For non-empty ICData the backref in the backing store array will point to
2430// the ICData object.
2431//
2432// Updating the ICData happens under a lock to avoid phantom-reads. The backing
2433// is treated as an immutable Copy-on-Write data structure: Adding to the ICData
2434// makes a copy with length+1 which will be store-release'd so any reader can
2435// see it (and doesn't need to hold a lock).
2436class ICData : public CallSiteData {
2437 public:
2438 FunctionPtr Owner() const;
2439
2440 ICDataPtr Original() const;
2441
2442 void SetOriginal(const ICData& value) const;
2443
2444 bool IsOriginal() const { return Original() == this->ptr(); }
2445
2446 intptr_t NumArgsTested() const;
2447
2448 intptr_t deopt_id() const {
2449#if defined(DART_PRECOMPILED_RUNTIME)
2450 UNREACHABLE();
2451 return -1;
2452#else
2453 return untag()->deopt_id_;
2454#endif
2455 }
2456
2457 bool IsImmutable() const;
2458
2459#if !defined(DART_PRECOMPILED_RUNTIME)
2460 AbstractTypePtr receivers_static_type() const {
2461 return untag()->receivers_static_type();
2462 }
2464 return untag()->state_bits_.Read<TrackingExactnessBit>();
2465 }
2466#else
2467 bool is_tracking_exactness() const { return false; }
2468#endif
2469
2470// Note: only deopts with reasons before Unknown in this list are recorded in
2471// the ICData. All other reasons are used purely for informational messages
2472// printed during deoptimization itself.
2473#define DEOPT_REASONS(V) \
2474 V(BinarySmiOp) \
2475 V(BinaryInt64Op) \
2476 V(DoubleToSmi) \
2477 V(CheckSmi) \
2478 V(CheckClass) \
2479 V(Unknown) \
2480 V(PolymorphicInstanceCallTestFail) \
2481 V(UnaryInt64Op) \
2482 V(BinaryDoubleOp) \
2483 V(UnaryOp) \
2484 V(UnboxInteger) \
2485 V(Unbox) \
2486 V(CheckArrayBound) \
2487 V(AtCall) \
2488 V(GuardField) \
2489 V(TestCids) \
2490 V(NumReasons)
2491
2493#define DEFINE_ENUM_LIST(name) kDeopt##name,
2495#undef DEFINE_ENUM_LIST
2496 };
2497
2498 static constexpr intptr_t kLastRecordedDeoptReason = kDeoptUnknown - 1;
2499
2501 // Deoptimization is caused by an optimistically hoisted instruction.
2502 kHoisted = 1 << 0,
2503
2504 // Deoptimization is caused by an optimistically generalized bounds check.
2505 kGeneralized = 1 << 1
2507
2508 bool HasDeoptReasons() const { return DeoptReasons() != 0; }
2509 uint32_t DeoptReasons() const;
2510 void SetDeoptReasons(uint32_t reasons) const;
2511
2512 bool HasDeoptReason(ICData::DeoptReasonId reason) const;
2513 void AddDeoptReason(ICData::DeoptReasonId reason) const;
2514
2515 // Call site classification that is helpful for hot-reload. Call sites with
2516 // different `RebindRule` have to be rebound differently.
2517#define FOR_EACH_REBIND_RULE(V) \
2518 V(Instance) \
2519 V(NoRebind) \
2520 V(NSMDispatch) \
2521 V(Optimized) \
2522 V(Static) \
2523 V(Super)
2524
2526#define REBIND_ENUM_DEF(name) k##name,
2528#undef REBIND_ENUM_DEF
2530 };
2531 static const char* RebindRuleToCString(RebindRule r);
2532 static bool ParseRebindRule(const char* str, RebindRule* out);
2533 RebindRule rebind_rule() const;
2534
2535 void set_is_megamorphic(bool value) const {
2536 untag()->state_bits_.UpdateBool<MegamorphicBit, std::memory_order_release>(
2537 value);
2538 }
2539
2540 // The length of the array. This includes all sentinel entries including
2541 // the final one.
2542 intptr_t Length() const;
2543
2544 intptr_t NumberOfChecks() const;
2545
2546 // Discounts any checks with usage of zero.
2547 // Takes O(result)) time!
2548 intptr_t NumberOfUsedChecks() const;
2549
2550 bool NumberOfChecksIs(intptr_t n) const;
2551
2552 bool IsValidEntryIndex(intptr_t index) const {
2553 return 0 <= index && index < NumberOfChecks();
2554 }
2555
2556 static intptr_t InstanceSize() {
2557 return RoundedAllocationSize(sizeof(UntaggedICData));
2558 }
2559
2560 static intptr_t state_bits_offset() {
2561 return OFFSET_OF(UntaggedICData, state_bits_);
2562 }
2563
2564 static intptr_t NumArgsTestedShift() { return kNumArgsTestedPos; }
2565
2566 static intptr_t NumArgsTestedMask() {
2567 return ((1 << kNumArgsTestedSize) - 1) << kNumArgsTestedPos;
2568 }
2569
2570 static intptr_t entries_offset() {
2571 return OFFSET_OF(UntaggedICData, entries_);
2572 }
2573
2574 static intptr_t owner_offset() { return OFFSET_OF(UntaggedICData, owner_); }
2575
2576#if !defined(DART_PRECOMPILED_RUNTIME)
2578 return OFFSET_OF(UntaggedICData, receivers_static_type_);
2579 }
2580#endif
2581
2582 // NOTE: Can only be called during reload.
2583 void Clear(const CallSiteResetter& proof_of_reload) const {
2584 TruncateTo(0, proof_of_reload);
2585 }
2586
2587 // NOTE: Can only be called during reload.
2588 void TruncateTo(intptr_t num_checks,
2589 const CallSiteResetter& proof_of_reload) const;
2590
2591 // Clears the count for entry |index|.
2592 // NOTE: Can only be called during reload.
2593 void ClearCountAt(intptr_t index,
2594 const CallSiteResetter& proof_of_reload) const;
2595
2596 // Clear all entries with the sentinel value and reset the first entry
2597 // with the dummy target entry.
2598 // NOTE: Can only be called during reload.
2599 void ClearAndSetStaticTarget(const Function& func,
2600 const CallSiteResetter& proof_of_reload) const;
2601
2602 void DebugDump() const;
2603
2604 // Adding checks.
2605
2606 // Ensures there is a check for [class_ids].
2607 //
2608 // Calls [AddCheck] iff there is no existing check. Ensures test (and
2609 // potential update) will be performed under exclusive lock to guard against
2610 // multiple threads trying to add the same check.
2611 void EnsureHasCheck(const GrowableArray<intptr_t>& class_ids,
2612 const Function& target,
2613 intptr_t count = 1) const;
2614
2615 // Adds one more class test to ICData. Length of 'classes' must be equal to
2616 // the number of arguments tested. Use only for num_args_tested > 1.
2617 void AddCheck(const GrowableArray<intptr_t>& class_ids,
2618 const Function& target,
2619 intptr_t count = 1) const;
2620
2621 StaticTypeExactnessState GetExactnessAt(intptr_t count) const;
2622
2623 // Ensures there is a receiver check for [receiver_class_id].
2624 //
2625 // Calls [AddCheckReceiverCheck] iff there is no existing check. Ensures
2626 // test (and potential update) will be performed under exclusive lock to
2627 // guard against multiple threads trying to add the same check.
2628 void EnsureHasReceiverCheck(
2629 intptr_t receiver_class_id,
2630 const Function& target,
2631 intptr_t count = 1,
2632 StaticTypeExactnessState exactness =
2634
2635 // Adds sorted so that Smi is the first class-id. Use only for
2636 // num_args_tested == 1.
2637 void AddReceiverCheck(intptr_t receiver_class_id,
2638 const Function& target,
2639 intptr_t count = 1,
2640 StaticTypeExactnessState exactness =
2642
2643 // Retrieving checks.
2644
2645 void GetCheckAt(intptr_t index,
2646 GrowableArray<intptr_t>* class_ids,
2647 Function* target) const;
2648 void GetClassIdsAt(intptr_t index, GrowableArray<intptr_t>* class_ids) const;
2649
2650 // Only for 'num_args_checked == 1'.
2651 void GetOneClassCheckAt(intptr_t index,
2652 intptr_t* class_id,
2653 Function* target) const;
2654 // Only for 'num_args_checked == 1'.
2655 intptr_t GetCidAt(intptr_t index) const;
2656
2657 intptr_t GetReceiverClassIdAt(intptr_t index) const;
2658 intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;
2659
2660 FunctionPtr GetTargetAt(intptr_t index) const;
2661
2662 void IncrementCountAt(intptr_t index, intptr_t value) const;
2663 void SetCountAt(intptr_t index, intptr_t value) const;
2664 intptr_t GetCountAt(intptr_t index) const;
2665 intptr_t AggregateCount() const;
2666
2667 // Returns this->untag() if num_args_tested == 1 and arg_nr == 1, otherwise
2668 // returns a new ICData object containing only unique arg_nr checks.
2669 // Returns only used entries.
2670 ICDataPtr AsUnaryClassChecksForArgNr(intptr_t arg_nr) const;
2671 ICDataPtr AsUnaryClassChecks() const { return AsUnaryClassChecksForArgNr(0); }
2672
2673 // Returns ICData with aggregated receiver count, sorted by highest count.
2674 // Smi not first!! (the convention for ICData used in code generation is that
2675 // Smi check is first)
2676 // Used for printing and optimizations.
2677 ICDataPtr AsUnaryClassChecksSortedByCount() const;
2678
2679 UnlinkedCallPtr AsUnlinkedCall() const;
2680
2681 bool HasReceiverClassId(intptr_t class_id) const;
2682
2683 // Note: passing non-null receiver_type enables exactness tracking for
2684 // the receiver type. Receiver type is expected to be a fully
2685 // instantiated generic (but not a FutureOr).
2686 // See StaticTypeExactnessState for more information.
2687 static ICDataPtr New(
2688 const Function& owner,
2689 const String& target_name,
2691 intptr_t deopt_id,
2692 intptr_t num_args_tested,
2693 RebindRule rebind_rule,
2694 const AbstractType& receiver_type = Object::null_abstract_type());
2695
2696 // Similar to [New] makes the ICData have an initial (cids, target) entry.
2697 static ICDataPtr NewWithCheck(
2698 const Function& owner,
2699 const String& target_name,
2701 intptr_t deopt_id,
2702 intptr_t num_args_tested,
2703 RebindRule rebind_rule,
2705 const Function& target,
2706 const AbstractType& receiver_type = Object::null_abstract_type());
2707
2708 static ICDataPtr NewForStaticCall(const Function& owner,
2709 const Function& target,
2711 intptr_t deopt_id,
2712 intptr_t num_args_tested,
2713 RebindRule rebind_rule);
2714
2715 static ICDataPtr NewFrom(const ICData& from, intptr_t num_args_tested);
2716
2717 // Generates a new ICData with descriptor and data array copied (deep clone).
2718 static ICDataPtr Clone(const ICData& from);
2719
2720 // Gets the [ICData] from the [ICData::entries_] array (which stores a back
2721 // ref).
2722 //
2723 // May return `null` if the [ICData] is empty.
2724 static ICDataPtr ICDataOfEntriesArray(const Array& array);
2725
2726 static intptr_t TestEntryLengthFor(intptr_t num_args,
2727 bool tracking_exactness);
2728
2729 static intptr_t CountIndexFor(intptr_t num_args) { return num_args; }
2730 static intptr_t EntryPointIndexFor(intptr_t num_args) { return num_args; }
2731
2732 static intptr_t TargetIndexFor(intptr_t num_args) { return num_args + 1; }
2733 static intptr_t CodeIndexFor(intptr_t num_args) { return num_args + 1; }
2734
2735 static intptr_t ExactnessIndexFor(intptr_t num_args) { return num_args + 2; }
2736
2737 bool IsUsedAt(intptr_t i) const;
2738
2739 void PrintToJSONArray(const JSONArray& jsarray,
2740 TokenPosition token_pos) const;
2741
2742 // Initialize the preallocated empty ICData entry arrays.
2743 static void Init();
2744
2745 // Clear the preallocated empty ICData entry arrays.
2746 static void Cleanup();
2747
2748 // We cache ICData with 0, 1, 2 arguments tested without exactness
2749 // tracking and with 1 argument tested with exactness tracking.
2750 enum {
2751 kCachedICDataZeroArgTestedWithoutExactnessTrackingIdx = 0,
2752 kCachedICDataMaxArgsTestedWithoutExactnessTracking = 2,
2753 kCachedICDataOneArgWithExactnessTrackingIdx =
2754 kCachedICDataZeroArgTestedWithoutExactnessTrackingIdx +
2755 kCachedICDataMaxArgsTestedWithoutExactnessTracking + 1,
2756 kCachedICDataArrayCount = kCachedICDataOneArgWithExactnessTrackingIdx + 1,
2757 };
2758
2759 bool is_static_call() const;
2760
2761 intptr_t FindCheck(const GrowableArray<intptr_t>& cids) const;
2762
2763 ArrayPtr entries() const {
2764 return untag()->entries<std::memory_order_acquire>();
2765 }
2766
2768 return untag()->state_bits_.Read<ReceiverCannotBeSmiBit>();
2769 }
2770
2771 void set_receiver_cannot_be_smi(bool value) const {
2772 untag()->state_bits_.UpdateBool<ReceiverCannotBeSmiBit>(value);
2773 }
2774
2775 uword Hash() const;
2776
2777 private:
2778 static ICDataPtr New();
2779
2780 // Grows the array and also sets the argument to the index that should be used
2781 // for the new entry.
2782 ArrayPtr Grow(intptr_t* index) const;
2783
2784 void set_deopt_id(intptr_t value) const;
2785 void set_entries(const Array& value) const;
2786 void set_owner(const Function& value) const;
2787 void set_rebind_rule(uint32_t rebind_rule) const;
2788 void clear_state_bits() const;
2789 void set_tracking_exactness(bool value) const {
2790 untag()->state_bits_.UpdateBool<TrackingExactnessBit>(value);
2791 }
2792
2793 // Does entry |index| contain the sentinel value?
2794 void SetNumArgsTested(intptr_t value) const;
2795 void SetReceiversStaticType(const AbstractType& type) const;
2796 DEBUG_ONLY(void AssertInvariantsAreSatisfied() const;)
2797
2798 static void SetTargetAtPos(const Array& data,
2799 intptr_t data_pos,
2800 intptr_t num_args_tested,
2801 const Function& target);
2802 void AddCheckInternal(const GrowableArray<intptr_t>& class_ids,
2803 const Function& target,
2804 intptr_t count) const;
2805 void AddReceiverCheckInternal(intptr_t receiver_class_id,
2806 const Function& target,
2807 intptr_t count,
2808 StaticTypeExactnessState exactness) const;
2809
2810 // This bit is set when a call site becomes megamorphic and starts using a
2811 // MegamorphicCache instead of ICData. It means that the entries in the
2812 // ICData are incomplete and the MegamorphicCache needs to also be consulted
2813 // to list the call site's observed receiver classes and targets.
2814 // In the compiler, this should only be read once by CallTargets to avoid the
2815 // compiler seeing an unstable set of feedback.
2816 bool is_megamorphic() const {
2817 // Ensure any following load instructions do not get performed before this
2818 // one.
2819 return untag()
2820 ->state_bits_.Read<MegamorphicBit, std::memory_order_acquire>();
2821 }
2822
2823 bool ValidateInterceptor(const Function& target) const;
2824
2825 enum {
2826 kNumArgsTestedPos = 0,
2827 kNumArgsTestedSize = 2,
2828 kTrackingExactnessPos = kNumArgsTestedPos + kNumArgsTestedSize,
2829 kTrackingExactnessSize = 1,
2830 kDeoptReasonPos = kTrackingExactnessPos + kTrackingExactnessSize,
2831 kDeoptReasonSize = kLastRecordedDeoptReason + 1,
2832 kRebindRulePos = kDeoptReasonPos + kDeoptReasonSize,
2833 kRebindRuleSize = 3,
2834 kMegamorphicPos = kRebindRulePos + kRebindRuleSize,
2835 kMegamorphicSize = 1,
2836 kReceiverCannotBeSmiPos = kMegamorphicPos + kMegamorphicSize,
2837 kReceiverCannotBeSmiSize = 1,
2838 };
2839
2840 COMPILE_ASSERT(kReceiverCannotBeSmiPos + kReceiverCannotBeSmiSize <=
2841 sizeof(UntaggedICData::state_bits_) * kBitsPerWord);
2842 COMPILE_ASSERT(kNumRebindRules <= (1 << kRebindRuleSize));
2843
2844 class NumArgsTestedBits : public BitField<uint32_t,
2845 uint32_t,
2846 kNumArgsTestedPos,
2847 kNumArgsTestedSize> {};
2848 class TrackingExactnessBit : public BitField<uint32_t,
2849 bool,
2850 kTrackingExactnessPos,
2851 kTrackingExactnessSize> {};
2852 class DeoptReasonBits : public BitField<uint32_t,
2853 uint32_t,
2854 ICData::kDeoptReasonPos,
2855 ICData::kDeoptReasonSize> {};
2856 class RebindRuleBits : public BitField<uint32_t,
2857 uint32_t,
2858 ICData::kRebindRulePos,
2859 ICData::kRebindRuleSize> {};
2860 class MegamorphicBit
2861 : public BitField<uint32_t, bool, kMegamorphicPos, kMegamorphicSize> {};
2862
2863 class ReceiverCannotBeSmiBit : public BitField<uint32_t,
2864 bool,
2865 kReceiverCannotBeSmiPos,
2866 kReceiverCannotBeSmiSize> {};
2867
2868#if defined(DEBUG)
2869 // Used in asserts to verify that a check is not added twice.
2870 bool HasCheck(const GrowableArray<intptr_t>& cids) const;
2871#endif // DEBUG
2872
2873 intptr_t TestEntryLength() const;
2874 static ArrayPtr NewNonCachedEmptyICDataArray(intptr_t num_args_tested,
2875 bool tracking_exactness);
2876 static ArrayPtr CachedEmptyICDataArray(intptr_t num_args_tested,
2877 bool tracking_exactness);
2878 static bool IsCachedEmptyEntry(const Array& array);
2879 static ICDataPtr NewDescriptor(Zone* zone,
2880 const Function& owner,
2881 const String& target_name,
2882 const Array& arguments_descriptor,
2883 intptr_t deopt_id,
2884 intptr_t num_args_tested,
2885 RebindRule rebind_rule,
2886 const AbstractType& receiver_type);
2887
2888 static void WriteSentinel(const Array& data,
2889 intptr_t test_entry_length,
2890 const Object& back_ref);
2891
2892 // A cache of VM heap allocated preinitialized empty ic data entry arrays.
2893 static ArrayPtr cached_icdata_arrays_[kCachedICDataArrayCount];
2894
2896 friend class CallSiteResetter;
2897 friend class CallTargets;
2898 friend class Class;
2900 friend class ICDataTestTask;
2902};
2903
2904// Often used constants for number of free function type parameters.
2905enum {
2907
2908 // 'kCurrentAndEnclosingFree' is used when partially applying a signature
2909 // function to a set of type arguments. It indicates that the set of type
2910 // parameters declared by the current function and enclosing functions should
2911 // be considered free, and the current function type parameters should be
2912 // substituted as well.
2913 //
2914 // For instance, if the signature "<T>(T, R) => T" is instantiated with
2915 // function type arguments [int, String] and kCurrentAndEnclosingFree is
2916 // supplied, the result of the instantiation will be "(String, int) => int".
2918
2919 // Only parameters declared by enclosing functions are free.
2921};
2922
2923// Formatting configuration for Function::PrintName.
2927
2928 // By default function name includes the name of the enclosing class if any.
2929 // However in some contexts this information is redundant and class name
2930 // is already known. In this case setting |include_class_name| to false
2931 // allows you to exclude this information from the formatted name.
2932 bool include_class_name = true;
2933
2934 // By default function name includes the name of the enclosing function if
2935 // any. However in some contexts this information is redundant and
2936 // the name of the enclosing function is already known. In this case
2937 // setting |include_parent_name| to false allows to exclude this information
2938 // from the formatted name.
2939 bool include_parent_name = true;
2940
2942 Object::NameDisambiguation name_disambiguation =
2943 Object::NameDisambiguation::kNo)
2944 : name_visibility(visibility),
2945 disambiguate_names(name_disambiguation ==
2946 Object::NameDisambiguation::kYes) {}
2947
2949 Object::NameVisibility visibility) {
2950 NameFormattingParams params(visibility, Object::NameDisambiguation::kYes);
2951 params.include_class_name = false;
2952 return params;
2953 }
2954
2956 Object::NameVisibility visibility) {
2957 NameFormattingParams params(visibility, Object::NameDisambiguation::kYes);
2958 params.include_class_name = false;
2959 params.include_parent_name = false;
2960 return params;
2961 }
2962};
2963
2969
2970class Function : public Object {
2971 public:
2972 StringPtr name() const { return untag()->name(); }
2973 StringPtr UserVisibleName() const; // Same as scrubbed name.
2974 const char* UserVisibleNameCString() const;
2975
2976 const char* NameCString(NameVisibility name_visibility) const;
2977
2978 void PrintName(const NameFormattingParams& params,
2979 BaseTextBuffer* printer) const;
2980 StringPtr QualifiedScrubbedName() const;
2981 const char* QualifiedScrubbedNameCString() const;
2982 StringPtr QualifiedUserVisibleName() const;
2983 const char* QualifiedUserVisibleNameCString() const;
2984
2985 virtual StringPtr DictionaryName() const { return name(); }
2986
2987 StringPtr GetSource() const;
2988
2989 // Set the "C signature" for an FFI trampoline.
2990 // Can only be used on FFI trampolines.
2991 void SetFfiCSignature(const FunctionType& sig) const;
2992
2993 // Retrieves the "C signature" for an FFI trampoline or FFI native.
2994 FunctionTypePtr FfiCSignature() const;
2995
2996 bool FfiCSignatureContainsHandles() const;
2997 bool FfiCSignatureReturnsStruct() const;
2998
2999 // Can only be called on FFI trampolines.
3000 int32_t FfiCallbackId() const;
3001
3002 // Should be called when ffi trampoline function object is created.
3003 void AssignFfiCallbackId(int32_t callback_id) const;
3004
3005 // Can only be called on FFI natives and FFI call closures.
3006 bool FfiIsLeaf() const;
3007
3008 // Can only be called on FFI trampolines.
3009 FunctionPtr FfiCallbackTarget() const;
3010
3011 // Can only be called on FFI trampolines.
3012 void SetFfiCallbackTarget(const Function& target) const;
3013
3014 // Can only be called on FFI trampolines.
3015 InstancePtr FfiCallbackExceptionalReturn() const;
3016
3017 // Can only be called on FFI trampolines.
3018 void SetFfiCallbackExceptionalReturn(const Instance& value) const;
3019
3020 // Can only be called on FFI trampolines.
3021 FfiCallbackKind GetFfiCallbackKind() const;
3022
3023 // Can only be called on FFI trampolines.
3024 void SetFfiCallbackKind(FfiCallbackKind value) const;
3025
3026 // Return the signature of this function.
3028 void SetSignature(const FunctionType& value) const;
3029 static intptr_t signature_offset() {
3030 return OFFSET_OF(UntaggedFunction, signature_);
3031 }
3032
3033 // Build a string of the form '<T>(T, {B b, C c}) => R' representing the
3034 // internal signature of the given function. In this example, T is a type
3035 // parameter of this function and R is a type parameter of class C, the owner
3036 // of the function. B and C are not type parameters.
3037 StringPtr InternalSignature() const;
3038
3039 // Build a string of the form '<T>(T, {B b, C c}) => R' representing the
3040 // user visible signature of the given function. In this example, T is a type
3041 // parameter of this function and R is a type parameter of class C, the owner
3042 // of the function. B and C are not type parameters.
3043 // Implicit parameters are hidden.
3044 StringPtr UserVisibleSignature() const;
3045
3046 // Returns true if the signature of this function is instantiated, i.e. if it
3047 // does not involve generic parameter types or generic result type.
3048 // Note that function type parameters declared by this function do not make
3049 // its signature uninstantiated, only type parameters declared by parent
3050 // generic functions or class type parameters.
3051 bool HasInstantiatedSignature(
3052 Genericity genericity = kAny,
3053 intptr_t num_free_fun_type_params = kAllFree) const;
3054
3055 bool IsPrivate() const;
3056
3057 ClassPtr Owner() const;
3058 void set_owner(const Object& value) const;
3059 ScriptPtr script() const;
3060#if !defined(DART_PRECOMPILED_RUNTIME)
3061 KernelProgramInfoPtr KernelProgramInfo() const;
3062#endif
3063 ObjectPtr RawOwner() const { return untag()->owner(); }
3064
3065 RegExpPtr regexp() const;
3066 intptr_t string_specialization_cid() const;
3067 bool is_sticky_specialization() const;
3068 void SetRegExpData(const RegExp& regexp,
3069 intptr_t string_specialization_cid,
3070 bool sticky) const;
3071
3072 StringPtr native_name() const;
3073 void set_native_name(const String& name) const;
3074
3075 InstancePtr GetNativeAnnotation() const;
3076 bool is_ffi_native() const;
3077 bool is_old_native() const;
3078
3079 AbstractTypePtr result_type() const {
3080 return signature()->untag()->result_type();
3081 }
3082
3083 // The parameters, starting with NumImplicitParameters() parameters which are
3084 // only visible to the VM, but not to Dart users.
3085 // Note that type checks exclude implicit parameters.
3086 AbstractTypePtr ParameterTypeAt(intptr_t index) const;
3087 ArrayPtr parameter_types() const {
3088 return signature()->untag()->parameter_types();
3089 }
3090
3091 // Outside of the AOT runtime, functions store the names for their positional
3092 // parameters, and delegate storage of the names for named parameters to
3093 // their signature. These methods handle fetching the name from and
3094 // setting the name to the correct location.
3095 StringPtr ParameterNameAt(intptr_t index) const;
3096 // Only valid for positional parameter indexes, as this should be called
3097 // explicitly on the signature for named parameters.
3098 void SetParameterNameAt(intptr_t index, const String& value) const;
3099 // Creates an appropriately sized array in the function to hold positional
3100 // parameter names, using the positional parameter count in the signature.
3101 // Uses same default space as Function::New.
3102 void CreateNameArray(Heap::Space space = Heap::kOld) const;
3103
3104 // Delegates to the signature, which stores the named parameter flags.
3105 bool IsRequiredAt(intptr_t index) const;
3106
3107 // The formal type parameters, their bounds, and defaults, are specified as an
3108 // object of type TypeParameters stored in the signature.
3109 TypeParametersPtr type_parameters() const {
3110 return signature()->untag()->type_parameters();
3111 }
3112
3113 // Returns the number of local type arguments for this function.
3114 intptr_t NumTypeParameters() const;
3115 // Return the cumulative number of type arguments in all parent functions.
3116 intptr_t NumParentTypeArguments() const;
3117 // Return the cumulative number of type arguments for this function, including
3118 // type arguments for all parent functions.
3119 intptr_t NumTypeArguments() const;
3120 // Return whether this function declares local type arguments.
3121 bool IsGeneric() const;
3122 // Returns whether any parent function of this function is generic.
3123 bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
3124
3125 // Return the type parameter declared at index.
3126 TypeParameterPtr TypeParameterAt(
3127 intptr_t index,
3128 Nullability nullability = Nullability::kNonNullable) const;
3129
3130 // Not thread-safe; must be called in the main thread.
3131 // Sets function's code and code's function.
3132 void InstallOptimizedCode(const Code& code) const;
3133 void AttachCode(const Code& value) const;
3134 void SetInstructions(const Code& value) const;
3135 void SetInstructionsSafe(const Code& value) const;
3136 void ClearCode() const;
3137 void ClearCodeSafe() const;
3138
3139 // Disables optimized code and switches to unoptimized code.
3140 void SwitchToUnoptimizedCode() const;
3141
3142 // Ensures that the function has code. If there is no code it compiles the
3143 // unoptimized version of the code. If the code contains errors, it calls
3144 // Exceptions::PropagateError and does not return. Normally returns the
3145 // current code, whether it is optimized or unoptimized.
3146 CodePtr EnsureHasCode() const;
3147
3148 // Disables optimized code and switches to unoptimized code (or the lazy
3149 // compilation stub).
3150 void SwitchToLazyCompiledUnoptimizedCode() const;
3151
3152 // Compiles unoptimized code (if necessary) and attaches it to the function.
3153 void EnsureHasCompiledUnoptimizedCode() const;
3154
3155 // Return the most recently compiled and installed code for this function.
3156 // It is not the only Code object that points to this function.
3157 CodePtr CurrentCode() const { return CurrentCodeOf(ptr()); }
3158
3159 bool SafeToClosurize() const;
3160
3161 static CodePtr CurrentCodeOf(const FunctionPtr function) {
3162 return function->untag()->code();
3163 }
3164
3165 CodePtr unoptimized_code() const {
3166#if defined(DART_PRECOMPILED_RUNTIME)
3167 return static_cast<CodePtr>(Object::null());
3168#else
3169 return untag()->unoptimized_code();
3170#endif
3171 }
3172 void set_unoptimized_code(const Code& value) const;
3173 bool HasCode() const;
3174 static bool HasCode(FunctionPtr function);
3175
3176 static intptr_t code_offset() { return OFFSET_OF(UntaggedFunction, code_); }
3177
3178 uword entry_point() const { return EntryPointOf(ptr()); }
3179 static uword EntryPointOf(const FunctionPtr function) {
3180 return function->untag()->entry_point_;
3181 }
3182
3183 static intptr_t entry_point_offset(
3184 CodeEntryKind entry_kind = CodeEntryKind::kNormal) {
3185 switch (entry_kind) {
3186 case CodeEntryKind::kNormal:
3187 return OFFSET_OF(UntaggedFunction, entry_point_);
3188 case CodeEntryKind::kUnchecked:
3189 return OFFSET_OF(UntaggedFunction, unchecked_entry_point_);
3190 default:
3191 UNREACHABLE();
3192 }
3193 }
3194
3196 return OFFSET_OF(UntaggedFunction, unchecked_entry_point_);
3197 }
3198
3199 virtual uword Hash() const;
3200
3201 // Returns true if there is at least one debugger breakpoint
3202 // set in this function.
3203 bool HasBreakpoint() const;
3204
3205 ContextScopePtr context_scope() const;
3206 void set_context_scope(const ContextScope& value) const;
3207
3209 // Context depth at which the `@pragma('vm:awaiter-link')` variable
3210 // is located.
3211 uint8_t depth = UntaggedClosureData::kNoAwaiterLinkDepth;
3212 // Context index at which the `@pragma('vm:awaiter-link')` variable
3213 // is located.
3214 uint8_t index = static_cast<uint8_t>(-1);
3215 };
3216
3217 AwaiterLink awaiter_link() const;
3218 void set_awaiter_link(AwaiterLink link) const;
3219 bool HasAwaiterLink() const {
3220 return IsClosureFunction() &&
3221 (awaiter_link().depth != UntaggedClosureData::kNoAwaiterLinkDepth);
3222 }
3223
3224 // Enclosing function of this local function.
3225 FunctionPtr parent_function() const;
3226
3227 // Returns a canonicalized vector of the type parameters instantiated
3228 // to bounds (e.g., the local type arguments that are used if no TAV is
3229 // provided when the function is invoked).
3230 //
3231 // If the function is owned by a generic class or has any generic parent
3232 // functions, then the returned vector may require instantiation, see
3233 // default_type_arguments_instantiation_mode() for Closure functions
3234 // or TypeArguments::GetInstantiationMode() otherwise.
3235 //
3236 // If non-generic, the empty type arguments vector is returned.
3237 TypeArgumentsPtr DefaultTypeArguments(Zone* zone) const;
3238
3239 // Only usable for closure functions.
3240 InstantiationMode default_type_arguments_instantiation_mode() const;
3241 void set_default_type_arguments_instantiation_mode(
3242 InstantiationMode value) const;
3243
3244 // Enclosing outermost function of this local function.
3245 FunctionPtr GetOutermostFunction() const;
3246
3247 void set_extracted_method_closure(const Function& function) const;
3248 FunctionPtr extracted_method_closure() const;
3249
3250 void set_saved_args_desc(const Array& array) const;
3251 ArrayPtr saved_args_desc() const;
3252
3254 return IsInvokeFieldDispatcher() || IsNoSuchMethodDispatcher();
3255 }
3256
3257 void set_accessor_field(const Field& value) const;
3258 FieldPtr accessor_field() const;
3259
3260 bool IsRegularFunction() const {
3261 return kind() == UntaggedFunction::kRegularFunction;
3262 }
3263
3264 bool IsMethodExtractor() const {
3265 return kind() == UntaggedFunction::kMethodExtractor;
3266 }
3267
3269 return kind() == UntaggedFunction::kNoSuchMethodDispatcher;
3270 }
3271
3272 bool IsRecordFieldGetter() const {
3273 return kind() == UntaggedFunction::kRecordFieldGetter;
3274 }
3275
3277 return kind() == UntaggedFunction::kInvokeFieldDispatcher;
3278 }
3279
3281 return IsInvokeFieldDispatcher() &&
3282 IsDynamicInvocationForwarderName(name());
3283 }
3284
3285 // Performs all the checks that don't require the current thread first, to
3286 // avoid retrieving it unless they all pass. If you have a handle on the
3287 // current thread, call the version that takes one instead.
3289 if (!IsDynamicInvokeFieldDispatcher()) return false;
3290 return IsDynamicClosureCallDispatcher(Thread::Current());
3291 }
3292 bool IsDynamicClosureCallDispatcher(Thread* thread) const;
3293
3295 return kind() == UntaggedFunction::kDynamicInvocationForwarder;
3296 }
3297
3299 return kind() == UntaggedFunction::kImplicitGetter ||
3300 kind() == UntaggedFunction::kImplicitSetter ||
3301 kind() == UntaggedFunction::kImplicitStaticGetter;
3302 }
3303
3304 // Returns true iff an implicit closure function has been created
3305 // for this function.
3307 return implicit_closure_function() != null();
3308 }
3309
3310 // Returns the closure function implicitly created for this function. If none
3311 // exists yet, create one and remember it. Implicit closure functions are
3312 // used in VM Closure instances that represent results of tear-off operations.
3313 FunctionPtr ImplicitClosureFunction() const;
3314 void DropUncompiledImplicitClosureFunction() const;
3315
3316 // Return the closure implicitly created for this function.
3317 // If none exists yet, create one and remember it.
3318 ClosurePtr ImplicitStaticClosure() const;
3319
3320 ClosurePtr ImplicitInstanceClosure(const Instance& receiver) const;
3321
3322 // Returns the target of the implicit closure or null if the target is now
3323 // invalid (e.g., mismatched argument shapes after a reload).
3324 FunctionPtr ImplicitClosureTarget(Zone* zone) const;
3325
3326 FunctionPtr ForwardingTarget() const;
3327 void SetForwardingTarget(const Function& target) const;
3328
3329 UntaggedFunction::Kind kind() const { return KindOf(ptr()); }
3330 static UntaggedFunction::Kind KindOf(FunctionPtr func) {
3331 return func->untag()->kind_tag_.Read<KindBits>();
3332 }
3333
3335 return untag()->kind_tag_.Read<ModifierBits>();
3336 }
3337
3338 static const char* KindToCString(UntaggedFunction::Kind kind);
3339
3340 bool IsConstructor() const {
3341 return kind() == UntaggedFunction::kConstructor;
3342 }
3344 return IsConstructor() && !is_static();
3345 }
3346 bool IsImplicitConstructor() const;
3347 bool IsFactory() const { return IsConstructor() && is_static(); }
3348
3349 bool HasThisParameter() const {
3350 return IsDynamicFunction(/*allow_abstract=*/true) ||
3351 IsGenerativeConstructor() || (IsFieldInitializer() && !is_static());
3352 }
3353
3354 bool IsDynamicFunction(bool allow_abstract = false) const {
3355 if (is_static() || (!allow_abstract && is_abstract())) {
3356 return false;
3357 }
3358 switch (kind()) {
3359 case UntaggedFunction::kRegularFunction:
3360 case UntaggedFunction::kGetterFunction:
3361 case UntaggedFunction::kSetterFunction:
3362 case UntaggedFunction::kImplicitGetter:
3363 case UntaggedFunction::kImplicitSetter:
3364 case UntaggedFunction::kMethodExtractor:
3365 case UntaggedFunction::kNoSuchMethodDispatcher:
3366 case UntaggedFunction::kInvokeFieldDispatcher:
3367 case UntaggedFunction::kDynamicInvocationForwarder:
3368 case UntaggedFunction::kRecordFieldGetter:
3369 return true;
3370 case UntaggedFunction::kClosureFunction:
3371 case UntaggedFunction::kImplicitClosureFunction:
3372 case UntaggedFunction::kConstructor:
3373 case UntaggedFunction::kImplicitStaticGetter:
3374 case UntaggedFunction::kFieldInitializer:
3375 case UntaggedFunction::kIrregexpFunction:
3376 return false;
3377 default:
3378 UNREACHABLE();
3379 return false;
3380 }
3381 }
3382 bool IsStaticFunction() const {
3383 if (!is_static()) {
3384 return false;
3385 }
3386 switch (kind()) {
3387 case UntaggedFunction::kRegularFunction:
3388 case UntaggedFunction::kGetterFunction:
3389 case UntaggedFunction::kSetterFunction:
3390 case UntaggedFunction::kImplicitGetter:
3391 case UntaggedFunction::kImplicitSetter:
3392 case UntaggedFunction::kImplicitStaticGetter:
3393 case UntaggedFunction::kFieldInitializer:
3394 case UntaggedFunction::kIrregexpFunction:
3395 return true;
3396 case UntaggedFunction::kClosureFunction:
3397 case UntaggedFunction::kImplicitClosureFunction:
3398 case UntaggedFunction::kConstructor:
3399 case UntaggedFunction::kMethodExtractor:
3400 case UntaggedFunction::kNoSuchMethodDispatcher:
3401 case UntaggedFunction::kInvokeFieldDispatcher:
3402 case UntaggedFunction::kDynamicInvocationForwarder:
3403 case UntaggedFunction::kFfiTrampoline:
3404 case UntaggedFunction::kRecordFieldGetter:
3405 return false;
3406 default:
3407 UNREACHABLE();
3408 return false;
3409 }
3410 }
3411
3413 return !(is_static() || (kind() == UntaggedFunction::kConstructor));
3414 }
3415
3417 return !(is_static() || (kind() == UntaggedFunction::kConstructor));
3418 }
3419
3420 bool NeedsMonomorphicCheckedEntry(Zone* zone) const;
3421 bool HasDynamicCallers(Zone* zone) const;
3422 bool PrologueNeedsArgumentsDescriptor() const;
3423
3424 bool MayHaveUncheckedEntryPoint() const;
3425
3427#if defined(DART_PRECOMPILED_RUNTIME)
3428 return TokenPosition::kNoSource;
3429#else
3430 return untag()->token_pos_;
3431#endif
3432 }
3433 void set_token_pos(TokenPosition value) const;
3434
3436#if defined(DART_PRECOMPILED_RUNTIME)
3437 return TokenPosition::kNoSource;
3438#else
3439 return untag()->end_token_pos_;
3440#endif
3441 }
3443#if defined(DART_PRECOMPILED_RUNTIME)
3444 UNREACHABLE();
3445#else
3446 StoreNonPointer(&untag()->end_token_pos_, value);
3447#endif
3448 }
3449
3450#if !defined(PRODUCT) && \
3451 (defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME))
3452 int32_t line() const { return untag()->token_pos_.Serialize(); }
3453
3454 void set_line(int32_t line) const {
3455 StoreNonPointer(&untag()->token_pos_, TokenPosition::Deserialize(line));
3456 }
3457#endif
3458
3459 // Returns the size of the source for this function.
3460 intptr_t SourceSize() const;
3461
3462 uint32_t packed_fields() const {
3463#if defined(DART_PRECOMPILED_RUNTIME)
3464 UNREACHABLE();
3465#else
3466 return untag()->packed_fields_;
3467#endif
3468 }
3469 void set_packed_fields(uint32_t packed_fields) const;
3470
3471 // Returns the number of required positional parameters.
3472 intptr_t num_fixed_parameters() const;
3473 // Returns the number of optional parameters, whether positional or named.
3474 bool HasOptionalParameters() const;
3475 // Returns whether the function has optional named parameters.
3476 bool HasOptionalNamedParameters() const;
3477 // Returns whether the function has required named parameters.
3478 bool HasRequiredNamedParameters() const;
3479 // Returns whether the function has optional positional parameters.
3480 bool HasOptionalPositionalParameters() const;
3481 // Returns the number of optional parameters, or 0 if none.
3482 intptr_t NumOptionalParameters() const;
3483 // Returns the number of optional positional parameters, or 0 if none.
3484 intptr_t NumOptionalPositionalParameters() const;
3485 // Returns the number of optional named parameters, or 0 if none.
3486 intptr_t NumOptionalNamedParameters() const;
3487 // Returns the total number of both required and optional parameters.
3488 intptr_t NumParameters() const;
3489 // Returns the number of implicit parameters, e.g., this for instance methods.
3490 intptr_t NumImplicitParameters() const;
3491
3492 // Returns true if parameters of this function are copied into the frame
3493 // in the function prologue.
3495 return HasOptionalParameters() || IsSuspendableFunction();
3496 }
3497
3498#if !defined(DART_PRECOMPILED_RUNTIME)
3499 intptr_t MaxNumberOfParametersInRegisters(Zone* zone) const;
3500#endif // !defined(DART_PRECOMPILED_RUNTIME)
3501
3502#if defined(DART_PRECOMPILED_RUNTIME)
3503#define DEFINE_GETTERS_AND_SETTERS(return_type, type, name) \
3504 static intptr_t name##_offset() { \
3505 UNREACHABLE(); \
3506 return 0; \
3507 } \
3508 return_type name() const { return 0; } \
3509 \
3510 void set_##name(type value) const { UNREACHABLE(); }
3511#else
3512#define DEFINE_GETTERS_AND_SETTERS(return_type, type, name) \
3513 static intptr_t name##_offset() { \
3514 return OFFSET_OF(UntaggedFunction, name##_); \
3515 } \
3516 return_type name() const { \
3517 return LoadNonPointer<type, std::memory_order_relaxed>(&untag()->name##_); \
3518 } \
3519 \
3520 void set_##name(type value) const { \
3521 StoreNonPointer<type, type, std::memory_order_relaxed>(&untag()->name##_, \
3522 value); \
3523 }
3524#endif
3525
3527
3528#undef DEFINE_GETTERS_AND_SETTERS
3529
3530 intptr_t kernel_offset() const {
3531#if defined(DART_PRECOMPILED_RUNTIME)
3532 return 0;
3533#else
3534 return untag()->kernel_offset_;
3535#endif
3536 }
3537
3538 void set_kernel_offset(intptr_t value) const {
3539#if defined(DART_PRECOMPILED_RUNTIME)
3540 UNREACHABLE();
3541#else
3542 ASSERT(value >= 0);
3543 StoreNonPointer(&untag()->kernel_offset_, value);
3544#endif
3545 }
3546
3547 void InheritKernelOffsetFrom(const Function& src) const;
3548 void InheritKernelOffsetFrom(const Field& src) const;
3549
3550 static constexpr intptr_t kMaxInstructionCount = (1 << 16) - 1;
3551
3552 void SetOptimizedInstructionCountClamped(uintptr_t value) const {
3553 if (value > kMaxInstructionCount) value = kMaxInstructionCount;
3554 set_optimized_instruction_count(value);
3555 }
3556
3557 void SetOptimizedCallSiteCountClamped(uintptr_t value) const {
3558 if (value > kMaxInstructionCount) value = kMaxInstructionCount;
3559 set_optimized_call_site_count(value);
3560 }
3561
3562 void SetKernelLibraryAndEvalScript(
3563 const Script& script,
3564 const class KernelProgramInfo& kernel_program_info,
3565 intptr_t index) const;
3566
3567 intptr_t KernelLibraryOffset() const;
3568 intptr_t KernelLibraryIndex() const;
3569
3570 TypedDataViewPtr KernelLibrary() const;
3571
3572 bool IsOptimizable() const;
3573 void SetIsOptimizable(bool value) const;
3574
3575 // Whether this function must be optimized immediately and cannot be compiled
3576 // with the unoptimizing compiler. Such a function must be sure to not
3577 // deoptimize, since we won't generate deoptimization info or register
3578 // dependencies. It will be compiled into optimized code immediately when it's
3579 // run.
3580 bool ForceOptimize() const;
3581
3582 // Whether this function should be inlined if at all possible.
3583 bool IsPreferInline() const;
3584
3585 // Whether this function is idempotent (i.e. calling it twice has the same
3586 // effect as calling it once - no visible side effects).
3587 //
3588 // If a function is idempotent VM may decide to abort halfway through one call
3589 // and retry it again.
3590 bool IsIdempotent() const;
3591
3592 bool IsCachableIdempotent() const;
3593
3594 // Whether this function's |recognized_kind| requires optimization.
3595 bool RecognizedKindForceOptimize() const;
3596
3597 bool CanBeInlined() const;
3598
3600 return untag()->kind_tag_.Read<RecognizedBits>();
3601 }
3602 void set_recognized_kind(MethodRecognizer::Kind value) const;
3603
3604 bool IsRecognized() const {
3605 return recognized_kind() != MethodRecognizer::kUnknown;
3606 }
3607
3608 bool HasOptimizedCode() const;
3609
3610 // Returns true if the argument counts are valid for calling this function.
3611 // Otherwise, it returns false and the reason (if error_message is not
3612 // nullptr).
3613 bool AreValidArgumentCounts(intptr_t num_type_arguments,
3614 intptr_t num_arguments,
3615 intptr_t num_named_arguments,
3616 String* error_message) const;
3617
3618 // Returns a TypeError if the provided arguments don't match the function
3619 // parameter types, null otherwise. Assumes AreValidArguments is called first.
3620 //
3621 // If the function has a non-null receiver in the arguments, the instantiator
3622 // type arguments are retrieved from the receiver, otherwise the null type
3623 // arguments vector is used.
3624 //
3625 // If the function is generic, the appropriate function type arguments are
3626 // retrieved either from the arguments array or the receiver (if a closure).
3627 // If no function type arguments are available in either location, the bounds
3628 // of the function type parameters are instantiated and used as the function
3629 // type arguments.
3630 //
3631 // The local function type arguments (_not_ parent function type arguments)
3632 // are also checked against the bounds of the corresponding parameters to
3633 // ensure they are appropriate subtypes if the function is generic.
3634 ObjectPtr DoArgumentTypesMatch(const Array& args,
3635 const ArgumentsDescriptor& arg_names) const;
3636
3637 // Returns a TypeError if the provided arguments don't match the function
3638 // parameter types, null otherwise. Assumes AreValidArguments is called first.
3639 //
3640 // If the function is generic, the appropriate function type arguments are
3641 // retrieved either from the arguments array or the receiver (if a closure).
3642 // If no function type arguments are available in either location, the bounds
3643 // of the function type parameters are instantiated and used as the function
3644 // type arguments.
3645 //
3646 // The local function type arguments (_not_ parent function type arguments)
3647 // are also checked against the bounds of the corresponding parameters to
3648 // ensure they are appropriate subtypes if the function is generic.
3649 ObjectPtr DoArgumentTypesMatch(
3650 const Array& args,
3651 const ArgumentsDescriptor& arg_names,
3652 const TypeArguments& instantiator_type_args) const;
3653
3654 // Returns a TypeError if the provided arguments don't match the function
3655 // parameter types, null otherwise. Assumes AreValidArguments is called first.
3656 //
3657 // The local function type arguments (_not_ parent function type arguments)
3658 // are also checked against the bounds of the corresponding parameters to
3659 // ensure they are appropriate subtypes if the function is generic.
3660 ObjectPtr DoArgumentTypesMatch(const Array& args,
3661 const ArgumentsDescriptor& arg_names,
3662 const TypeArguments& instantiator_type_args,
3663 const TypeArguments& function_type_args) const;
3664
3665 // Returns true if the type argument count, total argument count and the names
3666 // of optional arguments are valid for calling this function.
3667 // Otherwise, it returns false and the reason (if error_message is not
3668 // nullptr).
3669 bool AreValidArguments(intptr_t num_type_arguments,
3670 intptr_t num_arguments,
3671 const Array& argument_names,
3672 String* error_message) const;
3673 bool AreValidArguments(const ArgumentsDescriptor& args_desc,
3674 String* error_message) const;
3675
3676 // Fully qualified name uniquely identifying the function under gdb and during
3677 // ast printing. The special ':' character, if present, is replaced by '_'.
3678 const char* ToFullyQualifiedCString() const;
3679
3680 const char* ToLibNamePrefixedQualifiedCString() const;
3681
3682 const char* ToQualifiedCString() const;
3683
3684 static constexpr intptr_t maximum_unboxed_parameter_count() {
3685 // Subtracts one that represents the return value
3686 return UntaggedFunction::UnboxedParameterBitmap::kCapacity - 1;
3687 }
3688
3690#if !defined(DART_PRECOMPILED_RUNTIME)
3691 StoreNonPointer(&untag()->unboxed_parameters_info_,
3693#endif // !defined(DART_PRECOMPILED_RUNTIME)
3694 }
3695
3696 void set_unboxed_integer_parameter_at(intptr_t index) const {
3697#if !defined(DART_PRECOMPILED_RUNTIME)
3698 ASSERT(index >= 0 && index < maximum_unboxed_parameter_count());
3699 index++; // position 0 is reserved for the return value
3701 &untag()->unboxed_parameters_info_)
3702 ->SetUnboxedInteger(index);
3703#else
3704 UNREACHABLE();
3705#endif // !defined(DART_PRECOMPILED_RUNTIME)
3706 }
3707
3708 void set_unboxed_double_parameter_at(intptr_t index) const {
3709#if !defined(DART_PRECOMPILED_RUNTIME)
3710 ASSERT(index >= 0 && index < maximum_unboxed_parameter_count());
3711 index++; // position 0 is reserved for the return value
3713 &untag()->unboxed_parameters_info_)
3714 ->SetUnboxedDouble(index);
3715
3716#else
3717 UNREACHABLE();
3718#endif // !defined(DART_PRECOMPILED_RUNTIME)
3719 }
3720
3722#if !defined(DART_PRECOMPILED_RUNTIME)
3724 &untag()->unboxed_parameters_info_)
3725 ->SetUnboxedInteger(0);
3726#else
3727 UNREACHABLE();
3728#endif // !defined(DART_PRECOMPILED_RUNTIME)
3729 }
3730
3732#if !defined(DART_PRECOMPILED_RUNTIME)
3734 &untag()->unboxed_parameters_info_)
3735 ->SetUnboxedDouble(0);
3736
3737#else
3738 UNREACHABLE();
3739#endif // !defined(DART_PRECOMPILED_RUNTIME)
3740 }
3741
3743#if !defined(DART_PRECOMPILED_RUNTIME)
3745 &untag()->unboxed_parameters_info_)
3746 ->SetUnboxedRecord(0);
3747
3748#else
3749 UNREACHABLE();
3750#endif // !defined(DART_PRECOMPILED_RUNTIME)
3751 }
3752
3753 bool is_unboxed_parameter_at(intptr_t index) const {
3754#if !defined(DART_PRECOMPILED_RUNTIME)
3755 ASSERT(index >= 0);
3756 index++; // position 0 is reserved for the return value
3757 return untag()->unboxed_parameters_info_.IsUnboxed(index);
3758#else
3759 return false;
3760#endif // !defined(DART_PRECOMPILED_RUNTIME)
3761 }
3762
3763 bool is_unboxed_integer_parameter_at(intptr_t index) const {
3764#if !defined(DART_PRECOMPILED_RUNTIME)
3765 ASSERT(index >= 0);
3766 index++; // position 0 is reserved for the return value
3767 return untag()->unboxed_parameters_info_.IsUnboxedInteger(index);
3768#else
3769 return false;
3770#endif // !defined(DART_PRECOMPILED_RUNTIME)
3771 }
3772
3773 bool is_unboxed_double_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_.IsUnboxedDouble(index);
3778#else
3779 return false;
3780#endif // !defined(DART_PRECOMPILED_RUNTIME)
3781 }
3782
3783 bool has_unboxed_return() const {
3784#if !defined(DART_PRECOMPILED_RUNTIME)
3785 return untag()->unboxed_parameters_info_.IsUnboxed(0);
3786#else
3787 return false;
3788#endif // !defined(DART_PRECOMPILED_RUNTIME)
3789 }
3790
3792#if !defined(DART_PRECOMPILED_RUNTIME)
3793 return untag()->unboxed_parameters_info_.IsUnboxedInteger(0);
3794#else
3795 return false;
3796#endif // !defined(DART_PRECOMPILED_RUNTIME)
3797 }
3798
3800#if !defined(DART_PRECOMPILED_RUNTIME)
3801 return untag()->unboxed_parameters_info_.IsUnboxedDouble(0);
3802#else
3803 return false;
3804#endif // !defined(DART_PRECOMPILED_RUNTIME)
3805 }
3806
3808#if !defined(DART_PRECOMPILED_RUNTIME)
3809 return untag()->unboxed_parameters_info_.IsUnboxedRecord(0);
3810#else
3811 return false;
3812#endif // !defined(DART_PRECOMPILED_RUNTIME)
3813 }
3814
3815#if !defined(DART_PRECOMPILED_RUNTIME)
3817 return untag()->unboxed_parameters_info_.HasUnboxedParameters();
3818 }
3819 bool HasUnboxedReturnValue() const { return has_unboxed_return(); }
3820#endif // !defined(DART_PRECOMPILED_RUNTIME)
3821
3823 switch (kind()) {
3824 case UntaggedFunction::kImplicitGetter:
3825 case UntaggedFunction::kImplicitSetter:
3826 case UntaggedFunction::kImplicitStaticGetter:
3827 case UntaggedFunction::kNoSuchMethodDispatcher:
3828 case UntaggedFunction::kInvokeFieldDispatcher:
3829 case UntaggedFunction::kDynamicInvocationForwarder:
3830 return true;
3831 default:
3832 return false;
3833 }
3834 }
3835
3836 // Returns true if this function represents an explicit getter function.
3837 bool IsGetterFunction() const {
3838 return kind() == UntaggedFunction::kGetterFunction;
3839 }
3840
3841 // Returns true if this function represents an implicit getter function.
3843 return kind() == UntaggedFunction::kImplicitGetter;
3844 }
3845
3846 // Returns true if this function represents an implicit static getter
3847 // function.
3849 return kind() == UntaggedFunction::kImplicitStaticGetter;
3850 }
3851
3852 // Returns true if this function represents an explicit setter function.
3853 bool IsSetterFunction() const {
3854 return kind() == UntaggedFunction::kSetterFunction;
3855 }
3856
3857 // Returns true if this function represents an implicit setter function.
3859 return kind() == UntaggedFunction::kImplicitSetter;
3860 }
3861
3862 // Returns true if this function represents an initializer for a static or
3863 // instance field. The function returns the initial value and the caller is
3864 // responsible for setting the field.
3865 bool IsFieldInitializer() const {
3866 return kind() == UntaggedFunction::kFieldInitializer;
3867 }
3868
3869 // Returns true if this function represents a (possibly implicit) closure
3870 // function.
3871 bool IsClosureFunction() const {
3872 UntaggedFunction::Kind k = kind();
3873 return (k == UntaggedFunction::kClosureFunction) ||
3874 (k == UntaggedFunction::kImplicitClosureFunction);
3875 }
3876
3877 // Returns true if this function represents a generated irregexp function.
3878 bool IsIrregexpFunction() const {
3879 return kind() == UntaggedFunction::kIrregexpFunction;
3880 }
3881
3882 // Returns true if this function represents an implicit closure function.
3884 return kind() == UntaggedFunction::kImplicitClosureFunction;
3885 }
3886 static bool IsImplicitClosureFunction(FunctionPtr func) {
3887 return KindOf(func) == UntaggedFunction::kImplicitClosureFunction;
3888 }
3889
3890 // Returns true if this function represents a non implicit closure function.
3892 return IsClosureFunction() && !IsImplicitClosureFunction();
3893 }
3894
3895 // Returns true if this function represents an implicit static closure
3896 // function.
3898 return IsImplicitClosureFunction() && is_static();
3899 }
3900 static bool IsImplicitStaticClosureFunction(FunctionPtr func);
3901
3902 // Returns true if this function represents an implicit instance closure
3903 // function.
3905 return IsImplicitClosureFunction() && !is_static();
3906 }
3907 static bool IsImplicitInstanceClosureFunction(FunctionPtr func);
3908
3909 // Returns true if this function has a parent function.
3910 bool HasParent() const { return parent_function() != Function::null(); }
3911
3912 // Returns true if this function is a local function.
3913 bool IsLocalFunction() const {
3914 return !IsImplicitClosureFunction() && HasParent();
3915 }
3916
3917 // Returns true if this function represents an ffi trampoline.
3919 return kind() == UntaggedFunction::kFfiTrampoline;
3920 }
3921 static bool IsFfiCallbackTrampoline(FunctionPtr function) {
3922 NoSafepointScope no_safepoint;
3923 return function->untag()->kind_tag_.Read<KindBits>() ==
3924 UntaggedFunction::kFfiTrampoline;
3925 }
3926
3927 // Returns true if this function is a closure function
3928 // used to represent ffi call.
3929 bool IsFfiCallClosure() const;
3930
3931 // Returns value of vm:ffi:call-closure pragma.
3932 InstancePtr GetFfiCallClosurePragmaValue() const;
3933
3934 // Returns true for functions which execution can be suspended
3935 // using Suspend/Resume stubs. Such functions have an artificial
3936 // :suspend_state local variable at the fixed location of the frame.
3938 return modifier() != UntaggedFunction::kNoModifier;
3939 }
3940
3941 // Returns true if this function is marked with 'async' modifier.
3942 bool IsAsyncFunction() const {
3943 return modifier() == UntaggedFunction::kAsync;
3944 }
3945
3946 // Returns true if this function is marked with 'sync*' modifier.
3947 bool IsSyncGenerator() const {
3948 return modifier() == UntaggedFunction::kSyncGen;
3949 }
3950
3951 // Returns true if this function is marked with 'async*' modifier.
3952 bool IsAsyncGenerator() const {
3953 return modifier() == UntaggedFunction::kAsyncGen;
3954 }
3955
3956 bool IsTypedDataViewFactory() const;
3957 bool IsUnmodifiableTypedDataViewFactory() const;
3958
3960 ErrorPtr VerifyCallEntryPoint() const;
3961
3963 ErrorPtr VerifyClosurizedEntryPoint() const;
3964
3965 static intptr_t InstanceSize() {
3966 return RoundedAllocationSize(sizeof(UntaggedFunction));
3967 }
3968
3969 static FunctionPtr New(const FunctionType& signature,
3970 const String& name,
3972 bool is_static,
3973 bool is_const,
3974 bool is_abstract,
3975 bool is_external,
3976 bool is_native,
3977 const Object& owner,
3978 TokenPosition token_pos,
3979 Heap::Space space = Heap::kOld);
3980
3981 // Allocates a new Function object representing a closure function
3982 // with given kind - kClosureFunction or kImplicitClosureFunction.
3983 static FunctionPtr NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
3984 const String& name,
3985 const Function& parent,
3986 bool is_static,
3987 TokenPosition token_pos,
3988 const Object& owner);
3989
3990 // Allocates a new Function object representing a closure function.
3991 static FunctionPtr NewClosureFunction(const String& name,
3992 const Function& parent,
3993 TokenPosition token_pos);
3994
3995 // Allocates a new Function object representing an implicit closure function.
3996 static FunctionPtr NewImplicitClosureFunction(const String& name,
3997 const Function& parent,
3998 TokenPosition token_pos);
3999
4000 FunctionPtr CreateMethodExtractor(const String& getter_name) const;
4001 FunctionPtr GetMethodExtractor(const String& getter_name) const;
4002
4003 static bool IsDynamicInvocationForwarderName(const String& name);
4004 static bool IsDynamicInvocationForwarderName(StringPtr name);
4005
4006 static StringPtr DemangleDynamicInvocationForwarderName(const String& name);
4007
4008 static StringPtr CreateDynamicInvocationForwarderName(const String& name);
4009
4010#if !defined(DART_PRECOMPILED_RUNTIME)
4011 FunctionPtr CreateDynamicInvocationForwarder(
4012 const String& mangled_name) const;
4013
4014 FunctionPtr GetDynamicInvocationForwarder(const String& mangled_name,
4015 bool allow_add = true) const;
4016#endif
4017
4018 // Slow function, use in asserts to track changes in important library
4019 // functions.
4020 int32_t SourceFingerprint() const;
4021
4022 // Return false and report an error if the fingerprint does not match.
4023 bool CheckSourceFingerprint(int32_t fp, const char* kind = nullptr) const;
4024
4025 // Works with map [deopt-id] -> ICData.
4026 void SaveICDataMap(
4027 const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data,
4028 const Array& edge_counters_array,
4029 const Array& coverage_array) const;
4030 // Uses 'ic_data_array' to populate the table 'deopt_id_to_ic_data'. Clone
4031 // ic_data (array and descriptor) if 'clone_ic_data' is true.
4032 void RestoreICDataMap(ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
4033 bool clone_ic_data) const;
4034
4035 // ic_data_array attached to the function stores edge counters in the
4036 // first element, coverage data array in the second element and the rest
4037 // are ICData objects.
4039 static constexpr intptr_t kEdgeCounters = 0;
4040 static constexpr intptr_t kCoverageData = 1;
4041 static constexpr intptr_t kFirstICData = 2;
4042 };
4043
4044 ArrayPtr ic_data_array() const;
4045 void ClearICDataArray() const;
4046 ICDataPtr FindICData(intptr_t deopt_id) const;
4047
4048 // Coverage data array is a list of pairs:
4049 // element 2 * i + 0 is token position
4050 // element 2 * i + 1 is coverage hit (zero meaning code was not hit)
4051 ArrayPtr GetCoverageArray() const;
4052
4053 // Outputs this function's service ID to the provided JSON object.
4054 void AddFunctionServiceId(const JSONObject& obj) const;
4055
4056 // Sets deopt reason in all ICData-s with given deopt_id.
4057 void SetDeoptReasonForAll(intptr_t deopt_id, ICData::DeoptReasonId reason);
4058
4059 void set_modifier(UntaggedFunction::AsyncModifier value) const;
4060
4061// 'WasCompiled' is true if the function was compiled once in this
4062// VM instantiation. It is independent from presence of type feedback
4063// (ic_data_array) and code, which may be loaded from a snapshot.
4064// 'WasExecuted' is true if the usage counter has ever been positive.
4065// 'ProhibitsInstructionHoisting' is true if this function deoptimized before on
4066// a hoisted instruction.
4067// 'ProhibitsBoundsCheckGeneralization' is true if this function deoptimized
4068// before on a generalized bounds check.
4069#define STATE_BITS_LIST(V) \
4070 V(WasCompiled) \
4071 V(WasExecutedBit) \
4072 V(ProhibitsInstructionHoisting) \
4073 V(ProhibitsBoundsCheckGeneralization)
4074
4076#define DECLARE_FLAG_POS(Name) k##Name##Pos,
4078#undef DECLARE_FLAG_POS
4079 };
4080#define DEFINE_FLAG_BIT(Name) \
4081 class Name##Bit : public BitField<uint8_t, bool, k##Name##Pos, 1> {};
4083#undef DEFINE_FLAG_BIT
4084
4085#define DEFINE_FLAG_ACCESSORS(Name) \
4086 void Set##Name(bool value) const { \
4087 set_state_bits(Name##Bit::update(value, state_bits())); \
4088 } \
4089 bool Name() const { return Name##Bit::decode(state_bits()); }
4091#undef DEFINE_FLAG_ACCESSORS
4092
4093 void SetUsageCounter(intptr_t value) const {
4094 if (usage_counter() > 0) {
4095 SetWasExecuted(true);
4096 }
4097 set_usage_counter(value);
4098 }
4099
4100 bool WasExecuted() const { return (usage_counter() > 0) || WasExecutedBit(); }
4101
4102 void SetWasExecuted(bool value) const { SetWasExecutedBit(value); }
4103
4104 static intptr_t data_offset() { return OFFSET_OF(UntaggedFunction, data_); }
4105
4106 static intptr_t kind_tag_offset() {
4107 return OFFSET_OF(UntaggedFunction, kind_tag_);
4108 }
4109
4110 // static: Considered during class-side or top-level resolution rather than
4111 // instance-side resolution.
4112 // const: Valid target of a const constructor call.
4113 // abstract: Skipped during instance-side resolution.
4114 // reflectable: Enumerated by mirrors, invocable by mirrors. False for private
4115 // functions of dart: libraries.
4116 // debuggable: Valid location of a breakpoint. Synthetic code is not
4117 // debuggable.
4118 // visible: Frame is included in stack traces. Synthetic code such as
4119 // dispatchers is not visible. Synthetic code that can trigger
4120 // exceptions such as the outer async functions that create Futures
4121 // is visible.
4122 // intrinsic: Has a hand-written assembly prologue.
4123 // inlinable: Candidate for inlining. False for functions with features we
4124 // don't support during inlining (e.g., optional parameters),
4125 // functions which are too big, etc.
4126 // native: Bridge to C/C++ code.
4127 // external: Just a declaration that expects to be defined in another patch
4128 // file.
4129 // polymorphic_target: A polymorphic method.
4130 // has_pragma: Has a @pragma decoration.
4131 // no_such_method_forwarder: A stub method that just calls noSuchMethod.
4132
4133// Bits that are set when function is created, don't have to worry about
4134// concurrent updates.
4135#define FOR_EACH_FUNCTION_KIND_BIT(V) \
4136 V(Static, is_static) \
4137 V(Const, is_const) \
4138 V(Abstract, is_abstract) \
4139 V(Reflectable, is_reflectable) \
4140 V(Visible, is_visible) \
4141 V(Debuggable, is_debuggable) \
4142 V(Intrinsic, is_intrinsic) \
4143 V(Native, is_native) \
4144 V(External, is_external) \
4145 V(PolymorphicTarget, is_polymorphic_target) \
4146 V(HasPragma, has_pragma) \
4147 V(IsSynthetic, is_synthetic) \
4148 V(IsExtensionMember, is_extension_member) \
4149 V(IsExtensionTypeMember, is_extension_type_member) \
4150 V(IsRedirectingFactory, is_redirecting_factory)
4151// Bit that is updated after function is constructed, has to be updated in
4152// concurrent-safe manner.
4153#define FOR_EACH_FUNCTION_VOLATILE_KIND_BIT(V) V(Inlinable, is_inlinable)
4154
4155#define DEFINE_ACCESSORS(name, accessor_name) \
4156 void set_##accessor_name(bool value) const { \
4157 untag()->kind_tag_.UpdateUnsynchronized<name##Bit>(value); \
4158 } \
4159 bool accessor_name() const { return untag()->kind_tag_.Read<name##Bit>(); }
4161#undef DEFINE_ACCESSORS
4162
4163 static bool is_visible(FunctionPtr f) {
4164 return f.untag()->kind_tag_.Read<VisibleBit>();
4165 }
4166
4167#define DEFINE_ACCESSORS(name, accessor_name) \
4168 void set_##accessor_name(bool value) const { \
4169 untag()->kind_tag_.UpdateBool<name##Bit>(value); \
4170 } \
4171 bool accessor_name() const { return untag()->kind_tag_.Read<name##Bit>(); }
4173#undef DEFINE_ACCESSORS
4174
4175 // optimizable: Candidate for going through the optimizing compiler. False for
4176 // some functions known to be execute infrequently and functions
4177 // which have been de-optimized too many times.
4178 bool is_optimizable() const {
4179#if defined(DART_PRECOMPILED_RUNTIME)
4180 return false;
4181#else
4182 return untag()->packed_fields_.Read<UntaggedFunction::PackedOptimizable>();
4183#endif
4184 }
4185 void set_is_optimizable(bool value) const {
4186#if defined(DART_PRECOMPILED_RUNTIME)
4187 UNREACHABLE();
4188#else
4189 untag()->packed_fields_.UpdateBool<UntaggedFunction::PackedOptimizable>(
4190 value);
4191#endif
4192 }
4193
4195 kKindTagPos = 0,
4196 kKindTagSize = 5,
4197 kRecognizedTagPos = kKindTagPos + kKindTagSize,
4198 kRecognizedTagSize = 9,
4199 kModifierPos = kRecognizedTagPos + kRecognizedTagSize,
4200 kModifierSize = 2,
4201 kLastModifierBitPos = kModifierPos + (kModifierSize - 1),
4202// Single bit sized fields start here.
4203#define DECLARE_BIT(name, _) k##name##Bit,
4206#undef DECLARE_BIT
4207 kNumTagBits
4209
4210 COMPILE_ASSERT(MethodRecognizer::kNumRecognizedMethods <
4211 (1 << kRecognizedTagSize));
4212 COMPILE_ASSERT(kNumTagBits <=
4213 (kBitsPerByte *
4214 sizeof(decltype(UntaggedFunction::kind_tag_))));
4215
4216#define ASSERT_FUNCTION_KIND_IN_RANGE(Name) \
4217 COMPILE_ASSERT(UntaggedFunction::k##Name < (1 << kKindTagSize));
4219#undef ASSERT_FUNCTION_KIND_IN_RANGE
4220
4221 class KindBits : public BitField<uint32_t,
4222 UntaggedFunction::Kind,
4223 kKindTagPos,
4224 kKindTagSize> {};
4225
4226 class RecognizedBits : public BitField<uint32_t,
4227 MethodRecognizer::Kind,
4228 kRecognizedTagPos,
4229 kRecognizedTagSize> {};
4230 class ModifierBits : public BitField<uint32_t,
4231 UntaggedFunction::AsyncModifier,
4232 kModifierPos,
4233 kModifierSize> {};
4234
4235#define DEFINE_BIT(name, _) \
4236 class name##Bit : public BitField<uint32_t, bool, k##name##Bit, 1> {};
4239#undef DEFINE_BIT
4240
4241 private:
4242 enum class EvalFunctionData {
4243 kScript,
4244 kKernelProgramInfo,
4245 kKernelLibraryIndex,
4246 kLength,
4247 };
4248 enum NativeFunctionData {
4249 kNativeName,
4250 kTearOff,
4251 kLength,
4252 };
4253
4254 void set_ic_data_array(const Array& value) const;
4255 void set_name(const String& value) const;
4256 void set_kind(UntaggedFunction::Kind value) const;
4257 void set_parent_function(const Function& value) const;
4258 FunctionPtr implicit_closure_function() const;
4259 void set_implicit_closure_function(const Function& value) const;
4260 ClosurePtr implicit_static_closure() const;
4261 void set_implicit_static_closure(const Closure& closure) const;
4262 ScriptPtr eval_script() const;
4263 void set_eval_script(const Script& value) const;
4264 void set_num_optional_parameters(intptr_t value) const; // Encoded value.
4265 void set_kind_tag(uint32_t value) const;
4266 bool is_eval_function() const;
4267
4268#if !defined(DART_PRECOMPILED_RUNTIME)
4269 ArrayPtr positional_parameter_names() const {
4270 return untag()->positional_parameter_names();
4271 }
4272 void set_positional_parameter_names(const Array& value) const;
4273#endif
4274
4275 ObjectPtr data() const { return untag()->data<std::memory_order_acquire>(); }
4276 void set_data(const Object& value) const;
4277
4278 static FunctionPtr New(Heap::Space space = Heap::kOld);
4279
4280 FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
4281 friend class Class;
4282 friend class Parser; // For set_eval_script.
4283 // UntaggedFunction::VisitFunctionPointers accesses the private constructor of
4284 // Function.
4285 friend class UntaggedFunction;
4286 friend class ClassFinalizer; // To reset parent_function.
4287 friend class Type; // To adjust parent_function.
4288 friend class Precompiler; // To access closure data.
4289 friend class ProgramVisitor; // For set_parameter_types/names.
4290};
4291
4292class ClosureData : public Object {
4293 public:
4294 static intptr_t InstanceSize() {
4295 return RoundedAllocationSize(sizeof(UntaggedClosureData));
4296 }
4297
4298 static intptr_t packed_fields_offset() {
4299 return OFFSET_OF(UntaggedClosureData, packed_fields_);
4300 }
4301
4303
4304 static constexpr uint8_t kNoAwaiterLinkDepth =
4305 UntaggedClosureData::kNoAwaiterLinkDepth;
4306
4307 private:
4308 ContextScopePtr context_scope() const { return untag()->context_scope(); }
4309 void set_context_scope(const ContextScope& value) const;
4310
4311 void set_packed_fields(uint32_t value) const {
4312 untag()->packed_fields_ = value;
4313 }
4314
4315 Function::AwaiterLink awaiter_link() const;
4316 void set_awaiter_link(Function::AwaiterLink link) const;
4317
4318 // Enclosing function of this local function.
4319 PRECOMPILER_WSR_FIELD_DECLARATION(Function, parent_function)
4320
4321 ClosurePtr implicit_static_closure() const {
4322 return untag()->closure<std::memory_order_acquire>();
4323 }
4324 void set_implicit_static_closure(const Closure& closure) const;
4325
4326 static InstantiationMode DefaultTypeArgumentsInstantiationMode(
4327 ClosureDataPtr ptr) {
4328 return ptr->untag()->packed_fields_.Read<PackedInstantiationMode>();
4329 }
4330 InstantiationMode default_type_arguments_instantiation_mode() const {
4331 return DefaultTypeArgumentsInstantiationMode(ptr());
4332 }
4333 void set_default_type_arguments_instantiation_mode(
4334 InstantiationMode value) const;
4335
4336 static ClosureDataPtr New();
4337
4338 FINAL_HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
4339 friend class Class;
4340 friend class Function;
4341 friend class Precompiler; // To wrap parent functions in WSRs.
4342};
4343
4345 kAlways,
4346 kNever,
4349 kCallOnly
4350};
4351
4353 public:
4354 static intptr_t InstanceSize() {
4355 return RoundedAllocationSize(sizeof(UntaggedFfiTrampolineData));
4356 }
4357
4358 private:
4359 FunctionTypePtr c_signature() const { return untag()->c_signature(); }
4360 void set_c_signature(const FunctionType& value) const;
4361
4362 FunctionPtr callback_target() const { return untag()->callback_target(); }
4363 void set_callback_target(const Function& value) const;
4364
4365 InstancePtr callback_exceptional_return() const {
4366 return untag()->callback_exceptional_return();
4367 }
4368 void set_callback_exceptional_return(const Instance& value) const;
4369
4370 FfiCallbackKind ffi_function_kind() const {
4371 return static_cast<FfiCallbackKind>(untag()->ffi_function_kind_);
4372 }
4373 void set_ffi_function_kind(FfiCallbackKind kind) const;
4374
4375 int32_t callback_id() const { return untag()->callback_id_; }
4376 void set_callback_id(int32_t value) const;
4377
4378 static FfiTrampolineDataPtr New();
4379
4380 FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
4381 friend class Class;
4382 friend class Function;
4383};
4384
4385class Field : public Object {
4386 public:
4387 // The field that this field was cloned from, or this field itself if it isn't
4388 // a clone. The purpose of cloning is that the fields the background compiler
4389 // sees are consistent.
4390 FieldPtr Original() const;
4391
4392 // Set the original field that this field was cloned from.
4393 void SetOriginal(const Field& value) const;
4394
4395 // Returns whether this field is an original or a clone.
4396 bool IsOriginal() const {
4397 if (IsNull()) {
4398 return true;
4399 }
4400 NoSafepointScope no_safepoint;
4401 return !untag()->owner()->IsField();
4402 }
4403
4404 // Returns a field cloned from 'this'. 'this' is set as the
4405 // original field of result.
4406 FieldPtr CloneFromOriginal() const;
4407
4408 StringPtr name() const { return untag()->name(); }
4409 StringPtr UserVisibleName() const; // Same as scrubbed name.
4410 const char* UserVisibleNameCString() const;
4411 virtual StringPtr DictionaryName() const { return name(); }
4412
4413 uint16_t kind_bits() const {
4414 return LoadNonPointer<uint16_t, std::memory_order_acquire>(
4415 &untag()->kind_bits_);
4416 }
4417
4418 bool is_static() const { return StaticBit::decode(kind_bits()); }
4419 bool is_instance() const { return !is_static(); }
4420 bool is_final() const { return FinalBit::decode(kind_bits()); }
4421 bool is_const() const { return ConstBit::decode(kind_bits()); }
4422 bool is_late() const { return IsLateBit::decode(kind_bits()); }
4423 bool is_extension_member() const {
4424 return IsExtensionMemberBit::decode(kind_bits());
4425 }
4427 return IsExtensionTypeMemberBit::decode(kind_bits());
4428 }
4429 bool needs_load_guard() const {
4430 return NeedsLoadGuardBit::decode(kind_bits());
4431 }
4432 bool is_reflectable() const { return ReflectableBit::decode(kind_bits()); }
4433 void set_is_reflectable(bool value) const {
4434 ASSERT(IsOriginal());
4435 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4436 set_kind_bits(ReflectableBit::update(value, untag()->kind_bits_));
4437 }
4438
4440 return InitializerChangedAfterInitializationBit::decode(kind_bits());
4441 }
4443 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4444 set_kind_bits(InitializerChangedAfterInitializationBit::update(
4445 value, untag()->kind_bits_));
4446 }
4447
4448 bool has_pragma() const { return HasPragmaBit::decode(kind_bits()); }
4449 void set_has_pragma(bool value) const {
4450 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4451 set_kind_bits(HasPragmaBit::update(value, untag()->kind_bits_));
4452 }
4453
4454 bool is_covariant() const { return CovariantBit::decode(kind_bits()); }
4455 void set_is_covariant(bool value) const {
4456 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4457 set_kind_bits(CovariantBit::update(value, untag()->kind_bits_));
4458 }
4459
4461 return GenericCovariantImplBit::decode(kind_bits());
4462 }
4463 void set_is_generic_covariant_impl(bool value) const {
4464 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4465 set_kind_bits(GenericCovariantImplBit::update(value, untag()->kind_bits_));
4466 }
4467
4468 intptr_t kernel_offset() const {
4469#if defined(DART_PRECOMPILED_RUNTIME)
4470 return 0;
4471#else
4472 return untag()->kernel_offset_;
4473#endif
4474 }
4475
4476 void set_kernel_offset(intptr_t value) const {
4477#if defined(DART_PRECOMPILED_RUNTIME)
4478 UNREACHABLE();
4479#else
4480 ASSERT(value >= 0);
4481 StoreNonPointer(&untag()->kernel_offset_, value);
4482#endif
4483 }
4484
4485 void InheritKernelOffsetFrom(const Field& src) const;
4486
4487 TypedDataViewPtr KernelLibrary() const;
4488 intptr_t KernelLibraryOffset() const;
4489 intptr_t KernelLibraryIndex() const;
4490
4491 // Called during class finalization.
4492 inline void SetOffset(intptr_t host_offset_in_bytes,
4493 intptr_t target_offset_in_bytes) const;
4494
4495 inline intptr_t HostOffset() const;
4497 return OFFSET_OF(UntaggedField, host_offset_or_field_id_);
4498 }
4499
4500 inline intptr_t TargetOffset() const;
4501 static inline intptr_t TargetOffsetOf(FieldPtr field);
4502
4503 ObjectPtr StaticConstFieldValue() const;
4504 void SetStaticConstFieldValue(const Instance& value,
4505 bool assert_initializing_store = true) const;
4506
4507 inline ObjectPtr StaticValue() const;
4508 void SetStaticValue(const Object& value) const;
4509
4510 inline intptr_t field_id() const;
4511 inline void set_field_id(intptr_t field_id) const;
4512 inline void set_field_id_unsafe(intptr_t field_id) const;
4513
4514 ClassPtr Owner() const;
4515 ScriptPtr Script() const;
4516#if !defined(DART_PRECOMPILED_RUNTIME)
4517 KernelProgramInfoPtr KernelProgramInfo() const;
4518#endif
4519 ObjectPtr RawOwner() const;
4520
4521 uint32_t Hash() const;
4522
4523 AbstractTypePtr type() const { return untag()->type(); }
4524 // Used by class finalizer, otherwise initialized in constructor.
4525 void SetFieldType(const AbstractType& value) const;
4526 void SetFieldTypeSafe(const AbstractType& value) const;
4527
4529 ErrorPtr VerifyEntryPoint(EntryPointPragma kind) const;
4530
4531 static intptr_t InstanceSize() {
4532 return RoundedAllocationSize(sizeof(UntaggedField));
4533 }
4534
4535 static FieldPtr New(const String& name,
4536 bool is_static,
4537 bool is_final,
4538 bool is_const,
4539 bool is_reflectable,
4540 bool is_late,
4541 const Object& owner,
4542 const AbstractType& type,
4543 TokenPosition token_pos,
4544 TokenPosition end_token_pos);
4545
4546 static FieldPtr NewTopLevel(const String& name,
4547 bool is_final,
4548 bool is_const,
4549 bool is_late,
4550 const Object& owner,
4551 TokenPosition token_pos,
4552 TokenPosition end_token_pos);
4553
4554 // Allocate new field object, clone values from this field. The
4555 // original is specified.
4556 FieldPtr Clone(const Field& original) const;
4557
4558 static intptr_t kind_bits_offset() {
4559 return OFFSET_OF(UntaggedField, kind_bits_);
4560 }
4561
4562 TokenPosition token_pos() const { return untag()->token_pos_; }
4563 TokenPosition end_token_pos() const { return untag()->end_token_pos_; }
4564
4565 int32_t SourceFingerprint() const;
4566
4567 StringPtr InitializingExpression() const;
4568
4570 return HasNontrivialInitializerBit::decode(kind_bits());
4571 }
4572 // Called by parser after allocating field.
4574 bool has_nontrivial_initializer) const {
4575 ASSERT(IsOriginal());
4576 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4577 set_kind_bits(HasNontrivialInitializerBit::update(
4578 has_nontrivial_initializer, untag()->kind_bits_));
4579 }
4580 void set_has_nontrivial_initializer(bool has_nontrivial_initializer) const {
4582 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4583 set_has_nontrivial_initializer_unsafe(has_nontrivial_initializer);
4584 }
4585
4586 bool has_initializer() const {
4587 return HasInitializerBit::decode(kind_bits());
4588 }
4589 // Called by parser after allocating field.
4590 void set_has_initializer_unsafe(bool has_initializer) const {
4591 ASSERT(IsOriginal());
4592 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4593 set_kind_bits(
4594 HasInitializerBit::update(has_initializer, untag()->kind_bits_));
4595 }
4596 void set_has_initializer(bool has_initializer) const {
4598 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4599 set_has_initializer_unsafe(has_initializer);
4600 }
4601
4603 return has_initializer() && !has_nontrivial_initializer();
4604 }
4605
4607 return StaticTypeExactnessState::Decode(
4608 LoadNonPointer<int8_t, std::memory_order_relaxed>(
4609 &untag()->static_type_exactness_state_));
4610 }
4611
4614 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4615 set_static_type_exactness_state_unsafe(state);
4616 }
4617
4620 StoreNonPointer<int8_t, int8_t, std::memory_order_relaxed>(
4621 &untag()->static_type_exactness_state_, state.Encode());
4622 }
4623
4625 return OFFSET_OF(UntaggedField, static_type_exactness_state_);
4626 }
4627
4628 // Return class id that any non-null value read from this field is guaranteed
4629 // to have or kDynamicCid if such class id is not known.
4630 // Stores to this field must update this information hence the name.
4631 intptr_t guarded_cid() const;
4632
4633 void set_guarded_cid(intptr_t cid) const {
4635 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4636 set_guarded_cid_unsafe(cid);
4637 }
4638 void set_guarded_cid_unsafe(intptr_t cid) const {
4639 StoreNonPointer<ClassIdTagType, ClassIdTagType, std::memory_order_relaxed>(
4640 &untag()->guarded_cid_, cid);
4641 }
4642 static intptr_t guarded_cid_offset() {
4643 return OFFSET_OF(UntaggedField, guarded_cid_);
4644 }
4645 // Return the list length that any list stored in this field is guaranteed
4646 // to have. If length is kUnknownFixedLength the length has not
4647 // been determined. If length is kNoFixedLength this field has multiple
4648 // list lengths associated with it and cannot be predicted.
4649 intptr_t guarded_list_length() const;
4650 void set_guarded_list_length_unsafe(intptr_t list_length) const;
4651 void set_guarded_list_length(intptr_t list_length) const {
4653 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4654 set_guarded_list_length_unsafe(list_length);
4655 }
4656 static intptr_t guarded_list_length_offset() {
4657 return OFFSET_OF(UntaggedField, guarded_list_length_);
4658 }
4659 intptr_t guarded_list_length_in_object_offset() const;
4660 void set_guarded_list_length_in_object_offset_unsafe(intptr_t offset) const;
4663 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4664 set_guarded_list_length_in_object_offset_unsafe(offset);
4665 }
4667 return OFFSET_OF(UntaggedField, guarded_list_length_in_object_offset_);
4668 }
4669
4670 bool needs_length_check() const {
4671 const bool r = guarded_list_length() >= Field::kUnknownFixedLength;
4672 ASSERT(!r || is_final());
4673 return r;
4674 }
4675
4676 bool NeedsSetter() const;
4677 bool NeedsGetter() const;
4678
4680 return needs_load_guard() || (is_late() && !has_trivial_initializer());
4681 }
4682
4683 const char* GuardedPropertiesAsCString() const;
4684
4685 bool is_unboxed() const { return UnboxedBit::decode(kind_bits()); }
4686
4687 // Field unboxing decisions are based either on static types (JIT) or
4688 // inferred types (AOT). See the callers of this function.
4689 void set_is_unboxed_unsafe(bool b) const {
4690 set_kind_bits(UnboxedBit::update(b, untag()->kind_bits_));
4691 }
4692
4693 void set_is_unboxed(bool b) const {
4695 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4696 set_is_unboxed_unsafe(b);
4697 }
4698
4699 enum {
4700 kUnknownLengthOffset = -1,
4701 kUnknownFixedLength = -1,
4702 kNoFixedLength = -2,
4703 };
4704 void set_is_late(bool value) const {
4705 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4706 set_kind_bits(IsLateBit::update(value, untag()->kind_bits_));
4707 }
4708 void set_is_extension_member(bool value) const {
4709 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4710 set_kind_bits(IsExtensionMemberBit::update(value, untag()->kind_bits_));
4711 }
4712 void set_is_extension_type_member(bool value) const {
4713 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4714 set_kind_bits(IsExtensionTypeMemberBit::update(value, untag()->kind_bits_));
4715 }
4716 void set_needs_load_guard(bool value) const {
4717 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4718 set_kind_bits(NeedsLoadGuardBit::update(value, untag()->kind_bits_));
4719 }
4720 // Returns false if any value read from this field is guaranteed to be
4721 // not null.
4722 // Internally we is_nullable_ field contains either kNullCid (nullable) or
4723 // kIllegalCid (non-nullable) instead of boolean. This is done to simplify
4724 // guarding sequence in the generated code.
4725 bool is_nullable() const;
4726 void set_is_nullable(bool val) const {
4728 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
4729 set_is_nullable_unsafe(val);
4730 }
4731 bool is_nullable_unsafe() const {
4732 return LoadNonPointer<ClassIdTagType, std::memory_order_relaxed>(
4733 &untag()->is_nullable_) == kNullCid;
4734 }
4735 void set_is_nullable_unsafe(bool val) const {
4736 StoreNonPointer<ClassIdTagType, ClassIdTagType, std::memory_order_relaxed>(
4737 &untag()->is_nullable_, val ? kNullCid : kIllegalCid);
4738 }
4739 static intptr_t is_nullable_offset() {
4740 return OFFSET_OF(UntaggedField, is_nullable_);
4741 }
4742
4743 // Record store of the given value into this field. May trigger
4744 // deoptimization of dependent optimized code.
4745 void RecordStore(const Object& value) const;
4746
4747 void InitializeGuardedListLengthInObjectOffset(bool unsafe = false) const;
4748
4749 // Return the list of optimized code objects that were optimized under
4750 // assumptions about guarded class id and nullability of this field.
4751 // These code objects must be deoptimized when field's properties change.
4752 // Code objects are held weakly via an indirection through WeakProperty.
4753 WeakArrayPtr dependent_code() const;
4754 void set_dependent_code(const WeakArray& array) const;
4755
4756 // Add the given code object to the list of dependent ones.
4757 void RegisterDependentCode(const Code& code) const;
4758
4759 // Deoptimize all dependent code objects.
4760 void DeoptimizeDependentCode(bool are_mutators_stopped = false) const;
4761
4762 // Used by background compiler to check consistency of field copy with its
4763 // original.
4764 bool IsConsistentWith(const Field& field) const;
4765
4766 bool IsUninitialized() const;
4767
4768 // Run initializer and set field value.
4770 InitializeInstance(const Instance& instance) const;
4771 DART_WARN_UNUSED_RESULT ErrorPtr InitializeStatic() const;
4772
4773 // Run initializer only.
4774 DART_WARN_UNUSED_RESULT ObjectPtr EvaluateInitializer() const;
4775
4776 FunctionPtr EnsureInitializerFunction() const;
4777 FunctionPtr InitializerFunction() const {
4778 return untag()->initializer_function<std::memory_order_acquire>();
4779 }
4780 void SetInitializerFunction(const Function& initializer) const;
4781 bool HasInitializerFunction() const;
4783 return OFFSET_OF(UntaggedField, initializer_function_);
4784 }
4785
4786 // For static fields only. Constructs a closure that gets/sets the
4787 // field value.
4788 InstancePtr GetterClosure() const;
4789 InstancePtr SetterClosure() const;
4790 InstancePtr AccessorClosure(bool make_setter) const;
4791
4792 // Constructs getter and setter names for fields and vice versa.
4793 static StringPtr GetterName(const String& field_name);
4794 static StringPtr GetterSymbol(const String& field_name);
4795 // Returns String::null() if getter symbol does not exist.
4796 static StringPtr LookupGetterSymbol(const String& field_name);
4797 static StringPtr SetterName(const String& field_name);
4798 static StringPtr SetterSymbol(const String& field_name);
4799 // Returns String::null() if setter symbol does not exist.
4800 static StringPtr LookupSetterSymbol(const String& field_name);
4801 static StringPtr NameFromGetter(const String& getter_name);
4802 static StringPtr NameFromSetter(const String& setter_name);
4803 static StringPtr NameFromInit(const String& init_name);
4804 static bool IsGetterName(const String& function_name);
4805 static bool IsSetterName(const String& function_name);
4806 static bool IsInitName(const String& function_name);
4807
4808 private:
4809 static void InitializeNew(const Field& result,
4810 const String& name,
4811 bool is_static,
4812 bool is_final,
4813 bool is_const,
4814 bool is_reflectable,
4815 bool is_late,
4816 const Object& owner,
4817 TokenPosition token_pos,
4818 TokenPosition end_token_pos);
4819 friend class StoreFieldInstr; // Generated code access to bit field.
4820
4821 enum {
4822 kConstBit = 0,
4823 kStaticBit,
4824 kFinalBit,
4825 kHasNontrivialInitializerBit,
4826 kUnboxedBit,
4827 kReflectableBit,
4828 kInitializerChangedAfterInitializationBit,
4829 kHasPragmaBit,
4830 kCovariantBit,
4831 kGenericCovariantImplBit,
4832 kIsLateBit,
4833 kIsExtensionMemberBit,
4834 kIsExtensionTypeMemberBit,
4835 kNeedsLoadGuardBit,
4836 kHasInitializerBit,
4837 };
4838 class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
4839 class StaticBit : public BitField<uint16_t, bool, kStaticBit, 1> {};
4840 class FinalBit : public BitField<uint16_t, bool, kFinalBit, 1> {};
4841 class HasNontrivialInitializerBit
4842 : public BitField<uint16_t, bool, kHasNontrivialInitializerBit, 1> {};
4843 class UnboxedBit : public BitField<uint16_t, bool, kUnboxedBit, 1> {};
4844 class ReflectableBit : public BitField<uint16_t, bool, kReflectableBit, 1> {};
4845 class InitializerChangedAfterInitializationBit
4846 : public BitField<uint16_t,
4847 bool,
4848 kInitializerChangedAfterInitializationBit,
4849 1> {};
4850 class HasPragmaBit : public BitField<uint16_t, bool, kHasPragmaBit, 1> {};
4851 class CovariantBit : public BitField<uint16_t, bool, kCovariantBit, 1> {};
4852 class GenericCovariantImplBit
4853 : public BitField<uint16_t, bool, kGenericCovariantImplBit, 1> {};
4854 class IsLateBit : public BitField<uint16_t, bool, kIsLateBit, 1> {};
4855 class IsExtensionMemberBit
4856 : public BitField<uint16_t, bool, kIsExtensionMemberBit, 1> {};
4857 class IsExtensionTypeMemberBit
4858 : public BitField<uint16_t, bool, kIsExtensionTypeMemberBit, 1> {};
4859 class NeedsLoadGuardBit
4860 : public BitField<uint16_t, bool, kNeedsLoadGuardBit, 1> {};
4861 class HasInitializerBit
4862 : public BitField<uint16_t, bool, kHasInitializerBit, 1> {};
4863
4864 // Force this field's guard to be dynamic and deoptimize dependent code.
4865 void ForceDynamicGuardedCidAndLength() const;
4866
4867 void set_name(const String& value) const;
4868 void set_is_static(bool is_static) const {
4869 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4870 set_kind_bits(StaticBit::update(is_static, untag()->kind_bits_));
4871 }
4872 void set_is_final(bool is_final) const {
4873 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4874 set_kind_bits(FinalBit::update(is_final, untag()->kind_bits_));
4875 }
4876 void set_is_const(bool value) const {
4877 // TODO(36097): Once concurrent access is possible ensure updates are safe.
4878 set_kind_bits(ConstBit::update(value, untag()->kind_bits_));
4879 }
4880 void set_owner(const Object& value) const { untag()->set_owner(value.ptr()); }
4881 void set_token_pos(TokenPosition token_pos) const {
4882 StoreNonPointer(&untag()->token_pos_, token_pos);
4883 }
4884 void set_end_token_pos(TokenPosition token_pos) const {
4885 StoreNonPointer(&untag()->end_token_pos_, token_pos);
4886 }
4887 void set_kind_bits(uint16_t value) const {
4888 StoreNonPointer<uint16_t, uint16_t, std::memory_order_release>(
4889 &untag()->kind_bits_, value);
4890 }
4891
4892 static FieldPtr New();
4893
4894 FINAL_HEAP_OBJECT_IMPLEMENTATION(Field, Object);
4895 friend class Class;
4896 friend class UntaggedField;
4899};
4900
4901class Script : public Object {
4902 public:
4903 StringPtr url() const { return untag()->url(); }
4904 void set_url(const String& value) const;
4905
4906 // The actual url which was loaded from disk, if provided by the embedder.
4907 StringPtr resolved_url() const;
4908 bool HasSource() const;
4909 StringPtr Source() const;
4910 bool IsPartOfDartColonLibrary() const;
4911
4912 GrowableObjectArrayPtr GenerateLineNumberArray() const;
4913
4914 intptr_t line_offset() const { return 0; }
4915 intptr_t col_offset() const { return 0; }
4916 // Returns the max real token position for this script, or kNoSource
4917 // if there is no line starts information.
4918 TokenPosition MaxPosition() const;
4919
4920 // The load time in milliseconds since epoch.
4921 int64_t load_timestamp() const { return untag()->load_timestamp_; }
4922
4923#if !defined(DART_PRECOMPILED_RUNTIME)
4924 // Initializes thie script object from a kernel file.
4925 void InitializeFromKernel(const KernelProgramInfo& info,
4926 intptr_t script_index,
4927 const TypedData& line_starts,
4928 const TypedDataView& constant_coverage) const;
4929#endif
4930
4931 // The index of this script into the [KernelProgramInfo] object's source
4932 // table.
4933 intptr_t kernel_script_index() const { return untag()->kernel_script_index_; }
4934
4935 static intptr_t line_starts_offset() {
4936 return OFFSET_OF(UntaggedScript, line_starts_);
4937 }
4938
4939 TypedDataPtr line_starts() const;
4940
4941#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
4942 TypedDataViewPtr constant_coverage() const;
4943#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
4944
4945 LibraryPtr FindLibrary() const;
4946 StringPtr GetLine(intptr_t line_number, Heap::Space space = Heap::kNew) const;
4947 StringPtr GetSnippet(intptr_t from_line,
4948 intptr_t from_column,
4949 intptr_t to_line,
4950 intptr_t to_column) const;
4951
4952 // For real token positions when line starts are available, returns whether or
4953 // not a GetTokenLocation call would succeed. Returns true for non-real token
4954 // positions or if there is no line starts information.
4955 bool IsValidTokenPosition(TokenPosition token_pos) const;
4956
4957 // Returns whether a line and column could be computed for the given token
4958 // position and, if so, sets *line and *column (if not nullptr).
4959 bool GetTokenLocation(const TokenPosition& token_pos,
4960 intptr_t* line,
4961 intptr_t* column = nullptr) const;
4962
4963 // Returns the length of the token at the given position. If the length cannot
4964 // be determined, returns a negative value.
4965 intptr_t GetTokenLength(const TokenPosition& token_pos) const;
4966
4967 // Returns whether any tokens were found for the given line. When found,
4968 // *first_token_index and *last_token_index are set to the first and
4969 // last token on the line, respectively.
4970 bool TokenRangeAtLine(intptr_t line_number,
4971 TokenPosition* first_token_index,
4972 TokenPosition* last_token_index) const;
4973
4974 static intptr_t InstanceSize() {
4975 return RoundedAllocationSize(sizeof(UntaggedScript));
4976 }
4977
4978 static ScriptPtr New(const String& url, const String& source);
4979
4980 static ScriptPtr New(const String& url,
4981 const String& resolved_url,
4982 const String& source);
4983
4984#if !defined(DART_PRECOMPILED_RUNTIME)
4985 void LoadSourceFromKernel(const uint8_t* kernel_buffer,
4986 intptr_t kernel_buffer_len) const;
4987#endif // !defined(DART_PRECOMPILED_RUNTIME)
4988
4989 void CollectTokenPositionsFor() const;
4990 ArrayPtr CollectConstConstructorCoverageFrom() const;
4991
4992 private:
4993 KernelProgramInfoPtr kernel_program_info() const {
4994 return untag()->kernel_program_info();
4995 }
4996
4997 void set_debug_positions(const Array& value) const;
4998
4999#if !defined(DART_PRECOMPILED_RUNTIME)
5000 bool HasCachedMaxPosition() const;
5001
5002 void SetHasCachedMaxPosition(bool value) const;
5003 void SetCachedMaxPosition(intptr_t value) const;
5004#endif // !defined(DART_PRECOMPILED_RUNTIME)
5005
5006 void set_resolved_url(const String& value) const;
5007 void set_source(const String& value) const;
5008 void set_load_timestamp(int64_t value) const;
5009 ArrayPtr debug_positions() const;
5010
5011 FINAL_HEAP_OBJECT_IMPLEMENTATION(Script, Object);
5012 friend class Class;
5013 friend class Precompiler;
5014};
5015
5017 public:
5018 explicit DictionaryIterator(const Library& library);
5019
5020 bool HasNext() const { return next_ix_ < size_; }
5021
5022 // Returns next non-null raw object.
5023 ObjectPtr GetNext();
5024
5025 private:
5026 void MoveToNextObject();
5027
5028 const Array& array_;
5029 const int size_; // Number of elements to iterate over.
5030 int next_ix_; // Index of next element.
5031
5034};
5035
5037 public:
5039 // TODO(hausner): fix call sites that use kIteratePrivate. There is only
5040 // one top-level class per library left, not an array to iterate over.
5042 kNoIteratePrivate
5044
5045 ClassDictionaryIterator(const Library& library,
5046 IterationKind kind = kNoIteratePrivate);
5047
5048 bool HasNext() const {
5049 return (next_ix_ < size_) || !toplevel_class_.IsNull();
5050 }
5051
5052 // Returns a non-null raw class.
5053 ClassPtr GetNextClass();
5054
5055 private:
5056 void MoveToNextClass();
5057
5058 Class& toplevel_class_;
5059
5061};
5062
5063class Library : public Object {
5064 public:
5065 StringPtr name() const { return untag()->name(); }
5066 void SetName(const String& name) const;
5067
5068 StringPtr url() const { return untag()->url(); }
5069 static StringPtr UrlOf(LibraryPtr lib) { return lib->untag()->url(); }
5070 StringPtr private_key() const { return untag()->private_key(); }
5071 bool LoadNotStarted() const {
5072 return untag()->load_state_ == UntaggedLibrary::kAllocated;
5073 }
5074 bool LoadRequested() const {
5075 return untag()->load_state_ == UntaggedLibrary::kLoadRequested;
5076 }
5077 bool LoadInProgress() const {
5078 return untag()->load_state_ == UntaggedLibrary::kLoadInProgress;
5079 }
5080 void SetLoadRequested() const;
5081 void SetLoadInProgress() const;
5082 bool Loaded() const {
5083 return untag()->load_state_ == UntaggedLibrary::kLoaded;
5084 }
5085 void SetLoaded() const;
5086
5087 LoadingUnitPtr loading_unit() const { return untag()->loading_unit(); }
5088 void set_loading_unit(const LoadingUnit& value) const;
5089
5090 static intptr_t InstanceSize() {
5091 return RoundedAllocationSize(sizeof(UntaggedLibrary));
5092 }
5093
5094 static LibraryPtr New(const String& url);
5095
5096 ObjectPtr Invoke(const String& selector,
5097 const Array& arguments,
5098 const Array& argument_names,
5099 bool respect_reflectable = true,
5100 bool check_is_entrypoint = false) const;
5101 ObjectPtr InvokeGetter(const String& selector,
5102 bool throw_nsm_if_absent,
5103 bool respect_reflectable = true,
5104 bool check_is_entrypoint = false) const;
5105 ObjectPtr InvokeSetter(const String& selector,
5106 const Instance& argument,
5107 bool respect_reflectable = true,
5108 bool check_is_entrypoint = false) const;
5109
5110 // Evaluate the given expression as if it appeared in an top-level method of
5111 // this library and return the resulting value, or an error object if
5112 // evaluating the expression fails. The method has the formal (type)
5113 // parameters given in (type_)param_names, and is invoked with the (type)
5114 // argument values given in (type_)param_values.
5115 ObjectPtr EvaluateCompiledExpression(
5116 const ExternalTypedData& kernel_buffer,
5117 const Array& type_definitions,
5118 const Array& param_values,
5119 const TypeArguments& type_param_values) const;
5120
5121 // Library scope name dictionary.
5122 //
5123 // TODO(turnidge): The Lookup functions are not consistent in how
5124 // they deal with private names. Go through and make them a bit
5125 // more regular.
5126 void AddClass(const Class& cls) const;
5127 void AddObject(const Object& obj, const String& name) const;
5128 ObjectPtr LookupReExport(
5129 const String& name,
5130 ZoneGrowableArray<intptr_t>* visited = nullptr) const;
5131 ObjectPtr LookupLocalOrReExportObject(const String& name) const;
5132 LibraryPrefixPtr LookupLocalLibraryPrefix(const String& name) const;
5133
5134 // These lookups are local within the library.
5135 ClassPtr LookupClass(const String& name) const;
5136 ClassPtr LookupClassAllowPrivate(const String& name) const;
5137 FieldPtr LookupFieldAllowPrivate(const String& name) const;
5138 FunctionPtr LookupFunctionAllowPrivate(const String& name) const;
5139
5140 // Look up a Script based on a url. If 'useResolvedUri' is not provided or is
5141 // false, 'url' should have a 'dart:' scheme for Dart core libraries,
5142 // a 'package:' scheme for packages, and 'file:' scheme otherwise.
5143 //
5144 // If 'useResolvedUri' is true, 'url' should have a 'org-dartlang-sdk:' scheme
5145 // for Dart core libraries and a 'file:' scheme otherwise.
5146 ScriptPtr LookupScript(const String& url, bool useResolvedUri = false) const;
5147 ArrayPtr LoadedScripts() const;
5148
5149 void AddExport(const Namespace& ns) const;
5150
5151 void AddMetadata(const Object& declaration, intptr_t kernel_offset) const;
5152 ObjectPtr GetMetadata(const Object& declaration) const;
5153
5154#if !defined(DART_PRECOMPILED_RUNTIME)
5155 void EvaluatePragmas();
5156 void CopyPragmas(const Library& old_lib);
5157#endif
5158
5159 // Tries to finds a @pragma annotation on [object].
5160 //
5161 // If successful returns `true`. If an error happens during constant
5162 // evaluation, returns `false.
5163 //
5164 // If [only_core] is true, then the annotations on the object will only
5165 // be inspected if it is part of a core library.
5166 //
5167 // If [multiple] is true, then sets [options] to an GrowableObjectArray
5168 // containing all results and [options] may not be nullptr.
5169 //
5170 // WARNING: If the isolate received an [UnwindError] this function will not
5171 // return and rather unwinds until the enclosing setjmp() handler.
5172 static bool FindPragma(Thread* T,
5173 bool only_core,
5174 const Object& object,
5175 const String& pragma_name,
5176 bool multiple = false,
5177 Object* options = nullptr);
5178
5179 ClassPtr toplevel_class() const { return untag()->toplevel_class(); }
5180 void set_toplevel_class(const Class& value) const;
5181
5182 GrowableObjectArrayPtr used_scripts() const {
5183 return untag()->used_scripts();
5184 }
5185
5186 // Library imports.
5187 ArrayPtr imports() const { return untag()->imports(); }
5188 ArrayPtr exports() const { return untag()->exports(); }
5189 void AddImport(const Namespace& ns) const;
5190 intptr_t num_imports() const { return untag()->num_imports_; }
5191 NamespacePtr ImportAt(intptr_t index) const;
5192 LibraryPtr ImportLibraryAt(intptr_t index) const;
5193
5194 ArrayPtr dependencies() const { return untag()->dependencies(); }
5195 void set_dependencies(const Array& deps) const;
5196
5197 void DropDependenciesAndCaches() const;
5198
5199 // Resolving native methods for script loaded in the library.
5201 return LoadNonPointer<Dart_NativeEntryResolver, std::memory_order_relaxed>(
5202 &untag()->native_entry_resolver_);
5203 }
5206 std::memory_order_relaxed>(&untag()->native_entry_resolver_,
5207 value);
5208 }
5210 return LoadNonPointer<Dart_NativeEntrySymbol, std::memory_order_relaxed>(
5211 &untag()->native_entry_symbol_resolver_);
5212 }
5214 Dart_NativeEntrySymbol native_symbol_resolver) const {
5216 std::memory_order_relaxed>(
5217 &untag()->native_entry_symbol_resolver_, native_symbol_resolver);
5218 }
5219
5220 // Resolver for FFI native function pointers.
5222 return LoadNonPointer<Dart_FfiNativeResolver, std::memory_order_relaxed>(
5223 &untag()->ffi_native_resolver_);
5224 }
5227 std::memory_order_relaxed>(&untag()->ffi_native_resolver_,
5228 value);
5229 }
5230
5231 bool is_in_fullsnapshot() const {
5232 return UntaggedLibrary::InFullSnapshotBit::decode(untag()->flags_);
5233 }
5234 void set_is_in_fullsnapshot(bool value) const {
5235 set_flags(
5236 UntaggedLibrary::InFullSnapshotBit::update(value, untag()->flags_));
5237 }
5238
5239 StringPtr PrivateName(const String& name) const;
5240
5241 intptr_t index() const { return untag()->index_; }
5242 void set_index(intptr_t value) const {
5243 ASSERT((value == -1) ||
5244 ((value >= 0) && (value < std::numeric_limits<classid_t>::max())));
5245 StoreNonPointer(&untag()->index_, value);
5246 }
5247
5248 void Register(Thread* thread) const;
5249 static void RegisterLibraries(Thread* thread,
5250 const GrowableObjectArray& libs);
5251
5252 bool IsDebuggable() const {
5253 return UntaggedLibrary::DebuggableBit::decode(untag()->flags_);
5254 }
5255 void set_debuggable(bool value) const {
5256 set_flags(UntaggedLibrary::DebuggableBit::update(value, untag()->flags_));
5257 }
5258
5259 bool is_dart_scheme() const {
5260 return UntaggedLibrary::DartSchemeBit::decode(untag()->flags_);
5261 }
5262 void set_is_dart_scheme(bool value) const {
5263 set_flags(UntaggedLibrary::DartSchemeBit::update(value, untag()->flags_));
5264 }
5265
5266 // Includes 'dart:async', 'dart:typed_data', etc.
5267 bool IsAnyCoreLibrary() const;
5268
5269 inline intptr_t UrlHash() const;
5270
5271#if !defined(DART_PRECOMPILED_RUNTIME)
5272 KernelProgramInfoPtr kernel_program_info() const {
5273 return untag()->kernel_program_info();
5274 }
5275 void set_kernel_program_info(const KernelProgramInfo& info) const;
5276 TypedDataViewPtr KernelLibrary() const;
5277 intptr_t KernelLibraryOffset() const;
5278#endif
5279
5280 intptr_t kernel_library_index() const {
5281#if defined(DART_PRECOMPILED_RUNTIME)
5282 return 0;
5283#else
5284 return untag()->kernel_library_index_;
5285#endif
5286 }
5287
5288 void set_kernel_library_index(intptr_t value) const {
5289#if defined(DART_PRECOMPILED_RUNTIME)
5290 UNREACHABLE();
5291#else
5292 ASSERT(value >= 0);
5293 StoreNonPointer(&untag()->kernel_library_index_, value);
5294#endif
5295 }
5296
5297 static LibraryPtr LookupLibrary(Thread* thread, const String& url);
5298 static LibraryPtr GetLibrary(intptr_t index);
5299
5300 static void InitCoreLibrary(IsolateGroup* isolate_group);
5301 static void InitNativeWrappersLibrary(IsolateGroup* isolate_group,
5302 bool is_kernel_file);
5303
5304 static LibraryPtr AsyncLibrary();
5305 static LibraryPtr ConvertLibrary();
5306 static LibraryPtr CoreLibrary();
5307 static LibraryPtr CollectionLibrary();
5308 static LibraryPtr DeveloperLibrary();
5309 static LibraryPtr FfiLibrary();
5310 static LibraryPtr InternalLibrary();
5311 static LibraryPtr IsolateLibrary();
5312 static LibraryPtr MathLibrary();
5313#if !defined(DART_PRECOMPILED_RUNTIME)
5314 static LibraryPtr MirrorsLibrary();
5315#endif
5316 static LibraryPtr NativeWrappersLibrary();
5317 static LibraryPtr TypedDataLibrary();
5318 static LibraryPtr VMServiceLibrary();
5319
5320 // Eagerly compile all classes and functions in the library.
5321 static ErrorPtr CompileAll(bool ignore_error = false);
5322#if !defined(DART_PRECOMPILED_RUNTIME)
5323 // Finalize all classes in all libraries.
5324 static ErrorPtr FinalizeAllClasses();
5325#endif
5326
5327#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
5328 // Checks function fingerprints. Prints mismatches and aborts if
5329 // mismatch found.
5330 static void CheckFunctionFingerprints();
5331#endif // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
5332
5333 static bool IsPrivate(const String& name);
5334
5335 // Construct the full name of a corelib member.
5336 static const String& PrivateCoreLibName(const String& member);
5337
5338 // Returns true if [name] matches full name of corelib [member].
5339 static bool IsPrivateCoreLibName(const String& name, const String& member);
5340
5341 // Lookup class in the core lib which also contains various VM
5342 // helper methods and classes. Allow look up of private classes.
5343 static ClassPtr LookupCoreClass(const String& class_name);
5344
5345 // Return Function::null() if function does not exist in libs.
5346 static FunctionPtr GetFunction(const GrowableArray<Library*>& libs,
5347 const char* class_name,
5348 const char* function_name);
5349
5350 // Character used to indicate a private identifier.
5351 static const char kPrivateIdentifierStart = '_';
5352
5353 // Character used to separate private identifiers from
5354 // the library-specific key.
5355 static const char kPrivateKeySeparator = '@';
5356
5357 void CheckReload(const Library& replacement,
5358 ProgramReloadContext* context) const;
5359
5360 // Returns a closure of top level function 'name' in the exported namespace
5361 // of this library. If a top level function 'name' does not exist we look
5362 // for a top level getter 'name' that returns a closure.
5363 ObjectPtr GetFunctionClosure(const String& name) const;
5364
5365 // Ensures that all top-level functions and variables (fields) are loaded.
5366 void EnsureTopLevelClassIsFinalized() const;
5367
5368 private:
5369 static constexpr int kInitialImportsCapacity = 4;
5370 static constexpr int kImportsCapacityIncrement = 8;
5371
5372 static LibraryPtr New();
5373
5374 // These methods are only used by the Precompiler to obfuscate
5375 // the name and url.
5376 void set_name(const String& name) const;
5377 void set_url(const String& url) const;
5378 void set_private_key(const String& key) const;
5379
5380 void set_num_imports(intptr_t value) const;
5381 void set_flags(uint8_t flags) const;
5382 bool HasExports() const;
5383 ArrayPtr loaded_scripts() const { return untag()->loaded_scripts(); }
5384 ArrayPtr metadata() const {
5386 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
5387 return untag()->metadata();
5388 }
5389 void set_metadata(const Array& value) const;
5390 ArrayPtr dictionary() const { return untag()->dictionary(); }
5391 void InitClassDictionary() const;
5392
5393 void InitImportList() const;
5394 void RehashDictionary(const Array& old_dict, intptr_t new_dict_size) const;
5395 static LibraryPtr NewLibraryHelper(const String& url, bool import_core_lib);
5396 ObjectPtr LookupEntry(const String& name, intptr_t* index) const;
5397 ObjectPtr LookupLocalObject(const String& name) const;
5398 ObjectPtr LookupLocalObjectAllowPrivate(const String& name) const;
5399
5400 void AllocatePrivateKey() const;
5401
5402 FINAL_HEAP_OBJECT_IMPLEMENTATION(Library, Object);
5403
5404 friend class Bootstrap;
5405 friend class Class;
5406 friend class Debugger;
5408 friend class Isolate;
5410 friend class Namespace;
5411 friend class Object;
5412 friend class Precompiler;
5413};
5414
5415// A Namespace contains the names in a library dictionary, filtered by
5416// the show/hide combinators.
5417class Namespace : public Object {
5418 public:
5419 LibraryPtr target() const { return untag()->target(); }
5420 ArrayPtr show_names() const { return untag()->show_names(); }
5421 ArrayPtr hide_names() const { return untag()->hide_names(); }
5422 LibraryPtr owner() const { return untag()->owner(); }
5423
5424 static intptr_t InstanceSize() {
5425 return RoundedAllocationSize(sizeof(UntaggedNamespace));
5426 }
5427
5428 bool HidesName(const String& name) const;
5429 ObjectPtr Lookup(const String& name,
5430 ZoneGrowableArray<intptr_t>* trail = nullptr) const;
5431
5432 static NamespacePtr New(const Library& library,
5433 const Array& show_names,
5434 const Array& hide_names,
5435 const Library& owner);
5436
5437 private:
5438 static NamespacePtr New();
5439
5441 friend class Class;
5442 friend class Precompiler;
5443};
5444
5446 public:
5447 static KernelProgramInfoPtr New(const TypedDataBase& kernel_component,
5448 const TypedDataView& string_data,
5449 const TypedDataView& metadata_payload,
5450 const TypedDataView& metadata_mappings,
5451 const TypedDataView& constants_table,
5452 const TypedData& string_offsets,
5453 const TypedData& canonical_names,
5454 const Array& scripts,
5455 const Array& libraries_cache,
5456 const Array& classes_cache);
5457
5458 static intptr_t InstanceSize() {
5459 return RoundedAllocationSize(sizeof(UntaggedKernelProgramInfo));
5460 }
5461
5462 TypedDataPtr string_offsets() const { return untag()->string_offsets(); }
5463
5464 TypedDataBasePtr kernel_component() const {
5465 return untag()->kernel_component();
5466 }
5467 TypedDataViewPtr string_data() const { return untag()->string_data(); }
5468
5469 TypedDataPtr canonical_names() const { return untag()->canonical_names(); }
5470
5471 TypedDataViewPtr metadata_payloads() const {
5472 return untag()->metadata_payloads();
5473 }
5474
5475 TypedDataViewPtr metadata_mappings() const {
5476 return untag()->metadata_mappings();
5477 }
5478
5479 intptr_t KernelLibraryStartOffset(intptr_t library_index) const;
5480 intptr_t KernelLibraryEndOffset(intptr_t library_index) const;
5481 TypedDataViewPtr KernelLibrary(intptr_t library_index) const;
5482
5483 TypedDataViewPtr constants_table() const {
5484 return untag()->constants_table();
5485 }
5486
5487 void set_constants_table(const TypedDataView& value) const;
5488
5489 ArrayPtr scripts() const { return untag()->scripts(); }
5490 void set_scripts(const Array& scripts) const;
5491
5492 ArrayPtr constants() const { return untag()->constants(); }
5493 void set_constants(const Array& constants) const;
5494
5495 ScriptPtr ScriptAt(intptr_t index) const;
5496
5497 ArrayPtr libraries_cache() const { return untag()->libraries_cache(); }
5498 void set_libraries_cache(const Array& cache) const;
5499 LibraryPtr LookupLibrary(Thread* thread, const Smi& name_index) const;
5500 LibraryPtr InsertLibrary(Thread* thread,
5501 const Smi& name_index,
5502 const Library& lib) const;
5503
5504 ArrayPtr classes_cache() const { return untag()->classes_cache(); }
5505 void set_classes_cache(const Array& cache) const;
5506 ClassPtr LookupClass(Thread* thread, const Smi& name_index) const;
5507 ClassPtr InsertClass(Thread* thread,
5508 const Smi& name_index,
5509 const Class& klass) const;
5510
5511 private:
5512 static KernelProgramInfoPtr New();
5513
5515 friend class Class;
5516};
5517
5518// ObjectPool contains constants, immediates and addresses referenced by
5519// generated code and deoptimization infos. Each entry has an type associated
5520// with it which is stored in-inline after all the entries.
5521class ObjectPool : public Object {
5522 public:
5530
5531 struct Entry {
5532 Entry() : raw_value_(), type_() {}
5533 explicit Entry(const Object* obj)
5534 : obj_(obj), type_(EntryType::kTaggedObject) {}
5535 Entry(uword value, EntryType info) : raw_value_(value), type_(info) {}
5536 union {
5537 const Object* obj_;
5539 };
5541 };
5542
5543 intptr_t Length() const { return untag()->length_; }
5544 void SetLength(intptr_t value) const {
5545 StoreNonPointer(&untag()->length_, value);
5546 }
5547
5548 static intptr_t length_offset() {
5549 return OFFSET_OF(UntaggedObjectPool, length_);
5550 }
5551 static intptr_t data_offset() {
5553 }
5554 static intptr_t element_offset(intptr_t index) {
5556 sizeof(UntaggedObjectPool::Entry) * index;
5557 }
5558
5560 static intptr_t elements_start_offset() {
5561 return ObjectPool::data_offset();
5562 }
5563
5564 static constexpr intptr_t kElementSize = sizeof(UntaggedObjectPool::Entry);
5565 };
5566
5567 EntryType TypeAt(intptr_t index) const {
5568 ASSERT((index >= 0) && (index <= Length()));
5569 return TypeBits::decode(untag()->entry_bits()[index]);
5570 }
5571
5572 Patchability PatchableAt(intptr_t index) const {
5573 ASSERT((index >= 0) && (index <= Length()));
5574 return PatchableBit::decode(untag()->entry_bits()[index]);
5575 }
5576
5577 SnapshotBehavior SnapshotBehaviorAt(intptr_t index) const {
5578 ASSERT((index >= 0) && (index <= Length()));
5579 return SnapshotBehaviorBits::decode(untag()->entry_bits()[index]);
5580 }
5581
5582 static uint8_t EncodeBits(EntryType type,
5583 Patchability patchable,
5584 SnapshotBehavior snapshot_behavior) {
5585 return PatchableBit::encode(patchable) | TypeBits::encode(type) |
5586 SnapshotBehaviorBits::encode(snapshot_behavior);
5587 }
5588
5589 void SetTypeAt(intptr_t index,
5591 Patchability patchable,
5592 SnapshotBehavior snapshot_behavior) const {
5593 ASSERT(index >= 0 && index <= Length());
5594 const uint8_t bits = EncodeBits(type, patchable, snapshot_behavior);
5595 StoreNonPointer(&untag()->entry_bits()[index], bits);
5596 }
5597
5598 template <std::memory_order order = std::memory_order_relaxed>
5599 ObjectPtr ObjectAt(intptr_t index) const {
5600 ASSERT(TypeAt(index) == EntryType::kTaggedObject);
5601 return LoadPointer<ObjectPtr, order>(&(EntryAddr(index)->raw_obj_));
5602 }
5603
5604 template <std::memory_order order = std::memory_order_relaxed>
5605 void SetObjectAt(intptr_t index, const Object& obj) const {
5606 ASSERT((TypeAt(index) == EntryType::kTaggedObject) ||
5607 (TypeAt(index) == EntryType::kImmediate && obj.IsSmi()));
5608 StorePointer<ObjectPtr, order>(&EntryAddr(index)->raw_obj_, obj.ptr());
5609 }
5610
5611 uword RawValueAt(intptr_t index) const {
5612 ASSERT(TypeAt(index) != EntryType::kTaggedObject);
5613 return EntryAddr(index)->raw_value_;
5614 }
5615 void SetRawValueAt(intptr_t index, uword raw_value) const {
5616 ASSERT(TypeAt(index) != EntryType::kTaggedObject);
5617 StoreNonPointer(&EntryAddr(index)->raw_value_, raw_value);
5618 }
5619
5620 static intptr_t InstanceSize() {
5621 ASSERT(sizeof(UntaggedObjectPool) ==
5623 return 0;
5624 }
5625
5626 static constexpr intptr_t kBytesPerElement =
5627 sizeof(UntaggedObjectPool::Entry) + sizeof(uint8_t);
5628 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
5629
5630 static intptr_t InstanceSize(intptr_t len) {
5631 // Ensure that variable length data is not adding to the object length.
5632 ASSERT(sizeof(UntaggedObjectPool) ==
5633 (sizeof(UntaggedObject) + (1 * kWordSize)));
5634 ASSERT(0 <= len && len <= kMaxElements);
5635 return RoundedAllocationSize(sizeof(UntaggedObjectPool) +
5636 (len * kBytesPerElement));
5637 }
5638
5639 static ObjectPoolPtr NewFromBuilder(
5640 const compiler::ObjectPoolBuilder& builder);
5641 static ObjectPoolPtr New(intptr_t len);
5642
5643 void CopyInto(compiler::ObjectPoolBuilder* builder) const;
5644
5645 // Returns the pool index from the offset relative to a tagged ObjectPoolPtr,
5646 // adjusting for the tag-bit.
5647 static intptr_t IndexFromOffset(intptr_t offset) {
5648 ASSERT(
5649 Utils::IsAligned(offset + kHeapObjectTag, compiler::target::kWordSize));
5650#if defined(DART_PRECOMPILER)
5651 return (offset + kHeapObjectTag -
5652 compiler::target::ObjectPool::element_offset(0)) /
5653 compiler::target::kWordSize;
5654#else
5655 return (offset + kHeapObjectTag - element_offset(0)) / kWordSize;
5656#endif
5657 }
5658
5659 static intptr_t OffsetFromIndex(intptr_t index) {
5660 return element_offset(index) - kHeapObjectTag;
5661 }
5662
5663 void DebugPrint() const;
5664
5665 private:
5666 UntaggedObjectPool::Entry const* EntryAddr(intptr_t index) const {
5667 ASSERT((index >= 0) && (index < Length()));
5668 return &untag()->data()[index];
5669 }
5670
5671 FINAL_HEAP_OBJECT_IMPLEMENTATION(ObjectPool, Object);
5672 friend class Class;
5673 friend class Object;
5675};
5676
5677class Instructions : public Object {
5678 public:
5679 enum {
5680 kSizePos = 0,
5681 kSizeSize = 30,
5682 kFlagsPos = kSizePos + kSizeSize,
5683 kFlagsSize = kBitsPerInt32 - kSizeSize,
5684 };
5685
5686#define INSTRUCTIONS_FLAGS_LIST(V) \
5687 V(HasMonomorphicEntry) \
5688 V(ShouldBeAligned)
5689
5690 enum {
5691#define DEFINE_INSTRUCTIONS_FLAG(Name) k##Name##Index,
5693#undef DEFINE_INSTRUCTIONS_FLAG
5694 };
5695
5696 class SizeBits : public BitField<uint32_t, uint32_t, kSizePos, kSizeSize> {};
5697
5698#define DEFINE_INSTRUCTIONS_FLAG_HANDLING(Name) \
5699 class Name##Bit \
5700 : public BitField<uint32_t, bool, kFlagsPos + k##Name##Index, 1> {}; \
5701 bool Name() const { return Name##Bit::decode(untag()->size_and_flags_); } \
5702 static bool Name(const InstructionsPtr instr) { \
5703 return Name##Bit::decode(instr->untag()->size_and_flags_); \
5704 }
5705
5707
5708#undef DEFINE_INSTRUCTIONS_FLAG_HANDLING
5709
5710 // Excludes HeaderSize().
5711 intptr_t Size() const { return SizeBits::decode(untag()->size_and_flags_); }
5712 static intptr_t Size(const InstructionsPtr instr) {
5713 return SizeBits::decode(instr->untag()->size_and_flags_);
5714 }
5715
5716 uword PayloadStart() const { return PayloadStart(ptr()); }
5718 uword EntryPoint() const { return EntryPoint(ptr()); }
5719 static uword PayloadStart(const InstructionsPtr instr) {
5720 return reinterpret_cast<uword>(instr->untag()) + HeaderSize();
5721 }
5722
5723// Note: We keep the checked entrypoint offsets even (emitting NOPs if
5724// necessary) to allow them to be seen as Smis by the GC.
5725#if defined(TARGET_ARCH_IA32)
5726 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 6;
5727 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 36;
5728 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 0;
5729 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 0;
5730#elif defined(TARGET_ARCH_X64)
5731 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 8;
5732 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 42;
5733 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 8;
5734 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 22;
5735#elif defined(TARGET_ARCH_ARM)
5736 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 0;
5737 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 44;
5738 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 0;
5739 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 16;
5740#elif defined(TARGET_ARCH_ARM64)
5741 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 8;
5742 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 52;
5743 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 8;
5744 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 24;
5745#elif defined(TARGET_ARCH_RISCV32)
5746 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 6;
5747 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 44;
5748 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 6;
5749 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 18;
5750#elif defined(TARGET_ARCH_RISCV64)
5751 static constexpr intptr_t kMonomorphicEntryOffsetJIT = 6;
5752 static constexpr intptr_t kPolymorphicEntryOffsetJIT = 44;
5753 static constexpr intptr_t kMonomorphicEntryOffsetAOT = 6;
5754 static constexpr intptr_t kPolymorphicEntryOffsetAOT = 18;
5755#else
5756#error Missing entry offsets for current architecture
5757#endif
5758
5759 static uword MonomorphicEntryPoint(const InstructionsPtr instr) {
5760 uword entry = PayloadStart(instr);
5761 if (HasMonomorphicEntry(instr)) {
5762 entry += !FLAG_precompiled_mode ? kMonomorphicEntryOffsetJIT
5763 : kMonomorphicEntryOffsetAOT;
5764 }
5765 return entry;
5766 }
5767
5768 static uword EntryPoint(const InstructionsPtr instr) {
5769 uword entry = PayloadStart(instr);
5770 if (HasMonomorphicEntry(instr)) {
5771 entry += !FLAG_precompiled_mode ? kPolymorphicEntryOffsetJIT
5772 : kPolymorphicEntryOffsetAOT;
5773 }
5774 return entry;
5775 }
5776
5777 static constexpr intptr_t kMaxElements =
5778 (kMaxInt32 - (sizeof(UntaggedInstructions) + sizeof(UntaggedObject) +
5779 (2 * kObjectStartAlignment)));
5780
5781 // Currently, we align bare instruction payloads on 4 byte boundaries.
5782 //
5783 // If we later decide to align on larger boundaries to put entries at the
5784 // start of cache lines, make sure to account for entry points that are
5785 // _not_ at the start of the payload.
5786 static constexpr intptr_t kBarePayloadAlignment = 4;
5787
5788 // When instructions reside in the heap we align the payloads on word
5789 // boundaries.
5790 static constexpr intptr_t kNonBarePayloadAlignment = kWordSize;
5791
5792 // In the precompiled runtime when running in bare instructions mode,
5793 // Instructions objects don't exist, just their bare payloads, so we
5794 // mark them as unreachable in that case.
5795
5796 static intptr_t HeaderSize() {
5797#if defined(DART_PRECOMPILED_RUNTIME)
5798 UNREACHABLE();
5799#endif
5800 return Utils::RoundUp(sizeof(UntaggedInstructions),
5801 kNonBarePayloadAlignment);
5802 }
5803
5804 static intptr_t InstanceSize() {
5807 return 0;
5808 }
5809
5810 static intptr_t InstanceSize(intptr_t size) {
5811#if defined(DART_PRECOMPILED_RUNTIME)
5812 UNREACHABLE();
5813#endif
5814 return RoundedAllocationSize(HeaderSize() + size);
5815 }
5816
5817 static InstructionsPtr FromPayloadStart(uword payload_start) {
5818#if defined(DART_PRECOMPILED_RUNTIME)
5819 UNREACHABLE();
5820#endif
5821 return static_cast<InstructionsPtr>(payload_start - HeaderSize() +
5823 }
5824
5825 bool Equals(const Instructions& other) const {
5826 return Equals(ptr(), other.ptr());
5827 }
5828
5829 static bool Equals(InstructionsPtr a, InstructionsPtr b) {
5830 // This method should only be called on non-null Instructions objects.
5831 ASSERT_EQUAL(a->GetClassId(), kInstructionsCid);
5832 ASSERT_EQUAL(b->GetClassId(), kInstructionsCid);
5833 // Don't include the object header tags wholesale in the comparison,
5834 // because the GC tags may differ in JIT mode. In fact, we can skip checking
5835 // the object header entirely, as we're guaranteed that the cids match,
5836 // because there are no subclasses for the Instructions class, and the sizes
5837 // should match if the content size encoded in size_and_flags_ matches.
5838 if (a->untag()->size_and_flags_ != b->untag()->size_and_flags_) {
5839 return false;
5840 }
5841 NoSafepointScope no_safepoint;
5842 return memcmp(a->untag()->data(), b->untag()->data(), Size(a)) == 0;
5843 }
5844
5845 uint32_t Hash() const { return Hash(ptr()); }
5846
5847 static uint32_t Hash(const InstructionsPtr instr) {
5848 return HashBytes(reinterpret_cast<const uint8_t*>(PayloadStart(instr)),
5849 Size(instr));
5850 }
5851
5852 CodeStatistics* stats() const;
5853 void set_stats(CodeStatistics* stats) const;
5854
5855 private:
5856 friend struct RelocatorTestHelper;
5857
5858 void SetSize(intptr_t value) const {
5859 ASSERT(value >= 0);
5860 StoreNonPointer(&untag()->size_and_flags_,
5861 SizeBits::update(value, untag()->size_and_flags_));
5862 }
5863
5864#define DEFINE_INSTRUCTIONS_FLAG_HANDLING(Name) \
5865 void Set##Name(bool value) const { \
5866 StoreNonPointer(&untag()->size_and_flags_, \
5867 Name##Bit::update(value, untag()->size_and_flags_)); \
5868 }
5869
5871
5872#undef DEFINE_INSTRUCTIONS_FLAG_HANDLING
5873
5874 // New is a private method as RawInstruction and RawCode objects should
5875 // only be created using the Code::FinalizeCode method. This method creates
5876 // the RawInstruction and RawCode objects, sets up the pointer offsets
5877 // and links the two in a GC safe manner.
5878 static InstructionsPtr New(intptr_t size,
5879 bool has_monomorphic_entry,
5880 bool should_be_aligned);
5881
5883 friend class Class;
5884 friend class Code;
5885 friend class AssemblyImageWriter;
5886 friend class BlobImageWriter;
5887 friend class ImageWriter;
5888};
5889
5890// An InstructionsSection contains extra information about serialized AOT
5891// snapshots.
5892//
5893// To avoid changing the embedder to return more information about an AOT
5894// snapshot and possibly disturbing existing clients of that interface, we
5895// serialize a single InstructionsSection object at the start of any text
5896// segments. In bare instructions mode, it also has the benefit of providing
5897// memory accounting for the instructions payloads and avoiding special casing
5898// Images with bare instructions payloads in the GC. Otherwise, it is empty
5899// and the Instructions objects come after it in the Image.
5901 public:
5902 // Excludes HeaderSize().
5903 static intptr_t Size(const InstructionsSectionPtr instr) {
5904 return instr->untag()->payload_length_;
5905 }
5906 static intptr_t InstanceSize() {
5909 return 0;
5910 }
5911
5912 static intptr_t InstanceSize(intptr_t size) {
5913 return Utils::RoundUp(HeaderSize() + size, kObjectAlignment);
5914 }
5915
5916 static constexpr intptr_t kPayloadAlignment = 32;
5917 static_assert(kPreferredLoopAlignment <= kPayloadAlignment);
5918 static_assert(Instructions::kBarePayloadAlignment <= kPayloadAlignment);
5919
5920 static intptr_t HeaderSize() {
5921 return Utils::RoundUp(sizeof(UntaggedInstructionsSection),
5922 kPayloadAlignment);
5923 }
5924
5925 // There are no public instance methods for the InstructionsSection class, as
5926 // all access to the contents is handled by methods on the Image class.
5927
5928 private:
5929 // Note there are no New() methods for InstructionsSection. Instead, the
5930 // serializer writes the UntaggedInstructionsSection object manually at the
5931 // start of instructions Images in precompiled snapshots.
5932
5934 friend class Class;
5935};
5936
5937// Table which maps ranges of machine code to [Code] or
5938// [CompressedStackMaps] objects.
5939// Used in AOT in bare instructions mode.
5941 public:
5942 static intptr_t InstanceSize() { return sizeof(UntaggedInstructionsTable); }
5943
5944 static InstructionsTablePtr New(intptr_t length,
5945 uword start_pc,
5946 uword end_pc,
5947 uword rodata);
5948
5949 void SetCodeAt(intptr_t index, CodePtr code) const;
5950
5951 bool ContainsPc(uword pc) const { return ContainsPc(ptr(), pc); }
5952 static bool ContainsPc(InstructionsTablePtr table, uword pc);
5953
5954 static CodePtr FindCode(InstructionsTablePtr table, uword pc);
5955
5957 FindStackMap(InstructionsTablePtr table, uword pc, uword* start_pc);
5958
5959 static const UntaggedCompressedStackMaps::Payload* GetCanonicalStackMap(
5960 InstructionsTablePtr table);
5961
5962 const UntaggedInstructionsTable::Data* rodata() const {
5963 return ptr()->untag()->rodata_;
5964 }
5965
5966 // Returns start address of the instructions entry with given index.
5967 uword PayloadStartAt(intptr_t index) const {
5968 return InstructionsTable::PayloadStartAt(this->ptr(), index);
5969 }
5970 static uword PayloadStartAt(InstructionsTablePtr table, intptr_t index);
5971
5972 // Returns entry point of the instructions with given index.
5973 uword EntryPointAt(intptr_t index) const;
5974
5975 private:
5976 uword start_pc() const { return InstructionsTable::start_pc(this->ptr()); }
5977 static uword start_pc(InstructionsTablePtr table) {
5978 return table->untag()->start_pc_;
5979 }
5980
5981 uword end_pc() const { return InstructionsTable::end_pc(this->ptr()); }
5982 static uword end_pc(InstructionsTablePtr table) {
5983 return table->untag()->end_pc_;
5984 }
5985
5986 ArrayPtr code_objects() const { return untag()->code_objects_; }
5987
5988 void set_length(intptr_t value) const;
5989 void set_start_pc(uword value) const;
5990 void set_end_pc(uword value) const;
5991 void set_code_objects(const Array& value) const;
5992 void set_rodata(uword rodata) const;
5993
5994 uint32_t ConvertPcToOffset(uword pc) const {
5995 return InstructionsTable::ConvertPcToOffset(this->ptr(), pc);
5996 }
5997 static uint32_t ConvertPcToOffset(InstructionsTablePtr table, uword pc);
5998
5999 static intptr_t FindEntry(InstructionsTablePtr table,
6000 uword pc,
6001 intptr_t start_index = 0);
6002
6003 FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsTable, Object);
6004 friend class Class;
6005 friend class Deserializer;
6006};
6007
6009 public:
6010 intptr_t Length() const;
6011
6012 StringPtr GetName(intptr_t var_index) const;
6013
6014 void SetVar(intptr_t var_index,
6015 const String& name,
6017
6018 void GetInfo(intptr_t var_index,
6020
6021 static constexpr intptr_t kBytesPerElement =
6023 static constexpr intptr_t kMaxElements =
6024 UntaggedLocalVarDescriptors::kMaxIndex;
6025
6026 static intptr_t InstanceSize() {
6029 return 0;
6030 }
6031 static intptr_t InstanceSize(intptr_t len) {
6032 ASSERT(0 <= len && len <= kMaxElements);
6033 return RoundedAllocationSize(
6035 (len * kWordSize) // RawStrings for names.
6036 + (len * sizeof(UntaggedLocalVarDescriptors::VarInfo)));
6037 }
6038
6039 static LocalVarDescriptorsPtr New(intptr_t num_variables);
6040
6041 static const char* KindToCString(
6043
6044 private:
6046 friend class Class;
6047 friend class Object;
6048};
6049
6050class PcDescriptors : public Object {
6051 public:
6052 static constexpr intptr_t kBytesPerElement = 1;
6053 static constexpr intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
6054
6055 static intptr_t HeaderSize() { return sizeof(UntaggedPcDescriptors); }
6056 static intptr_t UnroundedSize(PcDescriptorsPtr desc) {
6057 return UnroundedSize(desc->untag()->length_);
6058 }
6059 static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
6060 static intptr_t InstanceSize() {
6063 return 0;
6064 }
6065 static intptr_t InstanceSize(intptr_t len) {
6066 ASSERT(0 <= len && len <= kMaxElements);
6067 return RoundedAllocationSize(UnroundedSize(len));
6068 }
6069
6070 static PcDescriptorsPtr New(const void* delta_encoded_data, intptr_t size);
6071
6072 // Verify (assert) assumptions about pc descriptors in debug mode.
6073 void Verify(const Function& function) const;
6074
6075 static void PrintHeaderString();
6076
6077 void PrintToJSONObject(JSONObject* jsobj, bool ref) const;
6078
6079 // We would have a VisitPointers function here to traverse the
6080 // pc descriptors table to visit objects if any in the table.
6081 // Note: never return a reference to a UntaggedPcDescriptors::PcDescriptorRec
6082 // as the object can move.
6083 class Iterator : public ValueObject {
6084 public:
6085 Iterator(const PcDescriptors& descriptors, intptr_t kind_mask)
6086 : descriptors_(descriptors),
6087 kind_mask_(kind_mask),
6088 byte_index_(0),
6089 cur_pc_offset_(0),
6090 cur_kind_(0),
6091 cur_deopt_id_(0),
6092 cur_token_pos_(0),
6093 cur_try_index_(0),
6094 cur_yield_index_(UntaggedPcDescriptors::kInvalidYieldIndex) {}
6095
6096 bool MoveNext() {
6097 NoSafepointScope scope;
6098 ReadStream stream(descriptors_.untag()->data(), descriptors_.Length(),
6099 byte_index_);
6100 // Moves to record that matches kind_mask_.
6101 while (byte_index_ < descriptors_.Length()) {
6102 const int32_t kind_and_metadata = stream.ReadSLEB128<int32_t>();
6103 cur_kind_ = UntaggedPcDescriptors::KindAndMetadata::DecodeKind(
6104 kind_and_metadata);
6105 cur_try_index_ = UntaggedPcDescriptors::KindAndMetadata::DecodeTryIndex(
6106 kind_and_metadata);
6107 cur_yield_index_ =
6108 UntaggedPcDescriptors::KindAndMetadata::DecodeYieldIndex(
6109 kind_and_metadata);
6110
6111 cur_pc_offset_ += stream.ReadSLEB128();
6112
6113 if (!FLAG_precompiled_mode) {
6114 cur_deopt_id_ += stream.ReadSLEB128();
6115 cur_token_pos_ = Utils::AddWithWrapAround(
6116 cur_token_pos_, stream.ReadSLEB128<int32_t>());
6117 }
6118 byte_index_ = stream.Position();
6119
6120 if ((cur_kind_ & kind_mask_) != 0) {
6121 return true; // Current is valid.
6122 }
6123 }
6124 return false;
6125 }
6126
6127 uword PcOffset() const { return cur_pc_offset_; }
6128 intptr_t DeoptId() const { return cur_deopt_id_; }
6130 return TokenPosition::Deserialize(cur_token_pos_);
6131 }
6132 intptr_t TryIndex() const { return cur_try_index_; }
6133 intptr_t YieldIndex() const { return cur_yield_index_; }
6135 return static_cast<UntaggedPcDescriptors::Kind>(cur_kind_);
6136 }
6137
6138 private:
6139 friend class PcDescriptors;
6140
6141 // For nested iterations, starting at element after.
6142 explicit Iterator(const Iterator& iter)
6143 : ValueObject(),
6144 descriptors_(iter.descriptors_),
6145 kind_mask_(iter.kind_mask_),
6146 byte_index_(iter.byte_index_),
6147 cur_pc_offset_(iter.cur_pc_offset_),
6148 cur_kind_(iter.cur_kind_),
6149 cur_deopt_id_(iter.cur_deopt_id_),
6150 cur_token_pos_(iter.cur_token_pos_),
6151 cur_try_index_(iter.cur_try_index_),
6152 cur_yield_index_(iter.cur_yield_index_) {}
6153
6154 const PcDescriptors& descriptors_;
6155 const intptr_t kind_mask_;
6156 intptr_t byte_index_;
6157
6158 intptr_t cur_pc_offset_;
6159 intptr_t cur_kind_;
6160 intptr_t cur_deopt_id_;
6161 int32_t cur_token_pos_;
6162 intptr_t cur_try_index_;
6163 intptr_t cur_yield_index_;
6164 };
6165
6166 intptr_t Length() const;
6167 bool Equals(const PcDescriptors& other) const {
6168 if (Length() != other.Length()) {
6169 return false;
6170 }
6171 NoSafepointScope no_safepoint;
6172 return memcmp(untag()->data(), other.untag()->data(), Length()) == 0;
6173 }
6174
6175 // Writes the contents of the PcDescriptors object to the given buffer.
6176 // The base argument is added to the PC offset for each entry.
6177 void WriteToBuffer(BaseTextBuffer* buffer, uword base) const;
6178
6179 private:
6180 static const char* KindAsStr(UntaggedPcDescriptors::Kind kind);
6181
6182 static PcDescriptorsPtr New(intptr_t length);
6183
6184 void SetLength(intptr_t value) const;
6185 void CopyData(const void* bytes, intptr_t size);
6186
6188 friend class Class;
6189 friend class Object;
6190};
6191
6192class CodeSourceMap : public Object {
6193 public:
6194 static constexpr intptr_t kBytesPerElement = 1;
6195 static constexpr intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
6196
6197 static intptr_t HeaderSize() { return sizeof(UntaggedCodeSourceMap); }
6198 static intptr_t UnroundedSize(CodeSourceMapPtr map) {
6199 return UnroundedSize(map->untag()->length_);
6200 }
6201 static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
6202 static intptr_t InstanceSize() {
6205 return 0;
6206 }
6207 static intptr_t InstanceSize(intptr_t len) {
6208 ASSERT(0 <= len && len <= kMaxElements);
6209 return RoundedAllocationSize(UnroundedSize(len));
6210 }
6211
6212 static CodeSourceMapPtr New(intptr_t length);
6213
6214 intptr_t Length() const { return untag()->length_; }
6215 uint8_t* Data() const { return UnsafeMutableNonPointer(&untag()->data()[0]); }
6216
6217 bool Equals(const CodeSourceMap& other) const {
6218 if (Length() != other.Length()) {
6219 return false;
6220 }
6221 NoSafepointScope no_safepoint;
6222 return memcmp(untag()->data(), other.untag()->data(), Length()) == 0;
6223 }
6224
6225 uint32_t Hash() const {
6226 NoSafepointScope no_safepoint;
6227 return HashBytes(Data(), Length());
6228 }
6229
6230 void PrintToJSONObject(JSONObject* jsobj, bool ref) const;
6231
6232 private:
6233 void SetLength(intptr_t value) const;
6234
6236 friend class Class;
6237 friend class Object;
6238};
6239
6241 public:
6242 uintptr_t payload_size() const { return PayloadSizeOf(ptr()); }
6243 static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw) {
6244 return UntaggedCompressedStackMaps::SizeField::decode(
6245 raw->untag()->payload()->flags_and_size());
6246 }
6247
6248 const uint8_t* data() const { return ptr()->untag()->payload()->data(); }
6249
6250 // Methods to allow use with PointerKeyValueTrait to create sets of CSMs.
6251 bool Equals(const CompressedStackMaps& other) const {
6252 // All of the table flags and payload size must match.
6253 if (untag()->payload()->flags_and_size() !=
6254 other.untag()->payload()->flags_and_size()) {
6255 return false;
6256 }
6257 NoSafepointScope no_safepoint;
6258 return memcmp(data(), other.data(), payload_size()) == 0;
6259 }
6260 uword Hash() const;
6261
6262 static intptr_t HeaderSize() {
6263 return sizeof(UntaggedCompressedStackMaps) +
6265 }
6266 static intptr_t UnroundedSize(CompressedStackMapsPtr maps) {
6267 return UnroundedSize(CompressedStackMaps::PayloadSizeOf(maps));
6268 }
6269 static intptr_t UnroundedSize(intptr_t length) {
6270 return HeaderSize() + length;
6271 }
6272 static intptr_t InstanceSize() { return 0; }
6273 static intptr_t InstanceSize(intptr_t length) {
6274 return RoundedAllocationSize(UnroundedSize(length));
6275 }
6276
6277 bool UsesGlobalTable() const { return UsesGlobalTable(ptr()); }
6278 static bool UsesGlobalTable(const CompressedStackMapsPtr raw) {
6279 return UntaggedCompressedStackMaps::UsesTableBit::decode(
6280 raw->untag()->payload()->flags_and_size());
6281 }
6282
6283 bool IsGlobalTable() const { return IsGlobalTable(ptr()); }
6284 static bool IsGlobalTable(const CompressedStackMapsPtr raw) {
6285 return UntaggedCompressedStackMaps::GlobalTableBit::decode(
6286 raw->untag()->payload()->flags_and_size());
6287 }
6288
6289 static CompressedStackMapsPtr NewInlined(const void* payload, intptr_t size) {
6290 return New(payload, size, /*is_global_table=*/false,
6291 /*uses_global_table=*/false);
6292 }
6293 static CompressedStackMapsPtr NewUsingTable(const void* payload,
6294 intptr_t size) {
6295 return New(payload, size, /*is_global_table=*/false,
6296 /*uses_global_table=*/true);
6297 }
6298
6299 static CompressedStackMapsPtr NewGlobalTable(const void* payload,
6300 intptr_t size) {
6301 return New(payload, size, /*is_global_table=*/true,
6302 /*uses_global_table=*/false);
6303 }
6304
6306 public:
6310
6312 return payload_;
6313 }
6314 bool IsNull() const { return payload_ == nullptr; }
6315
6317 const UntaggedCompressedStackMaps::Payload* payload) {
6318 payload_ = payload;
6319 return *this;
6320 }
6321
6323 ASSERT(!maps.IsNull());
6324 payload_ = maps.untag()->payload();
6325 return *this;
6326 }
6327
6328 RawPayloadHandle& operator=(CompressedStackMapsPtr maps) {
6329 ASSERT(maps != CompressedStackMaps::null());
6330 payload_ = maps.untag()->payload();
6331 return *this;
6332 }
6333
6334 uintptr_t payload_size() const {
6335 return UntaggedCompressedStackMaps::SizeField::decode(
6336 payload()->flags_and_size());
6337 }
6338 const uint8_t* data() const { return payload()->data(); }
6339
6340 bool UsesGlobalTable() const {
6341 return UntaggedCompressedStackMaps::UsesTableBit::decode(
6342 payload()->flags_and_size());
6343 }
6344
6345 bool IsGlobalTable() const {
6346 return UntaggedCompressedStackMaps::GlobalTableBit::decode(
6347 payload()->flags_and_size());
6348 }
6349
6350 private:
6351 const UntaggedCompressedStackMaps::Payload* payload_ = nullptr;
6352 };
6353
6354 template <typename PayloadHandle>
6355 class Iterator {
6356 public:
6357 Iterator(const PayloadHandle& maps, const PayloadHandle& global_table)
6358 : maps_(maps),
6359 bits_container_(maps.UsesGlobalTable() ? global_table : maps) {
6360 ASSERT(!maps_.IsNull());
6361 ASSERT(!bits_container_.IsNull());
6362 ASSERT(!maps_.IsGlobalTable());
6363 ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
6364 }
6365
6367 : maps_(it.maps_),
6368 bits_container_(it.bits_container_),
6369 next_offset_(it.next_offset_),
6370 current_pc_offset_(it.current_pc_offset_),
6371 current_global_table_offset_(it.current_global_table_offset_),
6372 current_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
6373 current_non_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
6374 current_bits_offset_(it.current_bits_offset_) {}
6375
6376 // Loads the next entry from [maps_], if any. If [maps_] is the null value,
6377 // this always returns false.
6378 bool MoveNext() {
6379 if (next_offset_ >= maps_.payload_size()) {
6380 return false;
6381 }
6382
6383 NoSafepointScope scope;
6384 ReadStream stream(maps_.data(), maps_.payload_size(), next_offset_);
6385
6386 auto const pc_delta = stream.ReadLEB128();
6387 ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
6388 current_pc_offset_ += pc_delta;
6389
6390 // Table-using CSMs have a table offset after the PC offset delta, whereas
6391 // the post-delta part of inlined entries has the same information as
6392 // global table entries.
6393 // See comments in UntaggedCompressedStackMaps for description of
6394 // encoding.
6395 if (maps_.UsesGlobalTable()) {
6396 current_global_table_offset_ = stream.ReadLEB128();
6397 ASSERT(current_global_table_offset_ < bits_container_.payload_size());
6398
6399 // Since generally we only use entries in the GC and the GC only needs
6400 // the rest of the entry information if the PC offset matches, we lazily
6401 // load and cache the information stored in the global object when it is
6402 // actually requested.
6403 current_spill_slot_bit_count_ = -1;
6404 current_non_spill_slot_bit_count_ = -1;
6405 current_bits_offset_ = -1;
6406
6407 next_offset_ = stream.Position();
6408 } else {
6409 current_spill_slot_bit_count_ = stream.ReadLEB128();
6410 ASSERT(current_spill_slot_bit_count_ >= 0);
6411
6412 current_non_spill_slot_bit_count_ = stream.ReadLEB128();
6413 ASSERT(current_non_spill_slot_bit_count_ >= 0);
6414
6415 const auto stackmap_bits =
6416 current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
6417 const uintptr_t stackmap_size =
6418 Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
6419 ASSERT(stackmap_size <= (maps_.payload_size() - stream.Position()));
6420
6421 current_bits_offset_ = stream.Position();
6422 next_offset_ = current_bits_offset_ + stackmap_size;
6423 }
6424
6425 return true;
6426 }
6427
6428 // Finds the entry with the given PC offset starting at the current position
6429 // of the iterator. If [maps_] is the null value, this always returns false.
6430 bool Find(uint32_t pc_offset) {
6431 // We should never have an entry with a PC offset of 0 inside an
6432 // non-empty CSM, so fail.
6433 if (pc_offset == 0) return false;
6434 do {
6435 if (current_pc_offset_ >= pc_offset) break;
6436 } while (MoveNext());
6437 return current_pc_offset_ == pc_offset;
6438 }
6439
6440 // Methods for accessing parts of an entry should not be called until
6441 // a successful MoveNext() or Find() call has been made.
6442
6443 // Returns the PC offset of the loaded entry.
6444 uint32_t pc_offset() const {
6445 ASSERT(HasLoadedEntry());
6446 return current_pc_offset_;
6447 }
6448
6449 // Returns the bit length of the loaded entry.
6450 intptr_t Length() const {
6451 EnsureFullyLoadedEntry();
6452 return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
6453 }
6454 // Returns the number of spill slot bits of the loaded entry.
6455 intptr_t SpillSlotBitCount() const {
6456 EnsureFullyLoadedEntry();
6457 return current_spill_slot_bit_count_;
6458 }
6459 // Returns whether the stack entry represented by the offset contains
6460 // a tagged object.
6461 bool IsObject(intptr_t bit_index) const {
6462 EnsureFullyLoadedEntry();
6463 ASSERT(bit_index >= 0 && bit_index < Length());
6464 const intptr_t byte_index = bit_index >> kBitsPerByteLog2;
6465 const intptr_t bit_remainder = bit_index & (kBitsPerByte - 1);
6466 uint8_t byte_mask = 1U << bit_remainder;
6467 const intptr_t byte_offset = current_bits_offset_ + byte_index;
6468 NoSafepointScope scope;
6469 return (bits_container_.data()[byte_offset] & byte_mask) != 0;
6470 }
6471
6472 private:
6473 bool HasLoadedEntry() const { return next_offset_ > 0; }
6474
6475 // Caches the corresponding values from the global table in the mutable
6476 // fields. We lazily load these as some clients only need the PC offset.
6477 void LazyLoadGlobalTableEntry() const {
6478 ASSERT(maps_.UsesGlobalTable());
6479 ASSERT(HasLoadedEntry());
6480 ASSERT(current_global_table_offset_ < bits_container_.payload_size());
6481
6482 NoSafepointScope scope;
6483 ReadStream stream(bits_container_.data(), bits_container_.payload_size(),
6484 current_global_table_offset_);
6485
6486 current_spill_slot_bit_count_ = stream.ReadLEB128();
6487 ASSERT(current_spill_slot_bit_count_ >= 0);
6488
6489 current_non_spill_slot_bit_count_ = stream.ReadLEB128();
6490 ASSERT(current_non_spill_slot_bit_count_ >= 0);
6491
6492 const auto stackmap_bits = Length();
6493 const uintptr_t stackmap_size =
6494 Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
6495 ASSERT(stackmap_size <=
6496 (bits_container_.payload_size() - stream.Position()));
6497
6498 current_bits_offset_ = stream.Position();
6499 }
6500
6501 void EnsureFullyLoadedEntry() const {
6502 ASSERT(HasLoadedEntry());
6503 if (current_spill_slot_bit_count_ < 0) {
6504 LazyLoadGlobalTableEntry();
6505 ASSERT(current_spill_slot_bit_count_ >= 0);
6506 }
6507 }
6508
6509 const PayloadHandle& maps_;
6510 const PayloadHandle& bits_container_;
6511
6512 uintptr_t next_offset_ = 0;
6513 uint32_t current_pc_offset_ = 0;
6514 // Only used when looking up non-PC information in the global table.
6515 uintptr_t current_global_table_offset_ = 0;
6516 // Marked as mutable as these fields may be updated with lazily loaded
6517 // values from the global table when their associated accessor is called,
6518 // but those values will never change for a given entry once loaded..
6519 mutable intptr_t current_spill_slot_bit_count_ = -1;
6520 mutable intptr_t current_non_spill_slot_bit_count_ = -1;
6521 mutable intptr_t current_bits_offset_ = -1;
6522
6523 friend class StackMapEntry;
6524 };
6525
6526 Iterator<CompressedStackMaps> iterator(Thread* thread) const;
6527
6528 // Writes the contents of the CompressedStackMaps object to the given buffer.
6529 // The base argument is added to the PC offset for each entry, and the
6530 // separator string is inserted between each entry.
6531 void WriteToBuffer(BaseTextBuffer* buffer,
6532 uword base,
6533 const char* separator) const;
6534
6535 private:
6536 static CompressedStackMapsPtr New(const void* payload,
6537 intptr_t size,
6538 bool is_global_table,
6539 bool uses_global_table);
6540
6542 friend class Class;
6543};
6544
6546 public:
6547 static constexpr intptr_t kInvalidPcOffset = 0;
6548
6549 intptr_t num_entries() const;
6550
6551 bool has_async_handler() const;
6552 void set_has_async_handler(bool value) const;
6553
6554 void GetHandlerInfo(intptr_t try_index, ExceptionHandlerInfo* info) const;
6555
6556 uword HandlerPCOffset(intptr_t try_index) const;
6557 intptr_t OuterTryIndex(intptr_t try_index) const;
6558 bool NeedsStackTrace(intptr_t try_index) const;
6559 bool IsGenerated(intptr_t try_index) const;
6560
6561 void SetHandlerInfo(intptr_t try_index,
6562 intptr_t outer_try_index,
6563 uword handler_pc_offset,
6564 bool needs_stacktrace,
6565 bool has_catch_all,
6566 bool is_generated) const;
6567
6568 ArrayPtr GetHandledTypes(intptr_t try_index) const;
6569 void SetHandledTypes(intptr_t try_index, const Array& handled_types) const;
6570 bool HasCatchAll(intptr_t try_index) const;
6571
6573 static intptr_t elements_start_offset() {
6574 return sizeof(UntaggedExceptionHandlers);
6575 }
6576 static constexpr intptr_t kElementSize = sizeof(ExceptionHandlerInfo);
6577 };
6578
6579 static intptr_t InstanceSize() {
6582 return 0;
6583 }
6584 static intptr_t InstanceSize(intptr_t len) {
6585 return RoundedAllocationSize(sizeof(UntaggedExceptionHandlers) +
6586 (len * sizeof(ExceptionHandlerInfo)));
6587 }
6588
6589 static ExceptionHandlersPtr New(intptr_t num_handlers);
6590 static ExceptionHandlersPtr New(const Array& handled_types_data);
6591
6592 // We would have a VisitPointers function here to traverse the
6593 // exception handler table to visit objects if any in the table.
6594
6595 // Writes the contents of the ExceptionHandlers object to the given buffer.
6596 // The base argument is added to the PC offset for each entry.
6597 void WriteToBuffer(BaseTextBuffer* buffer, uword base) const;
6598
6599 private:
6600 // Pick somewhat arbitrary maximum number of exception handlers
6601 // for a function. This value is used to catch potentially
6602 // malicious code.
6603 static constexpr intptr_t kMaxHandlers = 1024 * 1024;
6604
6605 void set_handled_types_data(const Array& value) const;
6606
6608 friend class Class;
6609 friend class Object;
6610};
6611
6612// A WeakSerializationReference (WSR) denotes a type of weak reference to a
6613// target object. In particular, objects that can only be reached from roots via
6614// WSR edges during serialization of AOT snapshots should not be serialized, but
6615// instead references to these objects should be replaced with a reference to
6616// the provided replacement object.
6617//
6618// Of course, the target object may still be serialized if there are paths to
6619// the object from the roots that do not go through one of these objects. In
6620// this case, references through WSRs are serialized as direct references to
6621// the target.
6622//
6623// Unfortunately a WSR is not a proxy for the original object, so WSRs may
6624// only currently be used with ObjectPtr fields. To ease this situation for
6625// fields that are normally a non-ObjectPtr type outside of the precompiler,
6626// use the following macros, which avoid the need to adjust other code to
6627// handle the WSR case:
6628//
6629// * WSR_*POINTER_FIELD() in raw_object.h (i.e., just append WSR_ to the
6630// original field declaration).
6631// * PRECOMPILER_WSR_FIELD_DECLARATION() in object.h
6632// * PRECOMPILER_WSR_FIELD_DEFINITION() in object.cc
6634 public:
6635 ObjectPtr target() const { return TargetOf(ptr()); }
6636 static ObjectPtr TargetOf(const WeakSerializationReferencePtr obj) {
6637 return obj->untag()->target();
6638 }
6639
6641#if defined(DART_PRECOMPILER)
6642 if (obj->IsHeapObject() && obj->IsWeakSerializationReference()) {
6643 return TargetOf(static_cast<WeakSerializationReferencePtr>(obj));
6644 }
6645#endif
6646 return obj;
6647 }
6648 static ObjectPtr Unwrap(const Object& obj) { return Unwrap(obj.ptr()); }
6649 static ObjectPtr UnwrapIfTarget(ObjectPtr obj) { return Unwrap(obj); }
6650 static ObjectPtr UnwrapIfTarget(const Object& obj) { return Unwrap(obj); }
6651
6652 static intptr_t InstanceSize() {
6653 return RoundedAllocationSize(sizeof(UntaggedWeakSerializationReference));
6654 }
6655
6656 // Returns an ObjectPtr as the target may not need wrapping (e.g., it
6657 // is guaranteed to be serialized).
6658 static ObjectPtr New(const Object& target, const Object& replacement);
6659
6660 private:
6662
6663 ObjectPtr replacement() const { return untag()->replacement(); }
6664
6665 friend class Class;
6666};
6667
6668class WeakArray : public Object {
6669 public:
6670 intptr_t Length() const { return LengthOf(ptr()); }
6671 static inline intptr_t LengthOf(const WeakArrayPtr array);
6672
6673 static intptr_t length_offset() {
6674 return OFFSET_OF(UntaggedWeakArray, length_);
6675 }
6676 static intptr_t data_offset() {
6678 }
6679 static intptr_t element_offset(intptr_t index) {
6681 kBytesPerElement * index;
6682 }
6683 static intptr_t index_at_offset(intptr_t offset_in_bytes) {
6684 intptr_t index = (offset_in_bytes - data_offset()) / kBytesPerElement;
6685 ASSERT(index >= 0);
6686 return index;
6687 }
6688
6690 static intptr_t elements_start_offset() { return WeakArray::data_offset(); }
6691
6692 static constexpr intptr_t kElementSize = kCompressedWordSize;
6693 };
6694
6695 ObjectPtr At(intptr_t index) const { return untag()->element(index); }
6696 void SetAt(intptr_t index, const Object& value) const {
6697 untag()->set_element(index, value.ptr());
6698 }
6699
6700 // Access to the array with acquire release semantics.
6701 ObjectPtr AtAcquire(intptr_t index) const {
6702 return untag()->element<std::memory_order_acquire>(index);
6703 }
6704 void SetAtRelease(intptr_t index, const Object& value) const {
6705 untag()->set_element<std::memory_order_release>(index, value.ptr());
6706 }
6707
6708 static constexpr intptr_t kBytesPerElement = kCompressedWordSize;
6709 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
6710
6711 static constexpr bool IsValidLength(intptr_t length) {
6712 return 0 <= length && length <= kMaxElements;
6713 }
6714
6715 static intptr_t InstanceSize() {
6716 ASSERT(sizeof(UntaggedWeakArray) ==
6718 return 0;
6719 }
6720
6721 static constexpr intptr_t InstanceSize(intptr_t len) {
6722 return RoundedAllocationSize(sizeof(UntaggedWeakArray) +
6723 (len * kBytesPerElement));
6724 }
6725
6726 static WeakArrayPtr New(intptr_t length, Heap::Space space = Heap::kNew);
6727
6728 private:
6730 friend class Class;
6731 friend class Object;
6732};
6733
6734class Code : public Object {
6735 public:
6736 // When dual mapping, this returns the executable view.
6737 InstructionsPtr active_instructions() const {
6738#if defined(DART_PRECOMPILED_RUNTIME)
6739 UNREACHABLE();
6740 return nullptr;
6741#else
6742 return untag()->active_instructions();
6743#endif
6744 }
6745
6746 // When dual mapping, these return the executable view.
6747 InstructionsPtr instructions() const { return untag()->instructions(); }
6748 static InstructionsPtr InstructionsOf(const CodePtr code) {
6749 return code->untag()->instructions();
6750 }
6751
6752 static intptr_t instructions_offset() {
6753 return OFFSET_OF(UntaggedCode, instructions_);
6754 }
6755#if !defined(DART_PRECOMPILED_RUNTIME)
6756 static intptr_t active_instructions_offset() {
6757 return OFFSET_OF(UntaggedCode, active_instructions_);
6758 }
6759#endif
6760
6762
6763 static const char* EntryKindToCString(EntryKind kind);
6764 static bool ParseEntryKind(const char* str, EntryKind* out);
6765
6766 static intptr_t entry_point_offset(EntryKind kind = EntryKind::kNormal) {
6767 switch (kind) {
6768 case EntryKind::kNormal:
6769 return OFFSET_OF(UntaggedCode, entry_point_);
6770 case EntryKind::kUnchecked:
6771 return OFFSET_OF(UntaggedCode, unchecked_entry_point_);
6772 case EntryKind::kMonomorphic:
6773 return OFFSET_OF(UntaggedCode, monomorphic_entry_point_);
6774 case EntryKind::kMonomorphicUnchecked:
6775 return OFFSET_OF(UntaggedCode, monomorphic_unchecked_entry_point_);
6776 default:
6777 UNREACHABLE();
6778 }
6779 }
6780
6781 ObjectPoolPtr object_pool() const { return untag()->object_pool(); }
6782 static intptr_t object_pool_offset() {
6783 return OFFSET_OF(UntaggedCode, object_pool_);
6784 }
6785
6786 intptr_t pointer_offsets_length() const {
6787 return PtrOffBits::decode(untag()->state_bits_);
6788 }
6789
6790 bool is_optimized() const {
6791 return OptimizedBit::decode(untag()->state_bits_);
6792 }
6793 void set_is_optimized(bool value) const;
6794 static bool IsOptimized(CodePtr code) {
6795 return Code::OptimizedBit::decode(code->untag()->state_bits_);
6796 }
6797
6798 bool is_force_optimized() const {
6799 return ForceOptimizedBit::decode(untag()->state_bits_);
6800 }
6801 void set_is_force_optimized(bool value) const;
6802
6803 bool is_alive() const { return AliveBit::decode(untag()->state_bits_); }
6804 void set_is_alive(bool value) const;
6805
6806 bool is_discarded() const { return IsDiscarded(ptr()); }
6807 static bool IsDiscarded(const CodePtr code) {
6808 return DiscardedBit::decode(code->untag()->state_bits_);
6809 }
6810 void set_is_discarded(bool value) const;
6811
6812 bool HasMonomorphicEntry() const { return HasMonomorphicEntry(ptr()); }
6813 static bool HasMonomorphicEntry(const CodePtr code) {
6814#if defined(DART_PRECOMPILED_RUNTIME)
6815 return code->untag()->entry_point_ !=
6816 code->untag()->monomorphic_entry_point_;
6817#else
6818 return Instructions::HasMonomorphicEntry(InstructionsOf(code));
6819#endif
6820 }
6821
6822 // Returns the payload start of [instructions()].
6823 uword PayloadStart() const { return PayloadStartOf(ptr()); }
6824 static uword PayloadStartOf(const CodePtr code) {
6825#if defined(DART_PRECOMPILED_RUNTIME)
6826 if (IsUnknownDartCode(code)) return 0;
6827 const uword entry_offset = HasMonomorphicEntry(code)
6828 ? Instructions::kPolymorphicEntryOffsetAOT
6829 : 0;
6830 return EntryPointOf(code) - entry_offset;
6831#else
6832 return Instructions::PayloadStart(InstructionsOf(code));
6833#endif
6834 }
6835
6836 // Returns the entry point of [instructions()].
6837 uword EntryPoint() const { return EntryPointOf(ptr()); }
6838 static uword EntryPointOf(const CodePtr code) {
6839#if defined(DART_PRECOMPILED_RUNTIME)
6840 return code->untag()->entry_point_;
6841#else
6842 return Instructions::EntryPoint(InstructionsOf(code));
6843#endif
6844 }
6845
6846 static uword UncheckedEntryPointOf(const CodePtr code) {
6847 return code->untag()->unchecked_entry_point_;
6848 }
6849
6850 // Returns the unchecked entry point of [instructions()].
6852#if defined(DART_PRECOMPILED_RUNTIME)
6853 return untag()->unchecked_entry_point_;
6854#else
6855 return EntryPoint() + untag()->unchecked_offset_;
6856#endif
6857 }
6858 // Returns the monomorphic entry point of [instructions()].
6860#if defined(DART_PRECOMPILED_RUNTIME)
6861 return untag()->monomorphic_entry_point_;
6862#else
6863 return Instructions::MonomorphicEntryPoint(instructions());
6864#endif
6865 }
6866 // Returns the unchecked monomorphic entry point of [instructions()].
6868#if defined(DART_PRECOMPILED_RUNTIME)
6869 return untag()->monomorphic_unchecked_entry_point_;
6870#else
6871 return MonomorphicEntryPoint() + untag()->unchecked_offset_;
6872#endif
6873 }
6874
6875 // Returns the size of [instructions()].
6876 uword Size() const { return PayloadSizeOf(ptr()); }
6877 static uword PayloadSizeOf(const CodePtr code) {
6878#if defined(DART_PRECOMPILED_RUNTIME)
6879 if (IsUnknownDartCode(code)) return kUwordMax;
6880 return code->untag()->instructions_length_;
6881#else
6882 return Instructions::Size(InstructionsOf(code));
6883#endif
6884 }
6885
6886 ObjectPoolPtr GetObjectPool() const;
6887 // Returns whether the given PC address is in [instructions()].
6888 bool ContainsInstructionAt(uword addr) const {
6889 return ContainsInstructionAt(ptr(), addr);
6890 }
6891
6892 // Returns whether the given PC address is in [InstructionsOf(code)].
6893 static bool ContainsInstructionAt(const CodePtr code, uword pc) {
6894 return UntaggedCode::ContainsPC(code, pc);
6895 }
6896
6897 // Returns true if there is a debugger breakpoint set in this code object.
6898 bool HasBreakpoint() const;
6899
6900 PcDescriptorsPtr pc_descriptors() const { return untag()->pc_descriptors(); }
6901 void set_pc_descriptors(const PcDescriptors& descriptors) const {
6902 ASSERT(descriptors.IsOld());
6903 untag()->set_pc_descriptors(descriptors.ptr());
6904 }
6905
6906 CodeSourceMapPtr code_source_map() const {
6907 return untag()->code_source_map();
6908 }
6909
6910 void set_code_source_map(const CodeSourceMap& code_source_map) const {
6911 ASSERT(code_source_map.IsOld());
6912 untag()->set_code_source_map(code_source_map.ptr());
6913 }
6914
6915 // Array of DeoptInfo objects.
6916 ArrayPtr deopt_info_array() const {
6917#if defined(DART_PRECOMPILED_RUNTIME)
6918 UNREACHABLE();
6919 return nullptr;
6920#else
6921 return untag()->deopt_info_array();
6922#endif
6923 }
6924 void set_deopt_info_array(const Array& array) const;
6925
6926#if !defined(DART_PRECOMPILED_RUNTIME)
6927 intptr_t num_variables() const;
6928 void set_num_variables(intptr_t num_variables) const;
6929#endif
6930
6931#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
6932 TypedDataPtr catch_entry_moves_maps() const;
6933 void set_catch_entry_moves_maps(const TypedData& maps) const;
6934#endif
6935
6936 CompressedStackMapsPtr compressed_stackmaps() const {
6937 return untag()->compressed_stackmaps();
6938 }
6939 void set_compressed_stackmaps(const CompressedStackMaps& maps) const;
6940
6942 kPcRelativeCall = 1,
6943 kPcRelativeTTSCall = 2,
6944 kPcRelativeTailCall = 3,
6945 kCallViaCode = 4,
6946 };
6947
6952
6954 kSCallTableKindAndOffset = 0,
6955 kSCallTableCodeOrTypeTarget = 1,
6956 kSCallTableFunctionTarget = 2,
6957 kSCallTableEntryLength = 3,
6958 };
6959
6960 enum class PoolAttachment {
6961 kAttachPool,
6962 kNotAttachPool,
6963 };
6964
6965 class KindField : public BitField<intptr_t, CallKind, 0, 3> {};
6967 : public BitField<intptr_t, CallEntryPoint, KindField::kNextBit, 1> {};
6969 : public BitField<intptr_t, intptr_t, EntryPointField::kNextBit, 26> {};
6970
6971 void set_static_calls_target_table(const Array& value) const;
6972 ArrayPtr static_calls_target_table() const {
6973#if defined(DART_PRECOMPILED_RUNTIME)
6974 UNREACHABLE();
6975 return nullptr;
6976#else
6977 return untag()->static_calls_target_table();
6978#endif
6979 }
6980
6981 TypedDataPtr GetDeoptInfoAtPc(uword pc,
6982 ICData::DeoptReasonId* deopt_reason,
6983 uint32_t* deopt_flags) const;
6984
6985 // Returns null if there is no static call at 'pc'.
6986 FunctionPtr GetStaticCallTargetFunctionAt(uword pc) const;
6987 // Aborts if there is no static call at 'pc'.
6988 void SetStaticCallTargetCodeAt(uword pc, const Code& code) const;
6989 void SetStubCallTargetCodeAt(uword pc, const Code& code) const;
6990
6991 void Disassemble(DisassemblyFormatter* formatter = nullptr) const;
6992
6993#if defined(INCLUDE_IL_PRINTER)
6994 class Comments : public ZoneAllocated, public CodeComments {
6995 public:
6996 static Comments& New(intptr_t count);
6997
6998 intptr_t Length() const override;
6999
7000 void SetPCOffsetAt(intptr_t idx, intptr_t pc_offset);
7001 void SetCommentAt(intptr_t idx, const String& comment);
7002
7003 intptr_t PCOffsetAt(intptr_t idx) const override;
7004 const char* CommentAt(intptr_t idx) const override;
7005
7006 private:
7007 explicit Comments(const Array& comments);
7008
7009 // Layout of entries describing comments.
7010 enum {kPCOffsetEntry = 0, // PC offset to a comment as a Smi.
7011 kCommentEntry, // Comment text as a String.
7012 kNumberOfEntries};
7013
7014 const Array& comments_;
7015 String& string_;
7016
7017 friend class Code;
7018
7019 DISALLOW_COPY_AND_ASSIGN(Comments);
7020 };
7021
7022 const CodeComments& comments() const;
7023 void set_comments(const CodeComments& comments) const;
7024#endif // defined(INCLUDE_IL_PRINTER)
7025
7027#if defined(PRODUCT)
7028 UNREACHABLE();
7029 return nullptr;
7030#else
7031 return untag()->return_address_metadata();
7032#endif
7033 }
7034 // Sets |return_address_metadata|.
7035 void SetPrologueOffset(intptr_t offset) const;
7036 // Returns -1 if no prologue offset is available.
7037 intptr_t GetPrologueOffset() const;
7038
7039 ArrayPtr inlined_id_to_function() const;
7040 void set_inlined_id_to_function(const Array& value) const;
7041
7042 // Provides the call stack at the given pc offset, with the top-of-stack in
7043 // the last element and the root function (this) as the first element, along
7044 // with the corresponding source positions. Note the token position for each
7045 // function except the top-of-stack is the position of the call to the next
7046 // function. The stack will be empty if we lack the metadata to produce it,
7047 // which happens for stub code.
7048 // The pc offset is interpreted as an instruction address (as needed by the
7049 // disassembler or the top frame of a profiler sample).
7050 void GetInlinedFunctionsAtInstruction(
7051 intptr_t pc_offset,
7053 GrowableArray<TokenPosition>* token_positions) const;
7054 // Same as above, except the pc is interpreted as a return address (as needed
7055 // for a stack trace or the bottom frames of a profiler sample).
7057 intptr_t pc_offset,
7059 GrowableArray<TokenPosition>* token_positions) const {
7060 GetInlinedFunctionsAtInstruction(pc_offset - 1, functions, token_positions);
7061 }
7062
7063 NOT_IN_PRODUCT(void PrintJSONInlineIntervals(JSONObject* object) const);
7064 void DumpInlineIntervals() const;
7065 void DumpSourcePositions(bool relative_addresses = false) const;
7066
7067 LocalVarDescriptorsPtr var_descriptors() const {
7068#if defined(PRODUCT)
7069 UNREACHABLE();
7070 return nullptr;
7071#else
7072 return untag()->var_descriptors();
7073#endif
7074 }
7075 void set_var_descriptors(const LocalVarDescriptors& value) const {
7076#if defined(PRODUCT)
7077 UNREACHABLE();
7078#else
7079 ASSERT(value.IsOld());
7080 untag()->set_var_descriptors(value.ptr());
7081#endif
7082 }
7083
7084 // Will compute local var descriptors if necessary.
7085 LocalVarDescriptorsPtr GetLocalVarDescriptors() const;
7086
7087 ExceptionHandlersPtr exception_handlers() const {
7088 return untag()->exception_handlers();
7089 }
7090 void set_exception_handlers(const ExceptionHandlers& handlers) const {
7091 ASSERT(handlers.IsOld());
7092 untag()->set_exception_handlers(handlers.ptr());
7093 }
7094
7095 // WARNING: function() returns the owner which is not guaranteed to be
7096 // a Function. It is up to the caller to guarantee it isn't a stub, class,
7097 // or something else.
7098 // TODO(turnidge): Consider dropping this function and making
7099 // everybody use owner(). Currently this function is misused - even
7100 // while generating the snapshot.
7101 FunctionPtr function() const {
7102 ASSERT(IsFunctionCode());
7103 return Function::RawCast(owner());
7104 }
7105
7107 return WeakSerializationReference::Unwrap(untag()->owner());
7108 }
7109 void set_owner(const Object& owner) const;
7110
7111 classid_t OwnerClassId() const { return OwnerClassIdOf(ptr()); }
7112 static classid_t OwnerClassIdOf(CodePtr raw) {
7113 ObjectPtr owner = WeakSerializationReference::Unwrap(raw->untag()->owner());
7114 if (!owner->IsHeapObject()) {
7115 return RawSmiValue(static_cast<SmiPtr>(owner));
7116 }
7117 return owner->GetClassId();
7118 }
7119
7120 static intptr_t owner_offset() { return OFFSET_OF(UntaggedCode, owner_); }
7121
7122 // We would have a VisitPointers function here to traverse all the
7123 // embedded objects in the instructions using pointer_offsets.
7124
7125 static constexpr intptr_t kBytesPerElement =
7126 sizeof(reinterpret_cast<UntaggedCode*>(kOffsetOfPtr)->data()[0]);
7127 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
7128
7130 static intptr_t elements_start_offset() { return sizeof(UntaggedCode); }
7131 static constexpr intptr_t kElementSize = kBytesPerElement;
7132 };
7133
7134 static intptr_t InstanceSize() {
7135 ASSERT(sizeof(UntaggedCode) ==
7137 return 0;
7138 }
7139 static intptr_t InstanceSize(intptr_t len) {
7140 ASSERT(0 <= len && len <= kMaxElements);
7141 return RoundedAllocationSize(sizeof(UntaggedCode) +
7142 (len * kBytesPerElement));
7143 }
7144#if !defined(DART_PRECOMPILED_RUNTIME)
7145 // Finalizes the generated code, by generating various kinds of metadata (e.g.
7146 // stack maps, pc descriptors, ...) and attach them to a newly generated
7147 // [Code] object.
7148 //
7149 // If Code::PoolAttachment::kAttachPool is specified for [pool_attachment]
7150 // then a new [ObjectPool] will be attached to the code object as well.
7151 // Otherwise the caller is responsible for doing this via
7152 // `Object::set_object_pool()`.
7153 static CodePtr FinalizeCode(FlowGraphCompiler* compiler,
7154 compiler::Assembler* assembler,
7155 PoolAttachment pool_attachment,
7156 bool optimized,
7157 CodeStatistics* stats);
7158
7159 // Notifies all active [CodeObserver]s.
7160 static void NotifyCodeObservers(const Code& code, bool optimized);
7161 static void NotifyCodeObservers(const Function& function,
7162 const Code& code,
7163 bool optimized);
7164 static void NotifyCodeObservers(const char* name,
7165 const Code& code,
7166 bool optimized);
7167
7168 // Calls [FinalizeCode] and also notifies [CodeObserver]s.
7169 static CodePtr FinalizeCodeAndNotify(const Function& function,
7171 compiler::Assembler* assembler,
7172 PoolAttachment pool_attachment,
7173 bool optimized = false,
7174 CodeStatistics* stats = nullptr);
7175 static CodePtr FinalizeCodeAndNotify(const char* name,
7177 compiler::Assembler* assembler,
7178 PoolAttachment pool_attachment,
7179 bool optimized = false,
7180 CodeStatistics* stats = nullptr);
7181
7182#endif
7183 static CodePtr FindCode(uword pc, int64_t timestamp);
7184 static CodePtr FindCodeUnsafe(uword pc);
7185
7186 int32_t GetPointerOffsetAt(int index) const {
7187 NoSafepointScope no_safepoint;
7188 return *PointerOffsetAddrAt(index);
7189 }
7190 TokenPosition GetTokenIndexOfPC(uword pc) const;
7191
7192 // Find pc, return 0 if not found.
7193 uword GetPcForDeoptId(intptr_t deopt_id,
7194 UntaggedPcDescriptors::Kind kind) const;
7195 intptr_t GetDeoptIdForOsr(uword pc) const;
7196
7197 uint32_t Hash() const;
7198 const char* Name() const;
7199 const char* QualifiedName(const NameFormattingParams& params) const;
7200
7201 int64_t compile_timestamp() const {
7202#if defined(PRODUCT)
7203 return 0;
7204#else
7205 return untag()->compile_timestamp_;
7206#endif
7207 }
7208
7209 bool IsStubCode() const;
7210 bool IsAllocationStubCode() const;
7211 bool IsTypeTestStubCode() const;
7212 bool IsFunctionCode() const;
7213
7214 // Returns true if this Code object represents
7215 // Dart function code without any additional information.
7216 bool IsUnknownDartCode() const { return IsUnknownDartCode(ptr()); }
7217 static bool IsUnknownDartCode(CodePtr code);
7218
7219 void DisableDartCode() const;
7220
7221 void DisableStubCode(bool is_cls_parameterized) const;
7222
7223 void Enable() const {
7224 if (!IsDisabled()) return;
7225 ResetActiveInstructions();
7226 }
7227
7228 bool IsDisabled() const { return IsDisabled(ptr()); }
7229 static bool IsDisabled(CodePtr code) {
7230#if defined(DART_PRECOMPILED_RUNTIME)
7231 UNREACHABLE();
7232 return false;
7233#else
7234 return code->untag()->instructions() !=
7235 code->untag()->active_instructions();
7236#endif
7237 }
7238
7239 void set_object_pool(ObjectPoolPtr object_pool) const {
7240 untag()->set_object_pool(object_pool);
7241 }
7242
7243 private:
7244 void set_state_bits(intptr_t bits) const;
7245
7246 friend class UntaggedObject; // For UntaggedObject::SizeFromClass().
7247 friend class UntaggedCode;
7248 friend struct RelocatorTestHelper;
7249
7250 enum {
7251 kOptimizedBit = 0,
7252 kForceOptimizedBit = 1,
7253 kAliveBit = 2,
7254 kDiscardedBit = 3,
7255 kPtrOffBit = 4,
7256 kPtrOffSize = kBitsPerInt32 - kPtrOffBit,
7257 };
7258
7259 class OptimizedBit : public BitField<int32_t, bool, kOptimizedBit, 1> {};
7260
7261 // Force-optimized is true if the Code was generated for a function with
7262 // Function::ForceOptimize().
7263 class ForceOptimizedBit
7264 : public BitField<int32_t, bool, kForceOptimizedBit, 1> {};
7265
7266 class AliveBit : public BitField<int32_t, bool, kAliveBit, 1> {};
7267
7268 // Set by precompiler if this Code object doesn't contain
7269 // useful information besides instructions and compressed stack map.
7270 // Such objects are serialized in a shorter form and replaced with
7271 // StubCode::UnknownDartCode() during snapshot deserialization.
7272 class DiscardedBit : public BitField<int32_t, bool, kDiscardedBit, 1> {};
7273
7274 class PtrOffBits
7275 : public BitField<int32_t, intptr_t, kPtrOffBit, kPtrOffSize> {};
7276
7277 static constexpr intptr_t kEntrySize = sizeof(int32_t); // NOLINT
7278
7279 void set_compile_timestamp(int64_t timestamp) const {
7280#if defined(PRODUCT)
7281 UNREACHABLE();
7282#else
7283 StoreNonPointer(&untag()->compile_timestamp_, timestamp);
7284#endif
7285 }
7286
7287 // Initializes the cached entrypoint addresses in [code] as calculated
7288 // from [instructions] and [unchecked_offset].
7289 static void InitializeCachedEntryPointsFrom(CodePtr code,
7290 InstructionsPtr instructions,
7291 uint32_t unchecked_offset);
7292
7293 // Sets [active_instructions_] to [instructions] and updates the cached
7294 // entry point addresses.
7295 void SetActiveInstructions(const Instructions& instructions,
7296 uint32_t unchecked_offset) const;
7297 void SetActiveInstructionsSafe(const Instructions& instructions,
7298 uint32_t unchecked_offset) const;
7299
7300 // Resets [active_instructions_] to its original value of [instructions_] and
7301 // updates the cached entry point addresses to match.
7302 void ResetActiveInstructions() const;
7303
7304 void set_instructions(const Instructions& instructions) const {
7305 ASSERT(Thread::Current()->IsDartMutatorThread() || !is_alive());
7306 untag()->set_instructions(instructions.ptr());
7307 }
7308#if !defined(DART_PRECOMPILED_RUNTIME)
7309 void set_unchecked_offset(uword offset) const {
7310 StoreNonPointer(&untag()->unchecked_offset_, offset);
7311 }
7312#endif
7313
7314 // Returns the unchecked entry point offset for [instructions_].
7315 uint32_t UncheckedEntryPointOffset() const {
7316 return UncheckedEntryPointOffsetOf(ptr());
7317 }
7318 static uint32_t UncheckedEntryPointOffsetOf(CodePtr code) {
7319#if defined(DART_PRECOMPILED_RUNTIME)
7320 UNREACHABLE();
7321#else
7322 return code->untag()->unchecked_offset_;
7323#endif
7324 }
7325
7326 void set_pointer_offsets_length(intptr_t value) {
7327 // The number of fixups is limited to 1-billion.
7328 ASSERT(Utils::IsUint(30, value));
7329 set_state_bits(PtrOffBits::update(value, untag()->state_bits_));
7330 }
7331 int32_t* PointerOffsetAddrAt(int index) const {
7332 ASSERT(index >= 0);
7333 ASSERT(index < pointer_offsets_length());
7334 // TODO(iposva): Unit test is missing for this functionality.
7335 return &UnsafeMutableNonPointer(untag()->data())[index];
7336 }
7337 void SetPointerOffsetAt(int index, int32_t offset_in_instructions) {
7338 NoSafepointScope no_safepoint;
7339 *PointerOffsetAddrAt(index) = offset_in_instructions;
7340 }
7341
7342 intptr_t BinarySearchInSCallTable(uword pc) const;
7343 static CodePtr LookupCodeInIsolateGroup(IsolateGroup* isolate_group,
7344 uword pc);
7345
7346 // New is a private method as RawInstruction and RawCode objects should
7347 // only be created using the Code::FinalizeCode method. This method creates
7348 // the RawInstruction and RawCode objects, sets up the pointer offsets
7349 // and links the two in a GC safe manner.
7350 static CodePtr New(intptr_t pointer_offsets_length);
7351
7353 friend class Class;
7354 friend class CodeTestHelper;
7355 friend class StubCode; // for set_object_pool
7356 friend class Precompiler; // for set_object_pool
7360 friend class Deserializer; // for InitializeCachedEntryPointsFrom
7361 friend class StubCode; // for set_object_pool
7362 friend class MegamorphicCacheTable; // for set_object_pool
7363 friend class CodePatcher; // for set_instructions
7364 friend class ProgramVisitor; // for set_instructions
7365 // So that the UntaggedFunction pointer visitor can determine whether code the
7366 // function points to is optimized.
7367 friend class UntaggedFunction;
7368 friend class CallSiteResetter;
7369 friend class CodeKeyValueTrait; // for UncheckedEntryPointOffset
7370 friend class InstanceCall; // for StorePointerUnaligned
7371 friend class StaticCall; // for StorePointerUnaligned
7372 friend void DumpStackFrame(intptr_t frame_index, uword pc, uword fp);
7373};
7374
7375class Context : public Object {
7376 public:
7377 ContextPtr parent() const { return untag()->parent(); }
7378 void set_parent(const Context& parent) const {
7379 untag()->set_parent(parent.ptr());
7380 }
7381 static intptr_t parent_offset() {
7382 return OFFSET_OF(UntaggedContext, parent_);
7383 }
7384
7385 intptr_t num_variables() const { return untag()->num_variables_; }
7386 static intptr_t num_variables_offset() {
7387 return OFFSET_OF(UntaggedContext, num_variables_);
7388 }
7389 static intptr_t NumVariables(const ContextPtr context) {
7390 return context->untag()->num_variables_;
7391 }
7392
7393 ObjectPtr At(intptr_t context_index) const {
7394 return untag()->element(context_index);
7395 }
7396 inline void SetAt(intptr_t context_index, const Object& value) const;
7397
7398 intptr_t GetLevel() const;
7399
7400 void Dump(int indent = 0) const;
7401
7402 static constexpr intptr_t kBytesPerElement = kCompressedWordSize;
7403 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
7404
7406 static intptr_t elements_start_offset() { return sizeof(UntaggedContext); }
7407 static constexpr intptr_t kElementSize = kBytesPerElement;
7408 };
7409
7410 static intptr_t variable_offset(intptr_t context_index) {
7412 (kBytesPerElement * context_index);
7413 }
7414
7415 static bool IsValidLength(intptr_t len) {
7416 return 0 <= len && len <= compiler::target::Context::kMaxElements;
7417 }
7418
7419 static intptr_t InstanceSize() {
7420 ASSERT(sizeof(UntaggedContext) ==
7422 return 0;
7423 }
7424
7425 static intptr_t InstanceSize(intptr_t len) {
7426 ASSERT(IsValidLength(len));
7427 return RoundedAllocationSize(sizeof(UntaggedContext) +
7428 (len * kBytesPerElement));
7429 }
7430
7431 static ContextPtr New(intptr_t num_variables, Heap::Space space = Heap::kNew);
7432
7433 private:
7434 void set_num_variables(intptr_t num_variables) const {
7435 StoreNonPointer(&untag()->num_variables_, num_variables);
7436 }
7437
7439 friend class Class;
7440 friend class Object;
7441};
7442
7443// The ContextScope class makes it possible to delay the compilation of a local
7444// function until it is invoked. A ContextScope instance collects the local
7445// variables that are referenced by the local function to be compiled and that
7446// belong to the outer scopes, that is, to the local scopes of (possibly nested)
7447// functions enclosing the local function. Each captured variable is represented
7448// by its token position in the source, its name, its type, its allocation index
7449// in the context, and its context level. The function nesting level and loop
7450// nesting level are not preserved, since they are only used until the context
7451// level is assigned. In addition the ContextScope has a field 'is_implicit'
7452// which is true if the ContextScope was created for an implicit closure.
7453class ContextScope : public Object {
7454 public:
7455 intptr_t num_variables() const { return untag()->num_variables_; }
7456
7457 TokenPosition TokenIndexAt(intptr_t scope_index) const;
7458 void SetTokenIndexAt(intptr_t scope_index, TokenPosition token_pos) const;
7459
7460 TokenPosition DeclarationTokenIndexAt(intptr_t scope_index) const;
7461 void SetDeclarationTokenIndexAt(intptr_t scope_index,
7462 TokenPosition declaration_token_pos) const;
7463
7464 StringPtr NameAt(intptr_t scope_index) const;
7465 void SetNameAt(intptr_t scope_index, const String& name) const;
7466
7467 void ClearFlagsAt(intptr_t scope_index) const;
7468
7469 intptr_t LateInitOffsetAt(intptr_t scope_index) const;
7470 void SetLateInitOffsetAt(intptr_t scope_index,
7471 intptr_t late_init_offset) const;
7472
7473#define DECLARE_FLAG_ACCESSORS(Name) \
7474 bool Is##Name##At(intptr_t scope_index) const; \
7475 void SetIs##Name##At(intptr_t scope_index, bool value) const;
7476
7478#undef DECLARE_FLAG_ACCESSORS
7479
7480 AbstractTypePtr TypeAt(intptr_t scope_index) const;
7481 void SetTypeAt(intptr_t scope_index, const AbstractType& type) const;
7482
7483 intptr_t CidAt(intptr_t scope_index) const;
7484 void SetCidAt(intptr_t scope_index, intptr_t cid) const;
7485
7486 intptr_t ContextIndexAt(intptr_t scope_index) const;
7487 void SetContextIndexAt(intptr_t scope_index, intptr_t context_index) const;
7488
7489 intptr_t ContextLevelAt(intptr_t scope_index) const;
7490 void SetContextLevelAt(intptr_t scope_index, intptr_t context_level) const;
7491
7492 intptr_t KernelOffsetAt(intptr_t scope_index) const;
7493 void SetKernelOffsetAt(intptr_t scope_index, intptr_t kernel_offset) const;
7494
7495 static constexpr intptr_t kBytesPerElement =
7496 sizeof(UntaggedContextScope::VariableDesc);
7497 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
7498
7500 static intptr_t elements_start_offset() {
7501 return sizeof(UntaggedContextScope);
7502 }
7503 static constexpr intptr_t kElementSize = kBytesPerElement;
7504 };
7505
7506 static intptr_t InstanceSize() {
7507 ASSERT(sizeof(UntaggedContextScope) ==
7509 return 0;
7510 }
7511
7512 static intptr_t InstanceSize(intptr_t len) {
7513 ASSERT(0 <= len && len <= kMaxElements);
7514 return RoundedAllocationSize(sizeof(UntaggedContextScope) +
7515 (len * kBytesPerElement));
7516 }
7517
7518 static ContextScopePtr New(intptr_t num_variables, bool is_implicit);
7519
7520 private:
7521 void set_num_variables(intptr_t num_variables) const {
7522 StoreNonPointer(&untag()->num_variables_, num_variables);
7523 }
7524
7525 void set_is_implicit(bool is_implicit) const {
7526 StoreNonPointer(&untag()->is_implicit_, is_implicit);
7527 }
7528
7529 const UntaggedContextScope::VariableDesc* VariableDescAddr(
7530 intptr_t index) const {
7531 ASSERT((index >= 0) && (index < num_variables()));
7532 return untag()->VariableDescAddr(index);
7533 }
7534
7535 bool GetFlagAt(intptr_t scope_index, intptr_t bit_index) const;
7536 void SetFlagAt(intptr_t scope_index, intptr_t bit_index, bool value) const;
7537
7538 FINAL_HEAP_OBJECT_IMPLEMENTATION(ContextScope, Object);
7539 friend class Class;
7540 friend class Object;
7541};
7542
7543// Class of special sentinel values:
7544// - Object::sentinel() is a value that cannot be produced by Dart code.
7545// It can be used to mark special values, for example to distinguish
7546// "uninitialized" fields.
7547// - Object::transition_sentinel() is a value marking that we are transitioning
7548// from sentinel, e.g., computing a field value. Used to detect circular
7549// initialization of static fields.
7550// - Object::unknown_constant() and Object::non_constant() are optimizing
7551// compiler's constant propagation constants.
7552// - Object::optimized_out() result from deopt environment pruning or failure
7553// to capture variables in a closure's context
7554class Sentinel : public Object {
7555 public:
7556 static intptr_t InstanceSize() {
7557 return RoundedAllocationSize(sizeof(UntaggedSentinel));
7558 }
7559
7560 static SentinelPtr New();
7561
7562 private:
7564 friend class Class;
7565 friend class Object;
7566};
7567
7569 public:
7570 static constexpr intptr_t kInitialCapacity = 16;
7571 static constexpr intptr_t kSpreadFactor = 7;
7572 static constexpr double kLoadFactor = 0.50;
7573
7579
7580 ArrayPtr buckets() const;
7581 void set_buckets(const Array& buckets) const;
7582
7583 intptr_t mask() const;
7584 void set_mask(intptr_t mask) const;
7585
7586 intptr_t filled_entry_count() const;
7587 void set_filled_entry_count(intptr_t num) const;
7588
7589 static intptr_t buckets_offset() {
7590 return OFFSET_OF(UntaggedMegamorphicCache, buckets_);
7591 }
7592 static intptr_t mask_offset() {
7593 return OFFSET_OF(UntaggedMegamorphicCache, mask_);
7594 }
7596 return OFFSET_OF(UntaggedMegamorphicCache, args_descriptor_);
7597 }
7598
7599 static MegamorphicCachePtr New(const String& target_name,
7601
7602 void EnsureContains(const Smi& class_id, const Object& target) const;
7603 ObjectPtr Lookup(const Smi& class_id) const;
7604
7605 static intptr_t InstanceSize() {
7607 }
7608
7609 private:
7610 friend class Class;
7612 friend class ProgramVisitor;
7613
7614 static MegamorphicCachePtr New();
7615
7616 // The caller must hold IsolateGroup::type_feedback_mutex().
7617 void InsertLocked(const Smi& class_id, const Object& target) const;
7618 void EnsureCapacityLocked() const;
7619 ObjectPtr LookupLocked(const Smi& class_id) const;
7620
7621 void InsertEntryLocked(const Smi& class_id, const Object& target) const;
7622
7623 static inline void SetEntry(const Array& array,
7624 intptr_t index,
7625 const Smi& class_id,
7626 const Object& target);
7627
7628 static inline ObjectPtr GetClassId(const Array& array, intptr_t index);
7629 static inline ObjectPtr GetTargetFunction(const Array& array, intptr_t index);
7630
7632};
7633
7634class SubtypeTestCache : public Object {
7635 public:
7636 // The contents of the backing array storage is a number of entry tuples.
7637 // Any entry that is unoccupied has the null value as its first component.
7638 //
7639 // If the cache is linear, the entries can be accessed in a linear fashion:
7640 // all occupied entries come first, followed by at least one unoccupied
7641 // entry to mark the end of the cache. Guaranteeing at least one unoccupied
7642 // entry avoids the need for a length check when iterating over the contents
7643 // of the linear cache in stubs.
7644 //
7645 // If the cache is hash-based, the array is instead treated as a hash table
7646 // probed by using a hash value derived from the inputs.
7647
7648 // The tuple of values stored in a given entry.
7649 //
7650 // Note that occupied entry contents are never modified. That means reading a
7651 // non-null instance cid or signature means the rest of the entry can be
7652 // loaded without worrying about concurrent modification. Thus, we always set
7653 // the instance cid or signature last when making an occupied entry.
7654 //
7655 // Also note that each STC, when created, has a set number of used inputs.
7656 // The value of any unused input is unspecified, so for example, if the
7657 // STC only uses 3 inputs, then no assumptions can be made about the value
7658 // stored in the instantiator type arguments slot.
7659 enum Entries {
7660 kInstanceCidOrSignature = 0,
7661 kInstanceTypeArguments = 1,
7662 kInstantiatorTypeArguments = 2,
7663 kFunctionTypeArguments = 3,
7664 kInstanceParentFunctionTypeArguments = 4,
7665 kInstanceDelayedFunctionTypeArguments = 5,
7666 kDestinationType = 6,
7667 kTestResult = 7,
7668 kTestEntryLength = 8,
7669 };
7670
7671 // Assumes only one non-input entry in the array, kTestResult.
7672 static_assert(kInstanceCidOrSignature == 0 &&
7673 kDestinationType + 1 == kTestResult &&
7674 kTestResult + 1 == kTestEntryLength,
7675 "Need to adjust number of max inputs");
7676 static constexpr intptr_t kMaxInputs = kTestResult;
7677
7678 // Returns the number of occupied entries stored in the cache.
7679 intptr_t NumberOfChecks() const;
7680
7681 // Retrieves the number of entries (occupied or unoccupied) in the cache.
7682 intptr_t NumEntries() const;
7683
7684 // Adds a check, returning the index of the new entry in the cache.
7685 intptr_t AddCheck(
7686 const Object& instance_class_id_or_signature,
7687 const AbstractType& destination_type,
7688 const TypeArguments& instance_type_arguments,
7689 const TypeArguments& instantiator_type_arguments,
7690 const TypeArguments& function_type_arguments,
7691 const TypeArguments& instance_parent_function_type_arguments,
7692 const TypeArguments& instance_delayed_type_arguments,
7693 const Bool& test_result) const;
7694 void GetCheck(intptr_t ix,
7695 Object* instance_class_id_or_signature,
7696 AbstractType* destination_type,
7697 TypeArguments* instance_type_arguments,
7698 TypeArguments* instantiator_type_arguments,
7699 TypeArguments* function_type_arguments,
7700 TypeArguments* instance_parent_function_type_arguments,
7701 TypeArguments* instance_delayed_type_arguments,
7702 Bool* test_result) const;
7703
7704 // Like GetCheck(), but does not require the subtype test cache mutex and so
7705 // may see an outdated view of the cache.
7706 void GetCurrentCheck(intptr_t ix,
7707 Object* instance_class_id_or_signature,
7708 AbstractType* destination_type,
7709 TypeArguments* instance_type_arguments,
7710 TypeArguments* instantiator_type_arguments,
7711 TypeArguments* function_type_arguments,
7712 TypeArguments* instance_parent_function_type_arguments,
7713 TypeArguments* instance_delayed_type_arguments,
7714 Bool* test_result) const;
7715
7716 // Like GetCheck(), but returns the contents of the first occupied entry
7717 // at or after the initial contents of [ix]. Returns whether an occupied entry
7718 // was found, and if an occupied entry was found, [ix] is updated to the entry
7719 // index following the occupied entry.
7720 bool GetNextCheck(intptr_t* ix,
7721 Object* instance_class_id_or_signature,
7722 AbstractType* destination_type,
7723 TypeArguments* instance_type_arguments,
7724 TypeArguments* instantiator_type_arguments,
7725 TypeArguments* function_type_arguments,
7726 TypeArguments* instance_parent_function_type_arguments,
7727 TypeArguments* instance_delayed_type_arguments,
7728 Bool* test_result) const;
7729
7730 // Returns whether all the elements of an existing cache entry, excluding
7731 // the result, match the non-pointer arguments. The pointer arguments are
7732 // out parameters as follows:
7733 //
7734 // If [index] is not nullptr, then it is set to the matching entry's index.
7735 // If [result] is not nullptr, then it is set to the matching entry's result.
7736 //
7737 // If called without the STC mutex lock, may return outdated information:
7738 // * May return a false negative if the entry was added concurrently.
7739 // * The [index] field may be invalid for the STC if the backing array is
7740 // grown concurrently and the new backing array is hash-based.
7741 bool HasCheck(const Object& instance_class_id_or_signature,
7742 const AbstractType& destination_type,
7743 const TypeArguments& instance_type_arguments,
7744 const TypeArguments& instantiator_type_arguments,
7745 const TypeArguments& function_type_arguments,
7746 const TypeArguments& instance_parent_function_type_arguments,
7747 const TypeArguments& instance_delayed_type_arguments,
7748 intptr_t* index,
7749 Bool* result) const;
7750
7751 // Writes the cache entry at index [index] to the given text buffer.
7752 //
7753 // The output is comma separated on a single line if [line_prefix] is nullptr,
7754 // otherwise line breaks followed by [line_prefix] is used as a separator.
7755 void WriteEntryToBuffer(Zone* zone,
7757 intptr_t index,
7758 const char* line_prefix = nullptr) const;
7759
7760 // Writes the contents of this SubtypeTestCache to the given text buffer.
7761 void WriteToBuffer(Zone* zone,
7763 const char* line_prefix = nullptr) const;
7764
7765 void Reset() const;
7766
7767 // Tests that [other] contains the same entries in the same order.
7768 bool Equals(const SubtypeTestCache& other) const;
7769
7770 // Returns whether the cache backed by the given storage is hash-based.
7771 bool IsHash() const;
7772
7773 // Creates a separate copy of the current STC contents.
7774 SubtypeTestCachePtr Copy(Thread* thread) const;
7775
7776 static SubtypeTestCachePtr New(intptr_t num_inputs);
7777
7778 static intptr_t InstanceSize() {
7779 return RoundedAllocationSize(sizeof(UntaggedSubtypeTestCache));
7780 }
7781
7782 static intptr_t cache_offset() {
7783 return OFFSET_OF(UntaggedSubtypeTestCache, cache_);
7784 }
7785 ArrayPtr cache() const;
7786
7787 static intptr_t num_inputs_offset() {
7788 return OFFSET_OF(UntaggedSubtypeTestCache, num_inputs_);
7789 }
7790 intptr_t num_inputs() const { return untag()->num_inputs_; }
7791
7792 intptr_t num_occupied() const { return untag()->num_occupied_; }
7793
7794 // The maximum number of occupied entries for a linear subtype test cache
7795 // before swapping to a hash table-based cache. Exposed publicly for tests.
7796#if defined(TARGET_ARCH_IA32)
7797 // We don't generate hash cache probing in the stub on IA32, so larger caches
7798 // force runtime checks.
7799 static constexpr intptr_t kMaxLinearCacheEntries = 100;
7800#else
7801 static constexpr intptr_t kMaxLinearCacheEntries = 30;
7802#endif
7803
7804 // Whether the entry at the given index in the cache is occupied. Exposed
7805 // publicly for tests.
7806 bool IsOccupied(intptr_t index) const;
7807
7808 // Returns the number of inputs needed to cache entries for the given type.
7809 static intptr_t UsedInputsForType(const AbstractType& type);
7810
7811 // Given a minimum entry count, calculates an entry count that won't force
7812 // additional allocation but minimizes the number of unoccupied entries.
7813 // Used to calculate an appropriate value for FLAG_max_subtype_cache_entries.
7814 static constexpr intptr_t MaxEntriesForCacheAllocatedFor(intptr_t count) {
7815 // If the cache would be linear, just return the count unchanged.
7816 if (count <= kMaxLinearCacheEntries) return count;
7817 intptr_t allocated_entries = Utils::RoundUpToPowerOfTwo(count);
7818 if (LoadFactor(count, allocated_entries) >= kMaxLoadFactor) {
7819 allocated_entries *= 2;
7820 }
7821 const intptr_t max_entries =
7822 static_cast<intptr_t>(kMaxLoadFactor * allocated_entries);
7823 assert(LoadFactor(max_entries, allocated_entries) < kMaxLoadFactor);
7824 assert(max_entries >= count);
7825 return max_entries;
7826 }
7827
7828 private:
7829 static constexpr double LoadFactor(intptr_t occupied, intptr_t capacity) {
7830 return occupied / static_cast<double>(capacity);
7831 }
7832
7833 // Retrieves the number of entries (occupied or unoccupied) in a cache
7834 // backed by the given array.
7835 static intptr_t NumEntries(const Array& array);
7836
7837 // Returns whether the cache backed by the given storage is linear.
7838 static bool IsLinear(const Array& array) { return !IsHash(array); }
7839
7840 // Returns whether the cache backed by the given storage is hash-based.
7841 static bool IsHash(const Array& array);
7842
7843 struct KeyLocation {
7844 // The entry index if [present] is true, otherwise where the entry would
7845 // be located if added afterwards without any intermediate additions.
7846 intptr_t entry;
7847 bool present; // Whether an entry already exists in the cache.
7848 };
7849
7850 // If a cache entry in the given array contains the given inputs, returns a
7851 // KeyLocation with the index of the entry and true. Otherwise, returns a
7852 // KeyLocation with the index that would be used if the instantiation for the
7853 // given type arguments is added and false.
7854 //
7855 // If called without the STC mutex lock, may return outdated information:
7856 // * The [present] field may be a false negative if the entry was added
7857 // concurrently.
7858 static KeyLocation FindKeyOrUnused(
7859 const Array& array,
7860 intptr_t num_inputs,
7861 const Object& instance_class_id_or_signature,
7862 const AbstractType& destination_type,
7863 const TypeArguments& instance_type_arguments,
7864 const TypeArguments& instantiator_type_arguments,
7865 const TypeArguments& function_type_arguments,
7866 const TypeArguments& instance_parent_function_type_arguments,
7867 const TypeArguments& instance_delayed_type_arguments);
7868
7869 // If the given array can contain the requested number of entries, returns
7870 // the same array and sets [was_grown] to false.
7871 //
7872 // If the given array cannot contain the requested number of entries,
7873 // returns a new array that can and which contains all the entries of the
7874 // given array and sets [was_grown] to true.
7875 ArrayPtr EnsureCapacity(Zone* zone,
7876 const Array& array,
7877 intptr_t new_capacity,
7878 bool* was_grown) const;
7879
7880 public: // Used in the StubCodeCompiler.
7881 // The maximum size of the array backing a linear cache. All hash based
7882 // caches are guaranteed to have sizes larger than this.
7883 static constexpr intptr_t kMaxLinearCacheSize =
7884 (kMaxLinearCacheEntries + 1) * kTestEntryLength;
7885
7886 private:
7887 // The initial number of entries used when converting from a linear to
7888 // a hash-based cache.
7889 static constexpr intptr_t kNumInitialHashCacheEntries =
7890 Utils::RoundUpToPowerOfTwo(2 * kMaxLinearCacheEntries);
7891 static_assert(Utils::IsPowerOfTwo(kNumInitialHashCacheEntries),
7892 "number of hash-based cache entries must be a power of two");
7893
7894 // The max load factor allowed in hash-based caches.
7895 static constexpr double kMaxLoadFactor = 0.71;
7896
7897 void set_cache(const Array& value) const;
7898 void set_num_occupied(intptr_t value) const;
7899
7900 // Like GetCurrentCheck, but takes the backing storage array.
7901 static void GetCheckFromArray(
7902 const Array& array,
7903 intptr_t num_inputs,
7904 intptr_t ix,
7905 Object* instance_class_id_or_signature,
7906 AbstractType* destination_type,
7907 TypeArguments* instance_type_arguments,
7908 TypeArguments* instantiator_type_arguments,
7909 TypeArguments* function_type_arguments,
7910 TypeArguments* instance_parent_function_type_arguments,
7911 TypeArguments* instance_delayed_type_arguments,
7912 Bool* test_result);
7913
7914 // Like WriteEntryToBuffer(), but does not require the subtype test cache
7915 // mutex and so may see an incorrect view of the cache if there are concurrent
7916 // modifications.
7917 void WriteCurrentEntryToBuffer(Zone* zone,
7919 intptr_t index,
7920 const char* line_prefix = nullptr) const;
7921
7922 // Like WriteToBuffer(), but does not require the subtype test cache mutex and
7923 // so may see an incorrect view of the cache if there are concurrent
7924 // modifications.
7925 void WriteToBufferUnlocked(Zone* zone,
7927 const char* line_prefix = nullptr) const;
7928
7930 friend class Class;
7931 friend class FieldInvalidator;
7934};
7935
7936class LoadingUnit : public Object {
7937 public:
7938 static constexpr intptr_t kIllegalId = 0;
7939 COMPILE_ASSERT(kIllegalId == WeakTable::kNoValue);
7940 static constexpr intptr_t kRootId = 1;
7941
7942 static LoadingUnitPtr New(intptr_t id, const LoadingUnit& parent);
7943
7944 static intptr_t InstanceSize() {
7945 return RoundedAllocationSize(sizeof(UntaggedLoadingUnit));
7946 }
7947
7948 static intptr_t LoadingUnitOf(const Function& function);
7949 static intptr_t LoadingUnitOf(const Code& code);
7950
7951 LoadingUnitPtr parent() const { return untag()->parent(); }
7952
7953 ArrayPtr base_objects() const { return untag()->base_objects(); }
7954 void set_base_objects(const Array& value) const;
7955
7956 intptr_t id() const {
7957 return untag()->packed_fields_.Read<UntaggedLoadingUnit::IdBits>();
7958 }
7959
7960 // True once the VM deserializes this unit's snapshot.
7961 bool loaded() const {
7962 return untag()->packed_fields_.Read<UntaggedLoadingUnit::LoadStateBits>() ==
7963 UntaggedLoadingUnit::kLoaded;
7964 }
7965 // value is whether the load succeeded or not.
7966 void set_loaded(bool value) const {
7967 ASSERT(load_outstanding());
7968 auto const expected =
7969 value ? UntaggedLoadingUnit::kLoaded : UntaggedLoadingUnit::kNotLoaded;
7970 auto const got = untag()
7971 ->packed_fields_
7972 .UpdateConditional<UntaggedLoadingUnit::LoadStateBits>(
7973 expected, UntaggedLoadingUnit::kLoadOutstanding);
7974 // Check that we're in the expected state afterwards.
7975 ASSERT_EQUAL(got, expected);
7976 }
7977
7978 // True once the VM invokes the embedder's deferred load callback until the
7979 // embedder calls Dart_DeferredLoadComplete[Error].
7980 bool load_outstanding() const {
7981 return untag()->packed_fields_.Read<UntaggedLoadingUnit::LoadStateBits>() ==
7982 UntaggedLoadingUnit::kLoadOutstanding;
7983 }
7985 auto const previous = UntaggedLoadingUnit::kNotLoaded;
7987 untag()->packed_fields_.Read<UntaggedLoadingUnit::LoadStateBits>(),
7988 previous);
7989 auto const expected = UntaggedLoadingUnit::kLoadOutstanding;
7990 auto const got = untag()
7991 ->packed_fields_
7992 .UpdateConditional<UntaggedLoadingUnit::LoadStateBits>(
7993 expected, previous);
7994 // Check that we're in the expected state afterwards.
7995 ASSERT_EQUAL(got, expected);
7996 }
7997
7998 const uint8_t* instructions_image() const {
7999 // The instructions image should only be accessed if the load succeeded.
8000 ASSERT(loaded());
8001 return untag()->instructions_image_;
8002 }
8003 void set_instructions_image(const uint8_t* value) const {
8004 ASSERT(load_outstanding());
8005 StoreNonPointer(&untag()->instructions_image_, value);
8006 }
8008 return loaded() && instructions_image() != nullptr;
8009 }
8010
8011 ObjectPtr IssueLoad() const;
8012 ObjectPtr CompleteLoad(const String& error_message,
8013 bool transient_error) const;
8014
8015 private:
8017 friend class Class;
8018};
8019
8020class Error : public Object {
8021 public:
8022 virtual const char* ToErrorCString() const;
8023
8024 private:
8026};
8027
8028class ApiError : public Error {
8029 public:
8030 StringPtr message() const { return untag()->message(); }
8031
8032 static intptr_t InstanceSize() {
8033 return RoundedAllocationSize(sizeof(UntaggedApiError));
8034 }
8035
8036 static ApiErrorPtr New(const String& message, Heap::Space space = Heap::kNew);
8037
8038 virtual const char* ToErrorCString() const;
8039
8040 private:
8041 void set_message(const String& message) const;
8042
8043 static ApiErrorPtr New();
8044
8046 friend class Class;
8047};
8048
8049class LanguageError : public Error {
8050 public:
8052 return static_cast<Report::Kind>(untag()->kind_);
8053 }
8054
8055 // Build, cache, and return formatted message.
8056 StringPtr FormatMessage() const;
8057
8058 static intptr_t InstanceSize() {
8059 return RoundedAllocationSize(sizeof(UntaggedLanguageError));
8060 }
8061
8062 // A null script means no source and a negative token_pos means no position.
8063 static LanguageErrorPtr NewFormatted(const Error& prev_error,
8064 const Script& script,
8065 TokenPosition token_pos,
8066 bool report_after_token,
8067 Report::Kind kind,
8068 Heap::Space space,
8069 const char* format,
8070 ...) PRINTF_ATTRIBUTE(7, 8);
8071
8072 static LanguageErrorPtr NewFormattedV(const Error& prev_error,
8073 const Script& script,
8074 TokenPosition token_pos,
8075 bool report_after_token,
8076 Report::Kind kind,
8077 Heap::Space space,
8078 const char* format,
8079 va_list args);
8080
8081 static LanguageErrorPtr New(const String& formatted_message,
8082 Report::Kind kind = Report::kError,
8083 Heap::Space space = Heap::kNew);
8084
8085 virtual const char* ToErrorCString() const;
8086
8087 TokenPosition token_pos() const { return untag()->token_pos_; }
8088
8089 private:
8090 ErrorPtr previous_error() const { return untag()->previous_error(); }
8091 void set_previous_error(const Error& value) const;
8092
8093 ScriptPtr script() const { return untag()->script(); }
8094 void set_script(const Script& value) const;
8095
8096 void set_token_pos(TokenPosition value) const;
8097
8098 bool report_after_token() const { return untag()->report_after_token_; }
8099 void set_report_after_token(bool value) const;
8100
8101 void set_kind(uint8_t value) const;
8102
8103 StringPtr message() const { return untag()->message(); }
8104 void set_message(const String& value) const;
8105
8106 StringPtr formatted_message() const { return untag()->formatted_message(); }
8107 void set_formatted_message(const String& value) const;
8108
8109 static LanguageErrorPtr New();
8110
8111 FINAL_HEAP_OBJECT_IMPLEMENTATION(LanguageError, Error);
8112 friend class Class;
8113};
8114
8116 public:
8117 InstancePtr exception() const { return untag()->exception(); }
8118 static intptr_t exception_offset() {
8119 return OFFSET_OF(UntaggedUnhandledException, exception_);
8120 }
8121
8122 InstancePtr stacktrace() const { return untag()->stacktrace(); }
8123 static intptr_t stacktrace_offset() {
8124 return OFFSET_OF(UntaggedUnhandledException, stacktrace_);
8125 }
8126
8127 static intptr_t InstanceSize() {
8128 return RoundedAllocationSize(sizeof(UntaggedUnhandledException));
8129 }
8130
8131 static UnhandledExceptionPtr New(const Instance& exception,
8132 const Instance& stacktrace,
8133 Heap::Space space = Heap::kNew);
8134
8135 virtual const char* ToErrorCString() const;
8136
8137 private:
8138 static UnhandledExceptionPtr New(Heap::Space space = Heap::kNew);
8139
8140 void set_exception(const Instance& exception) const;
8141 void set_stacktrace(const Instance& stacktrace) const;
8142
8144 friend class Class;
8145 friend class ObjectStore;
8146};
8147
8148class UnwindError : public Error {
8149 public:
8150 bool is_user_initiated() const { return untag()->is_user_initiated_; }
8151 void set_is_user_initiated(bool value) const;
8152
8153 StringPtr message() const { return untag()->message(); }
8154
8155 static intptr_t InstanceSize() {
8156 return RoundedAllocationSize(sizeof(UntaggedUnwindError));
8157 }
8158
8159 static UnwindErrorPtr New(const String& message,
8160 Heap::Space space = Heap::kNew);
8161
8162 virtual const char* ToErrorCString() const;
8163
8164 private:
8165 void set_message(const String& message) const;
8166
8168 friend class Class;
8169};
8170
8171// Instance is the base class for all instance objects (aka the Object class
8172// in Dart source code.
8173class Instance : public Object {
8174 public:
8175 // Equality and identity testing.
8176 // 1. OperatorEquals: true iff 'this == other' is true in Dart code.
8177 // 2. IsIdenticalTo: true iff 'identical(this, other)' is true in Dart code.
8178 // 3. CanonicalizeEquals: used to canonicalize compile-time constants, e.g.,
8179 // using bitwise equality of fields and list elements.
8180 // Subclasses where 1 and 3 coincide may also define a plain Equals, e.g.,
8181 // String and Integer.
8182 virtual bool OperatorEquals(const Instance& other) const;
8183 bool IsIdenticalTo(const Instance& other) const;
8184 virtual bool CanonicalizeEquals(const Instance& other) const;
8185 virtual uint32_t CanonicalizeHash() const;
8186
8187 intptr_t SizeFromClass() const {
8188#if defined(DEBUG)
8189 const Class& cls = Class::Handle(clazz());
8190 ASSERT(cls.is_finalized() || cls.is_prefinalized());
8191#endif
8192 return (clazz()->untag()->host_instance_size_in_words_ *
8193 kCompressedWordSize);
8194 }
8195
8196 InstancePtr Canonicalize(Thread* thread) const;
8197 // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
8198 virtual InstancePtr CanonicalizeLocked(Thread* thread) const;
8199 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
8200
8201 InstancePtr CopyShallowToOldSpace(Thread* thread) const;
8202
8203 ObjectPtr GetField(const Field& field) const;
8204
8205 void SetField(const Field& field, const Object& value) const;
8206
8207 AbstractTypePtr GetType(Heap::Space space) const;
8208
8209 // Access the type arguments vector of this [Instance].
8210 // This vector includes type arguments corresponding to type parameters of
8211 // instance's class and all its superclasses.
8212 virtual TypeArgumentsPtr GetTypeArguments() const;
8213 virtual void SetTypeArguments(const TypeArguments& value) const;
8214
8215 // Check if the type of this instance is a subtype of the given other type.
8216 // The type argument vectors are used to instantiate the other type if needed.
8217 bool IsInstanceOf(const AbstractType& other,
8218 const TypeArguments& other_instantiator_type_arguments,
8219 const TypeArguments& other_function_type_arguments) const;
8220
8221 // Check if this instance is assignable to the given other type.
8222 // The type argument vectors are used to instantiate the other type if needed.
8223 bool IsAssignableTo(const AbstractType& other,
8224 const TypeArguments& other_instantiator_type_arguments,
8225 const TypeArguments& other_function_type_arguments) const;
8226
8227 // Return true if the null instance can be assigned to a variable of [other]
8228 // type. Return false if null cannot be assigned or we cannot tell (if
8229 // [other] is a type parameter in NNBD strong mode). Only used for checks at
8230 // compile time.
8231 static bool NullIsAssignableTo(const AbstractType& other);
8232
8233 // Return true if the null instance can be assigned to a variable of [other]
8234 // type. Return false if null cannot be assigned. Used for checks at runtime,
8235 // when the instantiator and function type argument vectors are available.
8236 static bool NullIsAssignableTo(
8237 const AbstractType& other,
8238 const TypeArguments& other_instantiator_type_arguments,
8239 const TypeArguments& other_function_type_arguments);
8240
8241 bool IsValidNativeIndex(int index) const {
8242 return ((index >= 0) && (index < clazz()->untag()->num_native_fields_));
8243 }
8244
8245 intptr_t* NativeFieldsDataAddr() const;
8246 inline intptr_t GetNativeField(int index) const;
8247 inline void GetNativeFields(uint16_t num_fields,
8248 intptr_t* field_values) const;
8249 void SetNativeFields(uint16_t num_fields, const intptr_t* field_values) const;
8250
8251 uint16_t NumNativeFields() const {
8252 return clazz()->untag()->num_native_fields_;
8253 }
8254
8255 void SetNativeField(int index, intptr_t value) const;
8256
8257 // If the instance is a callable object, i.e. a closure or the instance of a
8258 // class implementing a 'call' method, return true and set the function
8259 // (if not nullptr) to call.
8260 bool IsCallable(Function* function) const;
8261
8262 ObjectPtr Invoke(const String& selector,
8263 const Array& arguments,
8264 const Array& argument_names,
8265 bool respect_reflectable = true,
8266 bool check_is_entrypoint = false) const;
8267 ObjectPtr InvokeGetter(const String& selector,
8268 bool respect_reflectable = true,
8269 bool check_is_entrypoint = false) const;
8270 ObjectPtr InvokeSetter(const String& selector,
8271 const Instance& argument,
8272 bool respect_reflectable = true,
8273 bool check_is_entrypoint = false) const;
8274
8275 ObjectPtr EvaluateCompiledExpression(
8276 const Class& klass,
8277 const ExternalTypedData& kernel_buffer,
8278 const Array& type_definitions,
8279 const Array& arguments,
8280 const TypeArguments& type_arguments) const;
8281
8282 // Evaluate the given expression as if it appeared in an instance method of
8283 // [receiver] and return the resulting value, or an error object if
8284 // evaluating the expression fails. The method has the formal (type)
8285 // parameters given in (type_)param_names, and is invoked with the (type)
8286 // argument values given in (type_)param_values.
8287 //
8288 // We allow [receiver] to be null/<optimized out> if
8289 // * the evaluation function doesn't access `this`
8290 // * the evaluation function is static
8291 static ObjectPtr EvaluateCompiledExpression(
8292 Thread* thread,
8293 const Object& receiver,
8294 const Library& library,
8295 const Class& klass,
8296 const ExternalTypedData& kernel_buffer,
8297 const Array& type_definitions,
8298 const Array& param_values,
8299 const TypeArguments& type_param_values);
8300
8301 // Equivalent to invoking hashCode on this instance.
8302 virtual ObjectPtr HashCode() const;
8303
8304 // Equivalent to invoking identityHashCode with this instance.
8305 IntegerPtr IdentityHashCode(Thread* thread) const;
8306
8307 static intptr_t UnroundedSize() { return sizeof(UntaggedInstance); }
8308 static intptr_t InstanceSize() {
8309 return RoundedAllocationSize(sizeof(UntaggedInstance));
8310 }
8311
8312 static InstancePtr New(const Class& cls, Heap::Space space = Heap::kNew);
8313 static InstancePtr NewAlreadyFinalized(const Class& cls,
8314 Heap::Space space = Heap::kNew);
8315
8316 // Array/list element address computations.
8317 static intptr_t DataOffsetFor(intptr_t cid);
8318 static intptr_t ElementSizeFor(intptr_t cid);
8319
8320 // Pointers may be subtyped, but their subtypes may not get extra fields.
8321 // The subtype runtime representation has exactly the same object layout,
8322 // only the class_id is different. So, it is safe to use subtype instances in
8323 // Pointer handles.
8324 virtual bool IsPointer() const;
8325
8326 static intptr_t NextFieldOffset() { return sizeof(UntaggedInstance); }
8327
8328 static intptr_t NativeFieldsOffset() { return sizeof(UntaggedObject); }
8329
8330 protected:
8331#ifndef PRODUCT
8332 virtual void PrintSharedInstanceJSON(JSONObject* jsobj,
8333 bool ref,
8334 bool include_id = true) const;
8335#endif
8336
8337 private:
8338 // Return true if the runtimeType of this instance is a subtype of other type.
8339 bool RuntimeTypeIsSubtypeOf(
8340 const AbstractType& other,
8341 const TypeArguments& other_instantiator_type_arguments,
8342 const TypeArguments& other_function_type_arguments) const;
8343
8344 // Returns true if the type of this instance is a subtype of FutureOr<T>
8345 // specified by instantiated type 'other'.
8346 // Returns false if other type is not a FutureOr.
8347 bool RuntimeTypeIsSubtypeOfFutureOr(Zone* zone,
8348 const AbstractType& other) const;
8349
8350 // Return true if the null instance is an instance of other type.
8351 static bool NullIsInstanceOf(
8352 const AbstractType& other,
8353 const TypeArguments& other_instantiator_type_arguments,
8354 const TypeArguments& other_function_type_arguments);
8355
8356 CompressedObjectPtr* FieldAddrAtOffset(intptr_t offset) const {
8357 ASSERT(IsValidFieldOffset(offset));
8358 return reinterpret_cast<CompressedObjectPtr*>(raw_value() - kHeapObjectTag +
8359 offset);
8360 }
8361 CompressedObjectPtr* FieldAddr(const Field& field) const {
8362 return FieldAddrAtOffset(field.HostOffset());
8363 }
8364 CompressedObjectPtr* NativeFieldsAddr() const {
8365 return FieldAddrAtOffset(sizeof(UntaggedObject));
8366 }
8367 void SetFieldAtOffset(intptr_t offset, const Object& value) const {
8368 StoreCompressedPointer(FieldAddrAtOffset(offset), value.ptr());
8369 }
8370 bool IsValidFieldOffset(intptr_t offset) const;
8371
8372 // The following raw methods are used for morphing.
8373 // They are needed due to the extraction of the class in IsValidFieldOffset.
8374 CompressedObjectPtr* RawFieldAddrAtOffset(intptr_t offset) const {
8375 return reinterpret_cast<CompressedObjectPtr*>(raw_value() - kHeapObjectTag +
8376 offset);
8377 }
8378 ObjectPtr RawGetFieldAtOffset(intptr_t offset) const {
8379 return RawFieldAddrAtOffset(offset)->Decompress(untag()->heap_base());
8380 }
8381 void RawSetFieldAtOffset(intptr_t offset, const Object& value) const {
8382 StoreCompressedPointer(RawFieldAddrAtOffset(offset), value.ptr());
8383 }
8384 void RawSetFieldAtOffset(intptr_t offset, ObjectPtr value) const {
8385 StoreCompressedPointer(RawFieldAddrAtOffset(offset), value);
8386 }
8387
8388 template <typename T>
8389 T* RawUnboxedFieldAddrAtOffset(intptr_t offset) const {
8390 return reinterpret_cast<T*>(raw_value() - kHeapObjectTag + offset);
8391 }
8392 template <typename T>
8393 T RawGetUnboxedFieldAtOffset(intptr_t offset) const {
8394 return *RawUnboxedFieldAddrAtOffset<T>(offset);
8395 }
8396 template <typename T>
8397 void RawSetUnboxedFieldAtOffset(intptr_t offset, const T& value) const {
8398 *RawUnboxedFieldAddrAtOffset<T>(offset) = value;
8399 }
8400
8401 // TODO(iposva): Determine if this gets in the way of Smi.
8402 HEAP_OBJECT_IMPLEMENTATION(Instance, Object);
8403 friend class ByteBuffer;
8404 friend class Class;
8405 friend class Closure;
8406 friend class Pointer;
8407 friend class DeferredObject;
8410 friend class RegExp;
8411 friend class StubCode;
8412 friend class TypedDataView;
8415 friend class ClassDeserializationCluster; // vtable
8416 friend class InstanceMorpher;
8417 friend class Obfuscator; // RawGetFieldAtOffset, RawSetFieldAtOffset
8418};
8419
8420class LibraryPrefix : public Instance {
8421 public:
8422 StringPtr name() const { return untag()->name(); }
8423 virtual StringPtr DictionaryName() const { return name(); }
8424
8425 ArrayPtr imports() const { return untag()->imports(); }
8426 intptr_t num_imports() const { return untag()->num_imports_; }
8427 LibraryPtr importer() const { return untag()->importer(); }
8428
8429 LibraryPtr GetLibrary(int index) const;
8430 void AddImport(const Namespace& import) const;
8431
8432 bool is_deferred_load() const { return untag()->is_deferred_load_; }
8433
8434 static intptr_t InstanceSize() {
8435 return RoundedAllocationSize(sizeof(UntaggedLibraryPrefix));
8436 }
8437
8438 static LibraryPrefixPtr New(const String& name,
8439 const Namespace& import,
8440 bool deferred_load,
8441 const Library& importer);
8442
8443 private:
8444 static constexpr int kInitialSize = 2;
8445 static constexpr int kIncrementSize = 2;
8446
8447 void set_name(const String& value) const;
8448 void set_imports(const Array& value) const;
8449 void set_num_imports(intptr_t value) const;
8450 void set_importer(const Library& value) const;
8451
8452 static LibraryPrefixPtr New();
8453
8455 friend class Class;
8456};
8457
8458// TypeParameters represents a list of formal type parameters with their bounds
8459// and their default values as calculated by CFE.
8460class TypeParameters : public Object {
8461 public:
8462 intptr_t Length() const;
8463
8464 static intptr_t names_offset() {
8465 return OFFSET_OF(UntaggedTypeParameters, names_);
8466 }
8467 StringPtr NameAt(intptr_t index) const;
8468 void SetNameAt(intptr_t index, const String& value) const;
8469
8470 static intptr_t flags_offset() {
8471 return OFFSET_OF(UntaggedTypeParameters, flags_);
8472 }
8473
8474 static intptr_t bounds_offset() {
8475 return OFFSET_OF(UntaggedTypeParameters, bounds_);
8476 }
8477 AbstractTypePtr BoundAt(intptr_t index) const;
8478 void SetBoundAt(intptr_t index, const AbstractType& value) const;
8479 bool AllDynamicBounds() const;
8480
8481 static intptr_t defaults_offset() {
8482 return OFFSET_OF(UntaggedTypeParameters, defaults_);
8483 }
8484 AbstractTypePtr DefaultAt(intptr_t index) const;
8485 void SetDefaultAt(intptr_t index, const AbstractType& value) const;
8486 bool AllDynamicDefaults() const;
8487
8488 // The isGenericCovariantImpl bits are packed into SMIs in the flags array,
8489 // but omitted if they're 0.
8490 bool IsGenericCovariantImplAt(intptr_t index) const;
8491 void SetIsGenericCovariantImplAt(intptr_t index, bool value) const;
8492
8493 // The number of flags per Smi should be a power of 2 in order to simplify the
8494 // generated code accessing the flags array.
8495#if !defined(DART_COMPRESSED_POINTERS)
8496 static constexpr intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 1;
8497#else
8498 static constexpr intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 2;
8499#endif
8500 static constexpr intptr_t kFlagsPerSmi = 1LL << kFlagsPerSmiShift;
8501 COMPILE_ASSERT(kFlagsPerSmi < kSmiBits);
8502 static constexpr intptr_t kFlagsPerSmiMask = kFlagsPerSmi - 1;
8503
8504 void Print(Thread* thread,
8505 Zone* zone,
8506 bool are_class_type_parameters,
8507 intptr_t base,
8508 NameVisibility name_visibility,
8509 BaseTextBuffer* printer) const;
8510
8511 static intptr_t InstanceSize() {
8512 return RoundedAllocationSize(sizeof(UntaggedTypeParameters));
8513 }
8514
8515 static TypeParametersPtr New(Heap::Space space = Heap::kOld);
8516 static TypeParametersPtr New(intptr_t count, Heap::Space space = Heap::kOld);
8517
8518 private:
8519 ArrayPtr names() const { return untag()->names(); }
8520 void set_names(const Array& value) const;
8521 ArrayPtr flags() const { return untag()->flags(); }
8522 void set_flags(const Array& value) const;
8523 TypeArgumentsPtr bounds() const { return untag()->bounds(); }
8524 void set_bounds(const TypeArguments& value) const;
8525 TypeArgumentsPtr defaults() const { return untag()->defaults(); }
8526 void set_defaults(const TypeArguments& value) const;
8527
8528 // Allocate and initialize the flags array to zero.
8529 void AllocateFlags(Heap::Space space) const;
8530 // Reset the flags array to null if all flags are zero.
8531 void OptimizeFlags() const;
8532
8533 FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeParameters, Object);
8534 friend class Class;
8535 friend class ClassFinalizer;
8538 friend class Function;
8539 friend class FunctionType;
8540 friend class Object;
8541 friend class Precompiler;
8542 friend class Type; // To determine whether to print type arguments.
8543};
8544
8545// A TypeArguments is an array of AbstractType.
8546class TypeArguments : public Instance {
8547 public:
8548 // Hash value for a type argument vector consisting solely of dynamic types.
8549 static constexpr intptr_t kAllDynamicHash = 1;
8550
8551 // Returns whether this TypeArguments vector can be used in a context that
8552 // expects a vector of length [count]. Always true for the null vector.
8553 bool HasCount(intptr_t count) const;
8554 static intptr_t length_offset() {
8555 return OFFSET_OF(UntaggedTypeArguments, length_);
8556 }
8557 intptr_t Length() const;
8558 AbstractTypePtr TypeAt(intptr_t index) const;
8559 AbstractTypePtr TypeAtNullSafe(intptr_t index) const;
8560 static intptr_t types_offset() {
8562 }
8563 static intptr_t type_at_offset(intptr_t index) {
8564 return types_offset() + index * kCompressedWordSize;
8565 }
8566 void SetTypeAt(intptr_t index, const AbstractType& value) const;
8567
8569 static intptr_t elements_start_offset() {
8570 return TypeArguments::types_offset();
8571 }
8572
8573 static constexpr intptr_t kElementSize = kCompressedWordSize;
8574 };
8575
8576 // The nullability of a type argument vector represents the nullability of its
8577 // type elements (up to a maximum number of them, i.e. kNullabilityMaxTypes).
8578 // It is used at runtime in some cases (predetermined by the compiler) to
8579 // decide whether the instantiator type arguments (ITA) can be shared instead
8580 // of performing a more costly instantiation of the uninstantiated type
8581 // arguments (UTA).
8582 // The vector nullability is stored as a bit vector (in a Smi field), using
8583 // 2 bits per type:
8584 // - the high bit is set if the type is nullable or legacy.
8585 // - the low bit is set if the type is nullable.
8586 // The nullability is 0 if the vector is longer than kNullabilityMaxTypes.
8587 // The condition evaluated at runtime to decide whether UTA can share ITA is
8588 // (UTA.nullability & ITA.nullability) == UTA.nullability
8589 // Note that this allows for ITA to be longer than UTA (the bit vector must be
8590 // stored in the same order as the corresponding type vector, i.e. with the
8591 // least significant 2 bits representing the nullability of the first type).
8592 static constexpr intptr_t kNullabilityBitsPerType = 2;
8593 static constexpr intptr_t kNullabilityMaxTypes =
8594 kSmiBits / kNullabilityBitsPerType;
8595 static constexpr intptr_t kNonNullableBits = 0;
8596 static constexpr intptr_t kNullableBits = 3;
8597 static constexpr intptr_t kLegacyBits = 2;
8598 intptr_t nullability() const;
8599 static intptr_t nullability_offset() {
8600 return OFFSET_OF(UntaggedTypeArguments, nullability_);
8601 }
8602
8603 // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
8604 StringPtr Name() const;
8605
8606 // The name of this type argument vector, e.g. "<T, dynamic, List<T>, int>".
8607 // Names of internal classes are mapped to their public interfaces.
8608 StringPtr UserVisibleName() const;
8609
8610 // Print the internal or public name of a subvector of this type argument
8611 // vector, e.g. "<T, dynamic, List<T>, int>".
8612 void PrintSubvectorName(intptr_t from_index,
8613 intptr_t len,
8614 NameVisibility name_visibility,
8615 BaseTextBuffer* printer) const;
8616 void PrintTo(BaseTextBuffer* printer) const;
8617
8618 // Check if the subvector of length 'len' starting at 'from_index' of this
8619 // type argument vector consists solely of DynamicType.
8620 bool IsRaw(intptr_t from_index, intptr_t len) const {
8621 return IsDynamicTypes(false, from_index, len);
8622 }
8623
8624 // Check if this type argument vector would consist solely of DynamicType if
8625 // it was instantiated from both a raw (null) instantiator type arguments and
8626 // a raw (null) function type arguments, i.e. consider each class type
8627 // parameter and function type parameters as it would be first instantiated
8628 // from a vector of dynamic types.
8629 // Consider only a prefix of length 'len'.
8630 bool IsRawWhenInstantiatedFromRaw(intptr_t len) const {
8631 return IsDynamicTypes(true, 0, len);
8632 }
8633
8634 TypeArgumentsPtr Prepend(Zone* zone,
8635 const TypeArguments& other,
8636 intptr_t other_length,
8637 intptr_t total_length) const;
8638
8639 // Concatenate [this] and [other] vectors of type parameters.
8640 TypeArgumentsPtr ConcatenateTypeParameters(Zone* zone,
8641 const TypeArguments& other) const;
8642
8643 // Returns an InstantiationMode for this type argument vector, which
8644 // specifies whether the type argument vector requires instantiation and
8645 // shortcuts to instantiate the vector when possible.
8646 //
8647 // If [function] is provided, any function type arguments used in the type
8648 // arguments vector are assumed to be bound by the function or its parent
8649 // functions.
8650 //
8651 // If [class] is provided, any class type arguments used in the type arguments
8652 // vector are assumed to be bound by that class. If [function] is provided
8653 // but [class] is not, then the owning class of the function is retrieved
8654 // and used.
8655 InstantiationMode GetInstantiationMode(Zone* zone,
8656 const Function* function = nullptr,
8657 const Class* cls = nullptr) const;
8658
8659 // Check if the vectors are equal (they may be null).
8660 bool Equals(const TypeArguments& other) const {
8661 return IsSubvectorEquivalent(other, 0, IsNull() ? 0 : Length(),
8662 TypeEquality::kCanonical);
8663 }
8664
8666 const TypeArguments& other,
8667 TypeEquality kind,
8668 FunctionTypeMapping* function_type_equivalence = nullptr) const {
8669 // Make a null vector a vector of dynamic as long as the other vector.
8670 return IsSubvectorEquivalent(other, 0, IsNull() ? other.Length() : Length(),
8671 kind, function_type_equivalence);
8672 }
8673 bool IsSubvectorEquivalent(
8674 const TypeArguments& other,
8675 intptr_t from_index,
8676 intptr_t len,
8677 TypeEquality kind,
8678 FunctionTypeMapping* function_type_equivalence = nullptr) const;
8679
8680 // Check if the vector is instantiated (it must not be null).
8681 bool IsInstantiated(Genericity genericity = kAny,
8682 intptr_t num_free_fun_type_params = kAllFree) const {
8683 return IsSubvectorInstantiated(0, Length(), genericity,
8684 num_free_fun_type_params);
8685 }
8686 bool IsSubvectorInstantiated(
8687 intptr_t from_index,
8688 intptr_t len,
8689 Genericity genericity = kAny,
8690 intptr_t num_free_fun_type_params = kAllFree) const;
8691 bool IsUninstantiatedIdentity() const;
8692
8693 // Determine whether this uninstantiated type argument vector can share its
8694 // instantiator (resp. function) type argument vector instead of being
8695 // instantiated at runtime.
8696 // If null is passed in for 'with_runtime_check', the answer is unconditional
8697 // (i.e. the answer will be false even if a runtime check may allow sharing),
8698 // otherwise, in case the function returns true, 'with_runtime_check'
8699 // indicates if a check is still required at runtime before allowing sharing.
8700 bool CanShareInstantiatorTypeArguments(
8701 const Class& instantiator_class,
8702 bool* with_runtime_check = nullptr) const;
8703 bool CanShareFunctionTypeArguments(const Function& function,
8704 bool* with_runtime_check = nullptr) const;
8705 TypeArgumentsPtr TruncatedTo(intptr_t length) const;
8706
8707 // Return true if all types of this vector are finalized.
8708 bool IsFinalized() const;
8709
8710 // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
8711 virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
8712 return Canonicalize(thread);
8713 }
8714
8715 // Canonicalize only if instantiated, otherwise returns 'this'.
8716 TypeArgumentsPtr Canonicalize(Thread* thread) const;
8717
8718 // Shrinks flattened instance type arguments to ordinary type arguments.
8719 TypeArgumentsPtr FromInstanceTypeArguments(Thread* thread,
8720 const Class& cls) const;
8721
8722 // Expands type arguments to a vector suitable as instantiator type
8723 // arguments.
8724 //
8725 // Only fills positions corresponding to type parameters of [cls], leave
8726 // all positions of superclass type parameters blank.
8727 // Use [GetInstanceTypeArguments] on a class or a type if full vector is
8728 // needed.
8729 TypeArgumentsPtr ToInstantiatorTypeArguments(Thread* thread,
8730 const Class& cls) const;
8731
8732 // Add the class name and URI of each type argument of this vector to the uris
8733 // list and mark ambiguous triplets to be printed.
8734 void EnumerateURIs(URIs* uris) const;
8735
8736 // Return 'this' if this type argument vector is instantiated, i.e. if it does
8737 // not refer to type parameters. Otherwise, return a new type argument vector
8738 // where each reference to a type parameter is replaced with the corresponding
8739 // type from the various type argument vectors (class instantiator, function,
8740 // or parent functions via the current context).
8741 TypeArgumentsPtr InstantiateFrom(
8742 const TypeArguments& instantiator_type_arguments,
8743 const TypeArguments& function_type_arguments,
8744 intptr_t num_free_fun_type_params,
8745 Heap::Space space,
8746 FunctionTypeMapping* function_type_mapping = nullptr,
8747 intptr_t num_parent_type_args_adjustment = 0) const;
8748
8749 // Update number of parent function type arguments for
8750 // all elements of this vector.
8751 TypeArgumentsPtr UpdateFunctionTypes(
8752 intptr_t num_parent_type_args_adjustment,
8753 intptr_t num_free_fun_type_params,
8754 Heap::Space space,
8755 FunctionTypeMapping* function_type_mapping) const;
8756
8757 // Runtime instantiation with canonicalization. Not to be used during type
8758 // finalization at compile time.
8759 TypeArgumentsPtr InstantiateAndCanonicalizeFrom(
8760 const TypeArguments& instantiator_type_arguments,
8761 const TypeArguments& function_type_arguments) const;
8762
8763 class Cache : public ValueObject {
8764 public:
8765 // The contents of the backing array storage is a header followed by
8766 // a number of entry tuples. Any entry that is unoccupied has
8767 // Sentinel() as its first component.
8768 //
8769 // If the cache is linear, the entries can be accessed in a linear fashion:
8770 // all occupied entries come first, followed by at least one unoccupied
8771 // entry to mark the end of the cache. Guaranteeing at least one unoccupied
8772 // entry avoids the need for a length check when iterating over the contents
8773 // of the linear cache in stubs.
8774 //
8775 // If the cache is hash-based, the array is instead treated as a hash table
8776 // probed by using a hash value derived from the instantiator and function
8777 // type arguments.
8778
8779 enum Header {
8780 // A single Smi that is a bitfield containing two values:
8781 // - The number of occupied entries in the cache for all caches.
8782 // - For hash-based caches, the upper bits contain log2(N) where N
8783 // is the number of total entries in the cache, so this information can
8784 // be quickly retrieved by stubs.
8785 //
8786 // Note: accesses outside of the type arguments canonicalization mutex
8787 // must have acquire semantics. In C++ code, use NumOccupied to retrieve
8788 // the number of occupied entries.
8789 kMetadataIndex = 0,
8791 };
8792
8793 using NumOccupiedBits = BitField<intptr_t,
8794 intptr_t,
8795 0,
8796 compiler::target::kSmiBits -
8797 compiler::target::kBitsPerWordLog2>;
8799 intptr_t,
8800 NumOccupiedBits::kNextBit,
8801 compiler::target::kBitsPerWordLog2>;
8802
8803 // The tuple of values stored in a given entry.
8804 //
8805 // Note: accesses of the first component outside of the type arguments
8806 // canonicalization mutex must have acquire semantics.
8807 enum Entry {
8808 kSentinelIndex = 0, // Used when only checking for sentinel values.
8809 kInstantiatorTypeArgsIndex = kSentinelIndex,
8813 };
8814
8815 // Requires that the type arguments canonicalization mutex is held.
8816 Cache(Zone* zone, const TypeArguments& source);
8817
8818 // Requires that the type arguments canonicalization mutex is held.
8819 Cache(Zone* zone, const Array& array);
8820
8821 // Used to check that the state of the backing array is valid.
8822 //
8823 // Requires that the type arguments canonicalization mutex is held.
8824 DEBUG_ONLY(static bool IsValidStorageLocked(const Array& array);)
8825
8826 // Returns the number of entries stored in the cache.
8827 intptr_t NumOccupied() const { return NumOccupied(data_); }
8828
8830 // The entry index if [present] is true, otherwise where the entry would
8831 // be located if added afterwards without any intermediate additions.
8832 intptr_t entry;
8833 bool present; // Whether an entry already exists in the cache.
8834 };
8835
8836 // If an entry contains the given instantiator and function type arguments,
8837 // returns a KeyLocation with the index of the entry and true. Otherwise,
8838 // returns the index an entry with those keys would have if added and false.
8840 const TypeArguments& function_tav) const {
8841 return FindKeyOrUnused(data_, instantiator_tav, function_tav);
8842 }
8843
8844 // Returns whether the entry at the given index in the cache is occupied.
8845 bool IsOccupied(intptr_t entry) const;
8846
8847 // Given an occupied entry index, returns the instantiated TypeArguments.
8848 TypeArgumentsPtr Retrieve(intptr_t entry) const;
8849
8850 // Adds a new instantiation mapping to the cache at index [entry]. Assumes
8851 // that the entry at index [entry] is unoccupied.
8852 //
8853 // May replace the underlying storage array, in which case the returned
8854 // index of the entry may differ from the requested one. If this Cache was
8855 // constructed using a TypeArguments object, its instantiations field is
8856 // also updated to point to the new storage.
8857 KeyLocation AddEntry(intptr_t entry,
8858 const TypeArguments& instantiator_tav,
8859 const TypeArguments& function_tav,
8860 const TypeArguments& instantiated_tav) const;
8861
8862 // The sentinel value used to mark unoccupied entries.
8863 static SmiPtr Sentinel();
8864
8865 static const Array& EmptyStorage() {
8866 return Object::empty_instantiations_cache_array();
8867 }
8868
8869 // Returns whether the cache is linear.
8870 bool IsLinear() const { return IsLinear(data_); }
8871
8872 // Returns whether the cache is hash-based.
8873 bool IsHash() const { return IsHash(data_); }
8874
8875 private:
8876 static constexpr double LoadFactor(intptr_t occupied, intptr_t capacity) {
8877 return occupied / static_cast<double>(capacity);
8878 }
8879
8880 // Returns the number of entries stored in the cache backed by the given
8881 // array.
8882 static intptr_t NumOccupied(const Array& array);
8883
8884 // Returns whether the cache backed by the given storage is linear.
8885 static bool IsLinear(const Array& array) { return !IsHash(array); }
8886
8887 // Returns whether the cache backed by the given storage is hash-based.
8888 static bool IsHash(const Array& array);
8889
8890 // Ensures that the backing store for the cache can hold at least [occupied]
8891 // occupied entries. If it cannot, replaces the backing store with one that
8892 // can, copying over entries from the old backing store.
8893 //
8894 // Returns whether the backing store changed.
8895 bool EnsureCapacity(intptr_t occupied) const;
8896
8897 public: // For testing purposes only.
8898 // Retrieves the number of entries (occupied or unoccupied) in the cache.
8899 intptr_t NumEntries() const { return NumEntries(data_); }
8900
8901 // The maximum number of occupied entries for a linear cache of
8902 // instantiations before swapping to a hash table-based cache.
8903#if defined(TARGET_ARCH_IA32)
8904 // We don't generate hash cache probing in the stub on IA32.
8905 static constexpr intptr_t kMaxLinearCacheEntries = 500;
8906#else
8907 static constexpr intptr_t kMaxLinearCacheEntries = 10;
8908#endif
8909
8910 private:
8911 // Retrieves the number of entries (occupied or unoccupied) in a cache
8912 // backed by the given array.
8913 static intptr_t NumEntries(const Array& array);
8914
8915 // If an entry in the given array contains the given instantiator and
8916 // function type arguments, returns a KeyLocation with the index of the
8917 // entry and true. Otherwise, returns a KeyLocation with the index that
8918 // would be used if the instantiation for the given type arguments is
8919 // added and false.
8920 static KeyLocation FindKeyOrUnused(const Array& array,
8921 const TypeArguments& instantiator_tav,
8922 const TypeArguments& function_tav);
8923
8924 // The sentinel value in the Smi returned from Sentinel().
8925 static constexpr intptr_t kSentinelValue = 0;
8926
8927 public: // Used in the StubCodeCompiler.
8928 // The maximum size of the array backing a linear cache. All hash based
8929 // caches are guaranteed to have sizes larger than this.
8930 static constexpr intptr_t kMaxLinearCacheSize =
8931 kHeaderSize + (kMaxLinearCacheEntries + 1) * kEntrySize;
8932
8933 private:
8934 // The initial number of entries used when converting from a linear to
8935 // a hash-based cache.
8936 static constexpr intptr_t kNumInitialHashCacheEntries =
8937 Utils::RoundUpToPowerOfTwo(2 * kMaxLinearCacheEntries);
8938 static_assert(Utils::IsPowerOfTwo(kNumInitialHashCacheEntries),
8939 "number of hash-based cache entries must be a power of two");
8940
8941 // The max load factor allowed in hash-based caches.
8942 static constexpr double kMaxLoadFactor = 0.71;
8943
8944 Zone* const zone_;
8945 const TypeArguments* const cache_container_;
8946 Array& data_;
8947 Smi& smi_handle_;
8948
8949 friend class TypeArguments; // For asserts against data_.
8950 };
8951
8952 // Return true if this type argument vector has cached instantiations.
8953 bool HasInstantiations() const;
8954
8955 static intptr_t instantiations_offset() {
8956 return OFFSET_OF(UntaggedTypeArguments, instantiations_);
8957 }
8958
8959 static constexpr intptr_t kBytesPerElement = kCompressedWordSize;
8960 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
8961
8962 static intptr_t InstanceSize() {
8963 ASSERT(sizeof(UntaggedTypeArguments) ==
8965 return 0;
8966 }
8967
8968 static intptr_t InstanceSize(intptr_t len) {
8969 // Ensure that the types() is not adding to the object size, which includes
8970 // 4 fields: instantiations_, length_, hash_, and nullability_.
8971 ASSERT(sizeof(UntaggedTypeArguments) ==
8972 (sizeof(UntaggedObject) + (kNumFields * kCompressedWordSize)));
8973 ASSERT(0 <= len && len <= kMaxElements);
8974 return RoundedAllocationSize(sizeof(UntaggedTypeArguments) +
8975 (len * kBytesPerElement));
8976 }
8977
8978 virtual uint32_t CanonicalizeHash() const {
8979 // Hash() is not stable until finalization is done.
8980 return 0;
8981 }
8982 uword Hash() const;
8983 uword HashForRange(intptr_t from_index, intptr_t len) const;
8984 static intptr_t hash_offset() {
8985 return OFFSET_OF(UntaggedTypeArguments, hash_);
8986 }
8987
8988 static TypeArgumentsPtr New(intptr_t len, Heap::Space space = Heap::kOld);
8989
8990 private:
8991 intptr_t ComputeNullability() const;
8992 void set_nullability(intptr_t value) const;
8993
8994 uword ComputeHash() const;
8995 void SetHash(intptr_t value) const;
8996
8997 // Check if the subvector of length 'len' starting at 'from_index' of this
8998 // type argument vector consists solely of DynamicType.
8999 // If raw_instantiated is true, consider each class type parameter to be first
9000 // instantiated from a vector of dynamic types.
9001 bool IsDynamicTypes(bool raw_instantiated,
9002 intptr_t from_index,
9003 intptr_t len) const;
9004
9005 ArrayPtr instantiations() const;
9006 void set_instantiations(const Array& value) const;
9007 void SetLength(intptr_t value) const;
9008 // Number of fields in the raw object is 4:
9009 // instantiations_, length_, hash_ and nullability_.
9010 static constexpr int kNumFields = 4;
9011
9013 friend class AbstractType;
9014 friend class Class;
9016 friend class Object;
9017};
9018
9019// AbstractType is an abstract superclass.
9020// Subclasses of AbstractType are Type and TypeParameter.
9021class AbstractType : public Instance {
9022 public:
9023 static intptr_t flags_offset() {
9024 return OFFSET_OF(UntaggedAbstractType, flags_);
9025 }
9026 static intptr_t hash_offset() {
9027 return OFFSET_OF(UntaggedAbstractType, hash_);
9028 }
9029
9030 bool IsFinalized() const {
9031 const auto state = type_state();
9032 return (state == UntaggedAbstractType::kFinalizedInstantiated) ||
9033 (state == UntaggedAbstractType::kFinalizedUninstantiated);
9034 }
9035 void SetIsFinalized() const;
9036
9038 return static_cast<Nullability>(
9039 UntaggedAbstractType::NullabilityBits::decode(untag()->flags()));
9040 }
9041 // Returns true if type has '?' nullability suffix, or it is a
9042 // built-in type which is always nullable (Null, dynamic or void).
9043 bool IsNullable() const { return nullability() == Nullability::kNullable; }
9044 // Returns true if type does not have any nullability suffix.
9045 // This function also returns true for type parameters without
9046 // nullability suffix ("T") which can be instantiated with
9047 // nullable or legacy types.
9048 bool IsNonNullable() const {
9049 return nullability() == Nullability::kNonNullable;
9050 }
9051 // Returns true if type has '*' nullability suffix, i.e.
9052 // it is from a legacy (opted-out) library.
9053 bool IsLegacy() const { return nullability() == Nullability::kLegacy; }
9054 // Returns true if it is guaranteed that null cannot be
9055 // assigned to this type.
9056 bool IsStrictlyNonNullable() const;
9057
9058 virtual AbstractTypePtr SetInstantiatedNullability(
9059 const TypeParameter& type_param,
9060 Heap::Space space) const;
9061 virtual AbstractTypePtr NormalizeFutureOrType(Heap::Space space) const;
9062
9063 virtual bool HasTypeClass() const { return type_class_id() != kIllegalCid; }
9064 virtual classid_t type_class_id() const;
9065 virtual ClassPtr type_class() const;
9066 virtual TypeArgumentsPtr arguments() const;
9067 virtual bool IsInstantiated(
9068 Genericity genericity = kAny,
9069 intptr_t num_free_fun_type_params = kAllFree) const;
9070 virtual bool CanonicalizeEquals(const Instance& other) const {
9071 return Equals(other);
9072 }
9073 virtual uint32_t CanonicalizeHash() const { return Hash(); }
9074 virtual bool Equals(const Instance& other) const {
9075 return IsEquivalent(other, TypeEquality::kCanonical);
9076 }
9077 virtual bool IsEquivalent(
9078 const Instance& other,
9079 TypeEquality kind,
9080 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9081
9082 // Instantiate this type using the given type argument vectors.
9083 //
9084 // Note that some type parameters appearing in this type may not require
9085 // instantiation. Consider a class C<T> declaring a non-generic method
9086 // foo(bar<B>(T t, B b)). Although foo is not a generic method, it takes a
9087 // generic function bar<B> as argument and its function type refers to class
9088 // type parameter T and function type parameter B. When instantiating the
9089 // function type of foo for a particular value of T, function type parameter B
9090 // must remain uninstantiated, because only T is a free variable in this type.
9091 //
9092 // Return a new type, or return 'this' if it is already instantiated.
9093 virtual AbstractTypePtr InstantiateFrom(
9094 const TypeArguments& instantiator_type_arguments,
9095 const TypeArguments& function_type_arguments,
9096 intptr_t num_free_fun_type_params,
9097 Heap::Space space,
9098 FunctionTypeMapping* function_type_mapping = nullptr,
9099 intptr_t num_parent_type_args_adjustment = 0) const;
9100
9101 // Update number of parent function type arguments for the
9102 // nested function types and their type parameters.
9103 //
9104 // This adjustment is needed when nesting one generic function type
9105 // inside another. It is also needed when function type is copied
9106 // and owners of type parameters need to be adjusted.
9107 //
9108 // Number of parent function type arguments is adjusted by
9109 // [num_parent_type_args_adjustment].
9110 // Type parameters up to [num_free_fun_type_params] are not adjusted.
9111 virtual AbstractTypePtr UpdateFunctionTypes(
9112 intptr_t num_parent_type_args_adjustment,
9113 intptr_t num_free_fun_type_params,
9114 Heap::Space space,
9115 FunctionTypeMapping* function_type_mapping) const;
9116
9117 // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
9118 virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
9119 return Canonicalize(thread);
9120 }
9121
9122 // Return the canonical version of this type.
9123 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
9124
9125 // Add the pair <name, uri> to the list, if not already present.
9126 static void AddURI(URIs* uris, const String& name, const String& uri);
9127
9128 // Return a formatted string of the uris.
9129 static StringPtr PrintURIs(URIs* uris);
9130
9131 // Returns a C-String (possibly "") representing the nullability of this type.
9132 // Legacy and undetermined suffixes are only displayed with kInternalName.
9133 virtual const char* NullabilitySuffix(NameVisibility name_visibility) const;
9134
9135 // The name of this type, including the names of its type arguments, if any.
9136 StringPtr Name() const;
9137 const char* NameCString() const;
9138
9139 // The name of this type, including the names of its type arguments, if any.
9140 // Names of internal classes are mapped to their public interfaces.
9141 StringPtr UserVisibleName() const;
9142 const char* UserVisibleNameCString() const;
9143
9144 // The name of this type, including the names of its type arguments, if any.
9145 // Privacy suffixes are dropped.
9146 StringPtr ScrubbedName() const;
9147 const char* ScrubbedNameCString() const;
9148
9149 // Return the internal or public name of this type, including the names of its
9150 // type arguments, if any.
9151 virtual void PrintName(NameVisibility visibility,
9152 BaseTextBuffer* printer) const;
9153
9154 // Add the class name and URI of each occurring type to the uris
9155 // list and mark ambiguous triplets to be printed.
9156 virtual void EnumerateURIs(URIs* uris) const;
9157
9158 uword Hash() const;
9159 virtual uword ComputeHash() const;
9160
9161 // The name of this type's class, i.e. without the type argument names of this
9162 // type.
9163 StringPtr ClassName() const;
9164
9165 // Check if this type represents the 'dynamic' type.
9166 bool IsDynamicType() const { return type_class_id() == kDynamicCid; }
9167
9168 // Check if this type represents the 'void' type.
9169 bool IsVoidType() const { return type_class_id() == kVoidCid; }
9170
9171 // Check if this type represents the 'Null' type.
9172 bool IsNullType() const;
9173
9174 // Check if this type represents the 'Never' type.
9175 bool IsNeverType() const;
9176
9177 // Check if this type represents the 'Sentinel' type.
9178 bool IsSentinelType() const;
9179
9180 // Check if this type represents the 'Object' type.
9181 bool IsObjectType() const { return type_class_id() == kInstanceCid; }
9182
9183 // Check if this type represents the 'Object?' type.
9185 return IsObjectType() && (nullability() == Nullability::kNullable);
9186 }
9187
9188 // Check if this type represents a top type for subtyping,
9189 // assignability and 'as' type tests.
9190 //
9191 // Returns true if
9192 // - any type is a subtype of this type;
9193 // - any value can be assigned to a variable of this type;
9194 // - 'as' type test always succeeds for this type.
9195 bool IsTopTypeForSubtyping() const;
9196
9197 // Check if this type represents a top type for 'is' type tests.
9198 // Returns true if 'is' type test always returns true for this type.
9199 bool IsTopTypeForInstanceOf() const;
9200
9201 // Check if this type represents the 'bool' type.
9202 bool IsBoolType() const { return type_class_id() == kBoolCid; }
9203
9204 // Check if this type represents the 'int' type.
9205 bool IsIntType() const;
9206
9207 // Check if this type represents the '_IntegerImplementation' type.
9208 bool IsIntegerImplementationType() const;
9209
9210 // Check if this type represents the 'double' type.
9211 bool IsDoubleType() const;
9212
9213 // Check if this type represents the 'Float32x4' type.
9214 bool IsFloat32x4Type() const;
9215
9216 // Check if this type represents the 'Float64x2' type.
9217 bool IsFloat64x2Type() const;
9218
9219 // Check if this type represents the 'Int32x4' type.
9220 bool IsInt32x4Type() const;
9221
9222 // Check if this type represents the 'num' type.
9223 bool IsNumberType() const { return type_class_id() == kNumberCid; }
9224
9225 // Check if this type represents the '_Smi' type.
9226 bool IsSmiType() const { return type_class_id() == kSmiCid; }
9227
9228 // Check if this type represents the '_Mint' type.
9229 bool IsMintType() const { return type_class_id() == kMintCid; }
9230
9231 // Check if this type represents the 'String' type.
9232 bool IsStringType() const;
9233
9234 // Check if this type represents the Dart 'Function' type.
9235 bool IsDartFunctionType() const;
9236
9237 // Check if this type represents the Dart '_Closure' type.
9238 bool IsDartClosureType() const;
9239
9240 // Check if this type represents the Dart 'Record' type.
9241 bool IsDartRecordType() const;
9242
9243 // Check if this type represents the 'Pointer' type from "dart:ffi".
9244 bool IsFfiPointerType() const;
9245
9246 // Check if this type represents the 'FutureOr' type.
9247 bool IsFutureOrType() const { return type_class_id() == kFutureOrCid; }
9248
9249 // Returns the type argument of this (possibly nested) 'FutureOr' type.
9250 // Returns unmodified type if this type is not a 'FutureOr' type.
9251 AbstractTypePtr UnwrapFutureOr() const;
9252
9253 // Returns true if catching this type will catch all exceptions.
9254 // Exception objects are guaranteed to be non-nullable, so
9255 // non-nullable Object is also a catch-all type.
9256 bool IsCatchAllType() const { return IsDynamicType() || IsObjectType(); }
9257
9258 // Returns true if this type has a type class permitted by SendPort.send for
9259 // messages between isolates in different groups. Does not recursively visit
9260 // type arguments.
9261 bool IsTypeClassAllowedBySpawnUri() const;
9262
9263 // Check the subtype relationship.
9264 bool IsSubtypeOf(
9265 const AbstractType& other,
9266 Heap::Space space,
9267 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9268
9269 // Returns true iff subtype is a subtype of supertype, false otherwise or if
9270 // an error occurred.
9271 static bool InstantiateAndTestSubtype(
9272 AbstractType* subtype,
9273 AbstractType* supertype,
9274 const TypeArguments& instantiator_type_args,
9275 const TypeArguments& function_type_args);
9276
9278 return OFFSET_OF(UntaggedAbstractType, type_test_stub_entry_point_);
9279 }
9280
9282 return untag()->type_test_stub_entry_point_;
9283 }
9284 CodePtr type_test_stub() const { return untag()->type_test_stub(); }
9285
9286 // Sets the TTS to [stub].
9287 //
9288 // The update will ensure both fields (code as well as the cached entrypoint)
9289 // are updated together.
9290 //
9291 // Can be used concurrently by multiple threads - the updates will be applied
9292 // in undetermined order - but always consistently.
9293 void SetTypeTestingStub(const Code& stub) const;
9294
9295 // Sets the TTS to the [stub].
9296 //
9297 // The caller has to ensure no other thread can concurrently try to update the
9298 // TTS. This should mainly be used when initializing newly allocated Type
9299 // objects.
9300 void InitializeTypeTestingStubNonAtomic(const Code& stub) const;
9301
9303 StoreNonPointer(&untag()->type_test_stub_entry_point_,
9304 Code::EntryPointOf(untag()->type_test_stub()));
9305 }
9306
9307 // No instances of type AbstractType are allocated, but InstanceSize() and
9308 // NextFieldOffset() are required to register class _AbstractType.
9309 static intptr_t InstanceSize() {
9310 return RoundedAllocationSize(sizeof(UntaggedAbstractType));
9311 }
9312
9313 static intptr_t NextFieldOffset() { return -kWordSize; }
9314
9315 private:
9316 // Returns true if this type is a subtype of FutureOr<T> specified by 'other'.
9317 // Returns false if other type is not a FutureOr.
9318 bool IsSubtypeOfFutureOr(
9319 Zone* zone,
9320 const AbstractType& other,
9321 Heap::Space space,
9322 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9323
9324 protected:
9325 bool IsNullabilityEquivalent(Thread* thread,
9326 const AbstractType& other_type,
9327 TypeEquality kind) const;
9328
9329 void SetHash(intptr_t value) const;
9330
9332 return static_cast<UntaggedAbstractType::TypeState>(
9333 UntaggedAbstractType::TypeStateBits::decode(untag()->flags()));
9334 }
9335 void set_flags(uint32_t value) const;
9336 void set_type_state(UntaggedAbstractType::TypeState value) const;
9337 void set_nullability(Nullability value) const;
9338
9340 friend class Class;
9342 friend class Function;
9343 friend class TypeArguments;
9344};
9345
9346// A Type consists of a class, possibly parameterized with type
9347// arguments. Example: C<T1, T2>.
9348class Type : public AbstractType {
9349 public:
9350 static intptr_t arguments_offset() {
9351 return OFFSET_OF(UntaggedType, arguments_);
9352 }
9353 virtual bool HasTypeClass() const {
9354 ASSERT(type_class_id() != kIllegalCid);
9355 return true;
9356 }
9357 TypePtr ToNullability(Nullability value, Heap::Space space) const;
9358 virtual classid_t type_class_id() const;
9359 virtual ClassPtr type_class() const;
9360 void set_type_class(const Class& value) const;
9361 virtual TypeArgumentsPtr arguments() const { return untag()->arguments(); }
9362 void set_arguments(const TypeArguments& value) const;
9363
9364 // Returns flattened instance type arguments vector for
9365 // instance of this type.
9366 TypeArgumentsPtr GetInstanceTypeArguments(Thread* thread,
9367 bool canonicalize = true) const;
9368
9369 virtual bool IsInstantiated(
9370 Genericity genericity = kAny,
9371 intptr_t num_free_fun_type_params = kAllFree) const;
9372 virtual bool IsEquivalent(
9373 const Instance& other,
9374 TypeEquality kind,
9375 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9376
9377 // Return true if this type can be used as the declaration type of cls after
9378 // canonicalization (passed-in cls must match type_class()).
9379 bool IsDeclarationTypeOf(const Class& cls) const;
9380
9381 virtual AbstractTypePtr InstantiateFrom(
9382 const TypeArguments& instantiator_type_arguments,
9383 const TypeArguments& function_type_arguments,
9384 intptr_t num_free_fun_type_params,
9385 Heap::Space space,
9386 FunctionTypeMapping* function_type_mapping = nullptr,
9387 intptr_t num_parent_type_args_adjustment = 0) const;
9388
9389 virtual AbstractTypePtr UpdateFunctionTypes(
9390 intptr_t num_parent_type_args_adjustment,
9391 intptr_t num_free_fun_type_params,
9392 Heap::Space space,
9393 FunctionTypeMapping* function_type_mapping) const;
9394
9395 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
9396 virtual void EnumerateURIs(URIs* uris) const;
9397 virtual void PrintName(NameVisibility visibility,
9398 BaseTextBuffer* printer) const;
9399
9400 virtual uword ComputeHash() const;
9401
9402 static intptr_t InstanceSize() {
9403 return RoundedAllocationSize(sizeof(UntaggedType));
9404 }
9405
9406 // The type of the literal 'null'.
9407 static TypePtr NullType();
9408
9409 // The 'dynamic' type.
9410 static TypePtr DynamicType();
9411
9412 // The 'void' type.
9413 static TypePtr VoidType();
9414
9415 // The 'Never' type.
9416 static TypePtr NeverType();
9417
9418 // The 'Object' type.
9419 static TypePtr ObjectType();
9420
9421 // The 'bool' type.
9422 static TypePtr BoolType();
9423
9424 // The 'int' type.
9425 static TypePtr IntType();
9426
9427 // The 'int?' type.
9428 static TypePtr NullableIntType();
9429
9430 // The 'Smi' type.
9431 static TypePtr SmiType();
9432
9433 // The 'Mint' type.
9434 static TypePtr MintType();
9435
9436 // The 'double' type.
9437 static TypePtr Double();
9438
9439 // The 'double?' type.
9440 static TypePtr NullableDouble();
9441
9442 // The 'Float32x4' type.
9443 static TypePtr Float32x4();
9444
9445 // The 'Float64x2' type.
9446 static TypePtr Float64x2();
9447
9448 // The 'Int32x4' type.
9449 static TypePtr Int32x4();
9450
9451 // The 'num' type.
9452 static TypePtr Number();
9453
9454 // The 'num?' type.
9455 static TypePtr NullableNumber();
9456
9457 // The 'String' type.
9458 static TypePtr StringType();
9459
9460 // The 'Array' type.
9461 static TypePtr ArrayType();
9462
9463 // The 'Function' type.
9464 static TypePtr DartFunctionType();
9465
9466 // The 'Type' type.
9467 static TypePtr DartTypeType();
9468
9469 // The finalized type of the given non-parameterized class.
9470 static TypePtr NewNonParameterizedType(const Class& type_class);
9471
9472 static TypePtr New(const Class& clazz,
9473 const TypeArguments& arguments,
9474 Nullability nullability = Nullability::kLegacy,
9475 Heap::Space space = Heap::kOld);
9476
9477 private:
9478 // Takes an intptr_t since the cids of some classes are larger than will fit
9479 // in ClassIdTagType. This allows us to guard against that case, instead of
9480 // silently truncating the cid.
9481 void set_type_class_id(intptr_t id) const;
9482
9483 static TypePtr New(Heap::Space space = Heap::kOld);
9484
9486 friend class Class;
9487 friend class TypeArguments;
9488};
9489
9490// A FunctionType represents the type of a function. It describes most of the
9491// signature of a function, excluding the names of type parameters and names
9492// of parameters, but includes the names of optional named parameters.
9494 public:
9495 // Reexported so they can be used by the flow graph builders.
9507
9508 virtual bool HasTypeClass() const { return false; }
9509 FunctionTypePtr ToNullability(Nullability value, Heap::Space space) const;
9510 virtual classid_t type_class_id() const { return kIllegalCid; }
9511 virtual bool IsInstantiated(
9512 Genericity genericity = kAny,
9513 intptr_t num_free_fun_type_params = kAllFree) const;
9514 virtual bool IsEquivalent(
9515 const Instance& other,
9516 TypeEquality kind,
9517 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9518
9519 virtual AbstractTypePtr InstantiateFrom(
9520 const TypeArguments& instantiator_type_arguments,
9521 const TypeArguments& function_type_arguments,
9522 intptr_t num_free_fun_type_params,
9523 Heap::Space space,
9524 FunctionTypeMapping* function_type_mapping = nullptr,
9525 intptr_t num_parent_type_args_adjustment = 0) const;
9526
9527 virtual AbstractTypePtr UpdateFunctionTypes(
9528 intptr_t num_parent_type_args_adjustment,
9529 intptr_t num_free_fun_type_params,
9530 Heap::Space space,
9531 FunctionTypeMapping* function_type_mapping) const;
9532
9533 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
9534 virtual void EnumerateURIs(URIs* uris) const;
9535 virtual void PrintName(NameVisibility visibility,
9536 BaseTextBuffer* printer) const;
9537
9538 virtual uword ComputeHash() const;
9539
9540 bool IsSubtypeOf(
9541 const FunctionType& other,
9542 Heap::Space space,
9543 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9544
9545 static intptr_t NumParentTypeArgumentsOf(FunctionTypePtr ptr) {
9546 return ptr->untag()
9547 ->packed_type_parameter_counts_.Read<PackedNumParentTypeArguments>();
9548 }
9549 // Return the number of type arguments in the enclosing signature.
9550 intptr_t NumParentTypeArguments() const {
9551 return NumParentTypeArgumentsOf(ptr());
9552 }
9553 void SetNumParentTypeArguments(intptr_t value) const;
9554 static intptr_t NumTypeParametersOf(FunctionTypePtr ptr) {
9555 return ptr->untag()
9556 ->packed_type_parameter_counts_.Read<PackedNumTypeParameters>();
9557 }
9558 intptr_t NumTypeParameters() const { return NumTypeParametersOf(ptr()); }
9559
9560 static intptr_t NumTypeArgumentsOf(FunctionTypePtr ptr) {
9561 return NumTypeParametersOf(ptr) + NumParentTypeArgumentsOf(ptr);
9562 }
9563 intptr_t NumTypeArguments() const { return NumTypeArgumentsOf(ptr()); }
9564
9565 intptr_t num_implicit_parameters() const {
9566 return untag()
9567 ->packed_parameter_counts_.Read<PackedNumImplicitParameters>();
9568 }
9569 void set_num_implicit_parameters(intptr_t value) const;
9570
9571 static intptr_t NumFixedParametersOf(FunctionTypePtr ptr) {
9572 return ptr->untag()
9573 ->packed_parameter_counts_.Read<PackedNumFixedParameters>();
9574 }
9575 intptr_t num_fixed_parameters() const { return NumFixedParametersOf(ptr()); }
9576 void set_num_fixed_parameters(intptr_t value) const;
9577
9578 static bool HasOptionalParameters(FunctionTypePtr ptr) {
9579 return ptr->untag()
9580 ->packed_parameter_counts_.Read<PackedNumOptionalParameters>() >
9581 0;
9582 }
9583 bool HasOptionalParameters() const { return HasOptionalParameters(ptr()); }
9584
9585 static bool HasOptionalNamedParameters(FunctionTypePtr ptr) {
9586 return ptr->untag()
9587 ->packed_parameter_counts_.Read<PackedHasNamedOptionalParameters>();
9588 }
9590 return HasOptionalNamedParameters(ptr());
9591 }
9592 bool HasRequiredNamedParameters() const;
9593
9594 static bool HasOptionalPositionalParameters(FunctionTypePtr ptr) {
9595 return !HasOptionalNamedParameters(ptr) && HasOptionalParameters(ptr);
9596 }
9598 return HasOptionalPositionalParameters(ptr());
9599 }
9600
9601 static intptr_t NumOptionalParametersOf(FunctionTypePtr ptr) {
9602 return ptr->untag()
9603 ->packed_parameter_counts_.Read<PackedNumOptionalParameters>();
9604 }
9605 intptr_t NumOptionalParameters() const {
9606 return NumOptionalParametersOf(ptr());
9607 }
9608 void SetNumOptionalParameters(intptr_t num_optional_parameters,
9609 bool are_optional_positional) const;
9610
9611 static intptr_t NumOptionalPositionalParametersOf(FunctionTypePtr ptr) {
9612 return HasOptionalNamedParameters(ptr) ? 0 : NumOptionalParametersOf(ptr);
9613 }
9615 return NumOptionalPositionalParametersOf(ptr());
9616 }
9617
9618 static intptr_t NumOptionalNamedParametersOf(FunctionTypePtr ptr) {
9619 return HasOptionalNamedParameters(ptr) ? NumOptionalParametersOf(ptr) : 0;
9620 }
9622 return NumOptionalNamedParametersOf(ptr());
9623 }
9624
9625 static intptr_t NumParametersOf(FunctionTypePtr ptr) {
9626 return NumFixedParametersOf(ptr) + NumOptionalParametersOf(ptr);
9627 }
9628 intptr_t NumParameters() const { return NumParametersOf(ptr()); }
9629
9630 uint32_t packed_parameter_counts() const {
9631 return untag()->packed_parameter_counts_;
9632 }
9633 void set_packed_parameter_counts(uint32_t packed_parameter_counts) const;
9635 return OFFSET_OF(UntaggedFunctionType, packed_parameter_counts_);
9636 }
9638 return untag()->packed_type_parameter_counts_;
9639 }
9640 void set_packed_type_parameter_counts(uint16_t packed_parameter_counts) const;
9642 return OFFSET_OF(UntaggedFunctionType, packed_type_parameter_counts_);
9643 }
9644
9645 // Return the type parameter declared at index.
9646 TypeParameterPtr TypeParameterAt(
9647 intptr_t index,
9648 Nullability nullability = Nullability::kNonNullable) const;
9649
9650 AbstractTypePtr result_type() const { return untag()->result_type(); }
9651 void set_result_type(const AbstractType& value) const;
9652
9653 // The parameters, starting with NumImplicitParameters() parameters which are
9654 // only visible to the VM, but not to Dart users.
9655 // Note that type checks exclude implicit parameters.
9656 AbstractTypePtr ParameterTypeAt(intptr_t index) const;
9657 void SetParameterTypeAt(intptr_t index, const AbstractType& value) const;
9658 ArrayPtr parameter_types() const { return untag()->parameter_types(); }
9659 void set_parameter_types(const Array& value) const;
9660 static intptr_t parameter_types_offset() {
9661 return OFFSET_OF(UntaggedFunctionType, parameter_types_);
9662 }
9663 // Parameter names are only stored for named parameters. If there are no named
9664 // parameters, named_parameter_names() is null.
9665 // If there are parameter flags (eg required) they're stored at the end of
9666 // this array, so the size of this array isn't necessarily
9667 // NumOptionalNamedParameters(), but the first NumOptionalNamedParameters()
9668 // elements are the names.
9669 ArrayPtr named_parameter_names() const {
9670 return untag()->named_parameter_names();
9671 }
9672 void set_named_parameter_names(const Array& value) const;
9674 return OFFSET_OF(UntaggedFunctionType, named_parameter_names_);
9675 }
9676 // The index for these operations is the absolute index of the parameter, not
9677 // the index relative to the start of the named parameters (if any).
9678 StringPtr ParameterNameAt(intptr_t index) const;
9679 // Only valid for absolute indexes of named parameters.
9680 void SetParameterNameAt(intptr_t index, const String& value) const;
9681
9682 // The required flags are stored at the end of the parameter_names. The flags
9683 // are packed into SMIs, but omitted if they're 0.
9684 bool IsRequiredAt(intptr_t index) const;
9685 void SetIsRequiredAt(intptr_t index) const;
9686
9687 // Sets up the signature's parameter name array, including appropriate space
9688 // for any possible parameter flags. This may be an overestimate if some
9689 // parameters don't have flags, and so FinalizeNameArray() should
9690 // be called after all parameter flags have been appropriately set.
9691 //
9692 // Assumes that the number of fixed and optional parameters for the signature
9693 // has already been set. Uses same default space as FunctionType::New.
9694 void CreateNameArrayIncludingFlags(Heap::Space space = Heap::kOld) const;
9695
9696 // Truncate the parameter names array to remove any unused flag slots. Make
9697 // sure to only do this after calling SetIsRequiredAt as necessary.
9698 void FinalizeNameArray() const;
9699
9700 // Returns the length of the parameter names array that is required to store
9701 // all the names plus all their flags. This may be an overestimate if some
9702 // parameters don't have flags.
9703 static intptr_t NameArrayLengthIncludingFlags(intptr_t num_parameters);
9704
9705 // The formal type parameters, their bounds, and defaults, are specified as an
9706 // object of type TypeParameters.
9707 TypeParametersPtr type_parameters() const {
9708 return untag()->type_parameters();
9709 }
9710 void SetTypeParameters(const TypeParameters& value) const;
9711 static intptr_t type_parameters_offset() {
9712 return OFFSET_OF(UntaggedFunctionType, type_parameters_);
9713 }
9714
9715 // Returns true if this function type has the same number of type parameters
9716 // with equal bounds as the other function type. Type parameter names and
9717 // parameter names (unless optional named) are ignored.
9718 bool HasSameTypeParametersAndBounds(
9719 const FunctionType& other,
9720 TypeEquality kind,
9721 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9722
9723 // Return true if this function type declares type parameters.
9724 static bool IsGeneric(FunctionTypePtr ptr) {
9725 return ptr->untag()->type_parameters() != TypeParameters::null();
9726 }
9727 bool IsGeneric() const { return IsGeneric(ptr()); }
9728
9729 // Return true if any enclosing signature of this signature is generic.
9730 bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
9731
9732 // Returns true if the type of the formal parameter at the given position in
9733 // this function type is contravariant with the type of the other formal
9734 // parameter at the given position in the other function type.
9735 bool IsContravariantParameter(
9736 intptr_t parameter_position,
9737 const FunctionType& other,
9738 intptr_t other_parameter_position,
9739 Heap::Space space,
9740 FunctionTypeMapping* function_type_equivalence) const;
9741
9742 // Returns the index in the parameter names array of the corresponding flag
9743 // for the given parameter index. Also returns (via flag_mask) the
9744 // corresponding mask within the flag.
9745 intptr_t GetRequiredFlagIndex(intptr_t index, intptr_t* flag_mask) const;
9746
9747 void Print(NameVisibility name_visibility, BaseTextBuffer* printer) const;
9748 void PrintParameters(Thread* thread,
9749 Zone* zone,
9750 NameVisibility name_visibility,
9751 BaseTextBuffer* printer) const;
9752
9753 StringPtr ToUserVisibleString() const;
9754 const char* ToUserVisibleCString() const;
9755
9756 static intptr_t InstanceSize() {
9757 return RoundedAllocationSize(sizeof(UntaggedFunctionType));
9758 }
9759
9760 static FunctionTypePtr New(intptr_t num_parent_type_arguments = 0,
9761 Nullability nullability = Nullability::kLegacy,
9762 Heap::Space space = Heap::kOld);
9763
9764 static FunctionTypePtr Clone(const FunctionType& orig, Heap::Space space);
9765
9766 bool ContainsHandles() const;
9767
9768 private:
9769 static FunctionTypePtr New(Heap::Space space);
9770
9772 friend class Class;
9773 friend class Function;
9774};
9775
9776// A TypeParameter represents a type parameter of a parameterized class.
9777// It specifies its index (and its name for debugging purposes), as well as its
9778// upper bound.
9779// For example, the type parameter 'V' is specified as index 1 in the context of
9780// the class HashMap<K, V>. At compile time, the TypeParameter is not
9781// instantiated yet, i.e. it is only a place holder.
9782// Upon finalization, the TypeParameter index is changed to reflect its position
9783// as type argument (rather than type parameter) of the parameterized class.
9784// If the type parameter is declared without an extends clause, its bound is set
9785// to the ObjectType.
9787 public:
9788 TypeParameterPtr ToNullability(Nullability value, Heap::Space space) const;
9789 virtual bool HasTypeClass() const { return false; }
9790 virtual classid_t type_class_id() const { return kIllegalCid; }
9791
9793 return UntaggedTypeParameter::IsFunctionTypeParameter::decode(
9794 untag()->flags());
9795 }
9796 bool IsClassTypeParameter() const { return !IsFunctionTypeParameter(); }
9797
9798 intptr_t base() const { return untag()->base_; }
9799 void set_base(intptr_t value) const;
9800 intptr_t index() const { return untag()->index_; }
9801 void set_index(intptr_t value) const;
9802 static intptr_t index_offset() {
9803 return OFFSET_OF(UntaggedTypeParameter, index_);
9804 }
9805
9806 classid_t parameterized_class_id() const;
9807 void set_parameterized_class_id(classid_t value) const;
9808 ClassPtr parameterized_class() const;
9809 FunctionTypePtr parameterized_function_type() const;
9810
9811 AbstractTypePtr bound() const;
9812
9813 virtual bool IsInstantiated(
9814 Genericity genericity = kAny,
9815 intptr_t num_free_fun_type_params = kAllFree) const;
9816 virtual bool IsEquivalent(
9817 const Instance& other,
9818 TypeEquality kind,
9819 FunctionTypeMapping* function_type_equivalence = nullptr) const;
9820 virtual AbstractTypePtr InstantiateFrom(
9821 const TypeArguments& instantiator_type_arguments,
9822 const TypeArguments& function_type_arguments,
9823 intptr_t num_free_fun_type_params,
9824 Heap::Space space,
9825 FunctionTypeMapping* function_type_mapping = nullptr,
9826 intptr_t num_parent_type_args_adjustment = 0) const;
9827
9828 virtual AbstractTypePtr UpdateFunctionTypes(
9829 intptr_t num_parent_type_args_adjustment,
9830 intptr_t num_free_fun_type_params,
9831 Heap::Space space,
9832 FunctionTypeMapping* function_type_mapping) const;
9833
9834 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
9835 virtual void EnumerateURIs(URIs* uris) const { return; }
9836 virtual void PrintName(NameVisibility visibility,
9837 BaseTextBuffer* printer) const;
9838
9839 // Returns type corresponding to [this] type parameter from the
9840 // given [instantiator_type_arguments] and [function_type_arguments].
9841 // Unlike InstantiateFrom, nullability of type parameter is not applied to
9842 // the result.
9843 AbstractTypePtr GetFromTypeArguments(
9844 const TypeArguments& instantiator_type_arguments,
9845 const TypeArguments& function_type_arguments) const;
9846
9847 // Return a constructed name for this nameless type parameter.
9848 const char* CanonicalNameCString() const {
9849 return CanonicalNameCString(IsClassTypeParameter(), base(), index());
9850 }
9851
9852 static const char* CanonicalNameCString(bool is_class_type_parameter,
9853 intptr_t base,
9854 intptr_t index);
9855
9856 static intptr_t InstanceSize() {
9857 return RoundedAllocationSize(sizeof(UntaggedTypeParameter));
9858 }
9859
9860 // 'owner' is a Class or FunctionType.
9861 static TypeParameterPtr New(const Object& owner,
9862 intptr_t base,
9863 intptr_t index,
9864 Nullability nullability);
9865
9866 private:
9867 virtual uword ComputeHash() const;
9868
9869 void set_owner(const Object& value) const;
9870
9871 static TypeParameterPtr New();
9872
9874 friend class Class;
9875};
9876
9877class Number : public Instance {
9878 public:
9879 // TODO(iposva): Add more useful Number methods.
9880 StringPtr ToString(Heap::Space space) const;
9881
9882 private:
9884
9885 friend class Class;
9886};
9887
9888class Integer : public Number {
9889 public:
9890 static IntegerPtr New(const String& str, Heap::Space space = Heap::kNew);
9891
9892 // Creates a new Integer by given uint64_t value.
9893 // Silently casts value to int64_t with wrap-around if it is greater
9894 // than kMaxInt64.
9895 static IntegerPtr NewFromUint64(uint64_t value,
9896 Heap::Space space = Heap::kNew);
9897
9898 // Returns a canonical Integer object allocated in the old gen space.
9899 // Returns null if integer is out of range.
9900 static IntegerPtr NewCanonical(const String& str);
9901 static IntegerPtr NewCanonical(int64_t value);
9902
9903 static IntegerPtr New(int64_t value, Heap::Space space = Heap::kNew);
9904
9905 // Returns true iff the given uint64_t value is representable as Dart integer.
9906 static bool IsValueInRange(uint64_t value);
9907
9908 virtual bool OperatorEquals(const Instance& other) const {
9909 return Equals(other);
9910 }
9911 virtual bool CanonicalizeEquals(const Instance& other) const {
9912 return Equals(other);
9913 }
9914 virtual uint32_t CanonicalizeHash() const;
9915 virtual bool Equals(const Instance& other) const;
9916
9917 virtual ObjectPtr HashCode() const { return ptr(); }
9918
9919 virtual bool IsZero() const;
9920 virtual bool IsNegative() const;
9921
9922 virtual double AsDoubleValue() const;
9923 virtual int64_t AsInt64Value() const;
9924 virtual int64_t AsTruncatedInt64Value() const { return AsInt64Value(); }
9925 virtual uint32_t AsTruncatedUint32Value() const;
9926
9927 virtual bool FitsIntoSmi() const;
9928
9929 // Returns 0, -1 or 1.
9930 virtual int CompareWith(const Integer& other) const;
9931
9932 // Converts integer to hex string.
9933 const char* ToHexCString(Zone* zone) const;
9934
9935 // Return the most compact presentation of an integer.
9936 IntegerPtr AsValidInteger() const;
9937
9938 // Returns null to indicate that a bigint operation is required.
9939 IntegerPtr ArithmeticOp(Token::Kind operation,
9940 const Integer& other,
9941 Heap::Space space = Heap::kNew) const;
9942 IntegerPtr BitOp(Token::Kind operation,
9943 const Integer& other,
9944 Heap::Space space = Heap::kNew) const;
9945 IntegerPtr ShiftOp(Token::Kind operation,
9946 const Integer& other,
9947 Heap::Space space = Heap::kNew) const;
9948
9949 static int64_t GetInt64Value(const IntegerPtr obj) {
9950 if (obj->IsSmi()) {
9951 return RawSmiValue(static_cast<const SmiPtr>(obj));
9952 } else {
9953 ASSERT(obj->IsMint());
9954 return static_cast<const MintPtr>(obj)->untag()->value_;
9955 }
9956 }
9957
9958 private:
9960 friend class Class;
9961};
9962
9963class Smi : public Integer {
9964 public:
9965 static constexpr intptr_t kBits = kSmiBits;
9966 static constexpr intptr_t kMaxValue = kSmiMax;
9967 static constexpr intptr_t kMinValue = kSmiMin;
9968
9969 intptr_t Value() const { return RawSmiValue(ptr()); }
9970
9971 virtual bool Equals(const Instance& other) const;
9972 virtual bool IsZero() const { return Value() == 0; }
9973 virtual bool IsNegative() const { return Value() < 0; }
9974
9975 virtual double AsDoubleValue() const;
9976 virtual int64_t AsInt64Value() const;
9977 virtual uint32_t AsTruncatedUint32Value() const;
9978
9979 virtual bool FitsIntoSmi() const { return true; }
9980
9981 virtual int CompareWith(const Integer& other) const;
9982
9983 static intptr_t InstanceSize() { return 0; }
9984
9985 static SmiPtr New(intptr_t value) {
9986 SmiPtr raw_smi = static_cast<SmiPtr>(
9987 (static_cast<uintptr_t>(value) << kSmiTagShift) | kSmiTag);
9988 ASSERT(RawSmiValue(raw_smi) == value);
9989 return raw_smi;
9990 }
9991
9992 static ClassPtr Class();
9993
9994 static intptr_t Value(const SmiPtr raw_smi) { return RawSmiValue(raw_smi); }
9995#if defined(DART_COMPRESSED_POINTERS)
9996 static intptr_t Value(const CompressedSmiPtr raw_smi) {
9997 return Smi::Value(static_cast<SmiPtr>(raw_smi.DecompressSmi()));
9998 }
9999#endif
10000
10001 static intptr_t RawValue(intptr_t value) {
10002 return static_cast<intptr_t>(New(value));
10003 }
10004
10005 static bool IsValid(int64_t value) { return compiler::target::IsSmi(value); }
10006
10007 void operator=(SmiPtr value) {
10008 ptr_ = value;
10009 CHECK_HANDLE();
10010 }
10011 void operator^=(ObjectPtr value) {
10012 ptr_ = value;
10013 CHECK_HANDLE();
10014 }
10015
10016 private:
10017 static intptr_t NextFieldOffset() {
10018 // Indicates this class cannot be extended by dart code.
10019 return -kWordSize;
10020 }
10021
10022 Smi() : Integer() {}
10023 BASE_OBJECT_IMPLEMENTATION(Smi, Integer);
10025 friend class Api; // For ValueFromRaw
10026 friend class Class;
10027 friend class Object;
10028 friend class ReusableSmiHandleScope;
10029 friend class Thread;
10030};
10031
10033 public:
10034 static const char* Name() { return "SmiTraits"; }
10035 static bool ReportStats() { return false; }
10036
10037 static bool IsMatch(const Object& a, const Object& b) {
10038 return Smi::Cast(a).Value() == Smi::Cast(b).Value();
10039 }
10040
10041 static uword Hash(const Object& obj) { return Smi::Cast(obj).Value(); }
10042};
10043
10044class Mint : public Integer {
10045 public:
10046 static constexpr intptr_t kBits = 63; // 64-th bit is sign.
10047 static constexpr int64_t kMaxValue =
10048 static_cast<int64_t>(DART_2PART_UINT64_C(0x7FFFFFFF, FFFFFFFF));
10049 static constexpr int64_t kMinValue =
10050 static_cast<int64_t>(DART_2PART_UINT64_C(0x80000000, 00000000));
10051
10052 int64_t value() const { return untag()->value_; }
10053 static intptr_t value_offset() { return OFFSET_OF(UntaggedMint, value_); }
10054 static int64_t Value(MintPtr mint) { return mint->untag()->value_; }
10055
10056 virtual bool IsZero() const { return value() == 0; }
10057 virtual bool IsNegative() const { return value() < 0; }
10058
10059 virtual bool Equals(const Instance& other) const;
10060
10061 virtual double AsDoubleValue() const;
10062 virtual int64_t AsInt64Value() const;
10063 virtual uint32_t AsTruncatedUint32Value() const;
10064
10065 virtual bool FitsIntoSmi() const;
10066
10067 virtual int CompareWith(const Integer& other) const;
10068
10069 static intptr_t InstanceSize() {
10070 return RoundedAllocationSize(sizeof(UntaggedMint));
10071 }
10072
10073 protected:
10074 // Only Integer::NewXXX is allowed to call Mint::NewXXX directly.
10075 friend class Integer;
10077
10078 static MintPtr New(int64_t value, Heap::Space space = Heap::kNew);
10079
10080 static MintPtr NewCanonical(int64_t value);
10081
10082 private:
10083 void set_value(int64_t value) const;
10084
10086 friend class Class;
10087 friend class Number;
10088};
10089
10090// Class Double represents class Double in corelib_impl, which implements
10091// abstract class double in corelib.
10092class Double : public Number {
10093 public:
10094 double value() const { return untag()->value_; }
10095 static double Value(DoublePtr dbl) { return dbl->untag()->value_; }
10096
10097 bool BitwiseEqualsToDouble(double value) const;
10098 virtual bool OperatorEquals(const Instance& other) const;
10099 virtual bool CanonicalizeEquals(const Instance& other) const;
10100 virtual uint32_t CanonicalizeHash() const;
10101
10102 static DoublePtr New(double d, Heap::Space space = Heap::kNew);
10103
10104 static DoublePtr New(const String& str, Heap::Space space = Heap::kNew);
10105
10106 // Returns a canonical double object allocated in the old gen space.
10107 static DoublePtr NewCanonical(double d);
10108
10109 // Returns a canonical double object (allocated in the old gen space) or
10110 // Double::null() if str points to a string that does not convert to a
10111 // double value.
10112 static DoublePtr NewCanonical(const String& str);
10113
10114 static intptr_t InstanceSize() {
10115 return RoundedAllocationSize(sizeof(UntaggedDouble));
10116 }
10117
10118 static intptr_t value_offset() { return OFFSET_OF(UntaggedDouble, value_); }
10119
10120 private:
10121 void set_value(double value) const;
10122
10124 friend class Class;
10125 friend class Number;
10126};
10127
10128// TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
10129class Symbol : public AllStatic {
10130 public:
10131 static bool IsSymbolCid(Thread* thread, classid_t class_id);
10132
10133 static uint32_t CanonicalizeHash(Thread* thread, const Instance& instance);
10134};
10135
10136// String may not be '\0' terminated.
10137class String : public Instance {
10138 public:
10139 static constexpr intptr_t kOneByteChar = 1;
10140 static constexpr intptr_t kTwoByteChar = 2;
10141
10142// All strings share the same maximum element count to keep things
10143// simple. We choose a value that will prevent integer overflow for
10144// 2 byte strings, since it is the worst case.
10145#if defined(HASH_IN_OBJECT_HEADER)
10146 static constexpr intptr_t kSizeofRawString =
10147 sizeof(UntaggedInstance) + kWordSize;
10148#else
10149 static constexpr intptr_t kSizeofRawString =
10150 sizeof(UntaggedInstance) + 2 * kWordSize;
10151#endif
10152 static constexpr intptr_t kMaxElements = kSmiMax / kTwoByteChar;
10153
10154 static intptr_t HeaderSize() { return String::kSizeofRawString; }
10155
10156 static intptr_t InstanceSize() {
10157 return RoundedAllocationSize(sizeof(UntaggedString));
10158 }
10159
10161 public:
10162 explicit CodePointIterator(const String& str)
10163 : str_(str), ch_(0), index_(-1), end_(str.Length()) {
10164 ASSERT(!str_.IsNull());
10165 }
10166
10167 CodePointIterator(const String& str, intptr_t start, intptr_t length)
10168 : str_(str), ch_(0), index_(start - 1), end_(start + length) {
10169 ASSERT(start >= 0);
10170 ASSERT(end_ <= str.Length());
10171 }
10172
10173 int32_t Current() const {
10174 ASSERT(index_ >= 0);
10175 ASSERT(index_ < end_);
10176 return ch_;
10177 }
10178
10179 bool Next();
10180
10181 private:
10182 const String& str_;
10183 int32_t ch_;
10184 intptr_t index_;
10185 intptr_t end_;
10187 };
10188
10189 intptr_t Length() const { return LengthOf(ptr()); }
10190 static intptr_t LengthOf(StringPtr obj) {
10191 return Smi::Value(obj->untag()->length());
10192 }
10193 static intptr_t length_offset() { return OFFSET_OF(UntaggedString, length_); }
10194
10195 uword Hash() const {
10196 uword result = GetCachedHash(ptr());
10197 if (result != 0) {
10198 return result;
10199 }
10200 result = String::Hash(*this, 0, this->Length());
10201 uword set_hash = SetCachedHashIfNotSet(ptr(), result);
10202 ASSERT(set_hash == result);
10203 return result;
10204 }
10205
10206 static uword Hash(StringPtr raw);
10207
10208 bool HasHash() const {
10209 ASSERT(Smi::New(0) == nullptr);
10210 return GetCachedHash(ptr()) != 0;
10211 }
10212
10213 static intptr_t hash_offset() {
10214#if defined(HASH_IN_OBJECT_HEADER)
10215 COMPILE_ASSERT(UntaggedObject::kHashTagPos % kBitsPerByte == 0);
10216 return OFFSET_OF(UntaggedObject, tags_) +
10217 UntaggedObject::kHashTagPos / kBitsPerByte;
10218#else
10219 return OFFSET_OF(UntaggedString, hash_);
10220#endif
10221 }
10222 static uword Hash(const String& str, intptr_t begin_index, intptr_t len);
10223 static uword Hash(const char* characters, intptr_t len);
10224 static uword Hash(const uint16_t* characters, intptr_t len);
10225 static uword Hash(const int32_t* characters, intptr_t len);
10226 static uword HashRawSymbol(const StringPtr symbol) {
10227 ASSERT(symbol->untag()->IsCanonical());
10228 const uword result = GetCachedHash(symbol);
10229 ASSERT(result != 0);
10230 return result;
10231 }
10232
10233 // Returns the hash of str1 + str2.
10234 static uword HashConcat(const String& str1, const String& str2);
10235
10236 virtual ObjectPtr HashCode() const { return Integer::New(Hash()); }
10237
10238 uint16_t CharAt(intptr_t index) const { return CharAt(ptr(), index); }
10239 static uint16_t CharAt(StringPtr str, intptr_t index);
10240
10241 intptr_t CharSize() const;
10242
10243 inline bool Equals(const String& str) const;
10244
10245 bool Equals(const String& str,
10246 intptr_t begin_index, // begin index on 'str'.
10247 intptr_t len) const; // len on 'str'.
10248
10249 // Compares to a '\0' terminated array of UTF-8 encoded characters.
10250 bool Equals(const char* cstr) const;
10251
10252 // Compares to an array of Latin-1 encoded characters.
10253 bool EqualsLatin1(const uint8_t* characters, intptr_t len) const {
10254 return Equals(characters, len);
10255 }
10256
10257 // Compares to an array of UTF-16 encoded characters.
10258 bool Equals(const uint16_t* characters, intptr_t len) const;
10259
10260 // Compares to an array of UTF-32 encoded characters.
10261 bool Equals(const int32_t* characters, intptr_t len) const;
10262
10263 // True iff this string equals str1 + str2.
10264 bool EqualsConcat(const String& str1, const String& str2) const;
10265
10266 virtual bool OperatorEquals(const Instance& other) const {
10267 return Equals(other);
10268 }
10269 virtual bool CanonicalizeEquals(const Instance& other) const {
10270 return Equals(other);
10271 }
10272 virtual uint32_t CanonicalizeHash() const { return Hash(); }
10273 virtual bool Equals(const Instance& other) const;
10274
10275 intptr_t CompareTo(const String& other) const;
10276
10277 bool StartsWith(const String& other) const {
10278 NoSafepointScope no_safepoint;
10279 return StartsWith(ptr(), other.ptr());
10280 }
10281 static bool StartsWith(StringPtr str, StringPtr prefix);
10282 bool EndsWith(const String& other) const;
10283
10284 // Strings are canonicalized using the symbol table.
10285 // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
10286 virtual InstancePtr CanonicalizeLocked(Thread* thread) const;
10287
10288 bool IsSymbol() const { return ptr()->untag()->IsCanonical(); }
10289
10290 bool IsOneByteString() const {
10291 return ptr()->GetClassId() == kOneByteStringCid;
10292 }
10293
10294 bool IsTwoByteString() const {
10295 return ptr()->GetClassId() == kTwoByteStringCid;
10296 }
10297
10298 char* ToMallocCString() const;
10299 void ToUTF8(uint8_t* utf8_array, intptr_t array_len) const;
10300 static const char* ToCString(Thread* thread, StringPtr ptr);
10301
10302 // Creates a new String object from a C string that is assumed to contain
10303 // UTF-8 encoded characters and '\0' is considered a termination character.
10304 // TODO(7123) - Rename this to FromCString(....).
10305 static StringPtr New(const char* cstr, Heap::Space space = Heap::kNew);
10306
10307 // Creates a new String object from an array of UTF-8 encoded characters.
10308 static StringPtr FromUTF8(const uint8_t* utf8_array,
10309 intptr_t array_len,
10310 Heap::Space space = Heap::kNew);
10311
10312 // Creates a new String object from an array of Latin-1 encoded characters.
10313 static StringPtr FromLatin1(const uint8_t* latin1_array,
10314 intptr_t array_len,
10315 Heap::Space space = Heap::kNew);
10316
10317 // Creates a new String object from an array of UTF-16 encoded characters.
10318 static StringPtr FromUTF16(const uint16_t* utf16_array,
10319 intptr_t array_len,
10320 Heap::Space space = Heap::kNew);
10321
10322 // Creates a new String object from an array of UTF-32 encoded characters.
10323 static StringPtr FromUTF32(const int32_t* utf32_array,
10324 intptr_t array_len,
10325 Heap::Space space = Heap::kNew);
10326
10327 // Create a new String object from another Dart String instance.
10328 static StringPtr New(const String& str, Heap::Space space = Heap::kNew);
10329
10330 // Creates a new External String object using the specified array of
10331 // UTF-8 encoded characters as the external reference.
10332 static StringPtr NewExternal(const uint8_t* utf8_array,
10333 intptr_t array_len,
10334 void* peer,
10335 intptr_t external_allocation_size,
10337 Heap::Space = Heap::kNew);
10338
10339 // Creates a new External String object using the specified array of
10340 // UTF-16 encoded characters as the external reference.
10341 static StringPtr NewExternal(const uint16_t* utf16_array,
10342 intptr_t array_len,
10343 void* peer,
10344 intptr_t external_allocation_size,
10346 Heap::Space = Heap::kNew);
10347
10348 static void Copy(const String& dst,
10349 intptr_t dst_offset,
10350 const uint8_t* characters,
10351 intptr_t len);
10352 static void Copy(const String& dst,
10353 intptr_t dst_offset,
10354 const uint16_t* characters,
10355 intptr_t len);
10356 static void Copy(const String& dst,
10357 intptr_t dst_offset,
10358 const String& src,
10359 intptr_t src_offset,
10360 intptr_t len);
10361
10362 static StringPtr EscapeSpecialCharacters(const String& str);
10363 // Encodes 'str' for use in an Internationalized Resource Identifier (IRI),
10364 // a generalization of URI (percent-encoding). See RFC 3987.
10365 static const char* EncodeIRI(const String& str);
10366 // Returns null if 'str' is not a valid encoding.
10367 static StringPtr DecodeIRI(const String& str);
10368 static StringPtr Concat(const String& str1,
10369 const String& str2,
10370 Heap::Space space = Heap::kNew);
10371 static StringPtr ConcatAll(const Array& strings,
10372 Heap::Space space = Heap::kNew);
10373 // Concat all strings in 'strings' from 'start' to 'end' (excluding).
10374 static StringPtr ConcatAllRange(const Array& strings,
10375 intptr_t start,
10376 intptr_t end,
10377 Heap::Space space = Heap::kNew);
10378
10379 static StringPtr SubString(const String& str,
10380 intptr_t begin_index,
10381 Heap::Space space = Heap::kNew);
10382 static StringPtr SubString(const String& str,
10383 intptr_t begin_index,
10384 intptr_t length,
10385 Heap::Space space = Heap::kNew) {
10386 return SubString(Thread::Current(), str, begin_index, length, space);
10387 }
10388 static StringPtr SubString(Thread* thread,
10389 const String& str,
10390 intptr_t begin_index,
10391 intptr_t length,
10392 Heap::Space space = Heap::kNew);
10393
10394 static StringPtr Transform(int32_t (*mapping)(int32_t ch),
10395 const String& str,
10396 Heap::Space space = Heap::kNew);
10397
10398 static StringPtr ToUpperCase(const String& str,
10399 Heap::Space space = Heap::kNew);
10400 static StringPtr ToLowerCase(const String& str,
10401 Heap::Space space = Heap::kNew);
10402
10403 static StringPtr RemovePrivateKey(const String& name);
10404
10405 static const char* ScrubName(const String& name, bool is_extension = false);
10406 static StringPtr ScrubNameRetainPrivate(const String& name,
10407 bool is_extension = false);
10408
10409 static bool EqualsIgnoringPrivateKey(const String& str1, const String& str2);
10410
10411 static StringPtr NewFormatted(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
10412 static StringPtr NewFormatted(Heap::Space space, const char* format, ...)
10413 PRINTF_ATTRIBUTE(2, 3);
10414 static StringPtr NewFormattedV(const char* format,
10415 va_list args,
10416 Heap::Space space = Heap::kNew);
10417
10418 static bool ParseDouble(const String& str,
10419 intptr_t start,
10420 intptr_t end,
10421 double* result);
10422
10423#if !defined(HASH_IN_OBJECT_HEADER)
10424 static uint32_t GetCachedHash(const StringPtr obj) {
10425 return Smi::Value(obj->untag()->hash_);
10426 }
10427
10428 static uint32_t SetCachedHashIfNotSet(StringPtr obj, uint32_t hash) {
10429 ASSERT(Smi::Value(obj->untag()->hash_) == 0 ||
10430 Smi::Value(obj->untag()->hash_) == static_cast<intptr_t>(hash));
10431 return SetCachedHash(obj, hash);
10432 }
10433 static uint32_t SetCachedHash(StringPtr obj, uint32_t hash) {
10434 obj->untag()->hash_ = Smi::New(hash);
10435 return hash;
10436 }
10437#else
10438 static uint32_t SetCachedHash(StringPtr obj, uint32_t hash) {
10439 return Object::SetCachedHashIfNotSet(obj, hash);
10440 }
10441#endif
10442
10443 protected:
10444 // These two operate on an array of Latin-1 encoded characters.
10445 // They are protected to avoid mistaking Latin-1 for UTF-8, but used
10446 // by friendly templated code (e.g., Symbols).
10447 bool Equals(const uint8_t* characters, intptr_t len) const;
10448 static uword Hash(const uint8_t* characters, intptr_t len);
10449
10450 void SetLength(intptr_t value) const {
10451 // This is only safe because we create a new Smi, which does not cause
10452 // heap allocation.
10453 untag()->set_length(Smi::New(value));
10454 }
10455
10456 void SetHash(intptr_t value) const {
10457 const intptr_t hash_set = SetCachedHashIfNotSet(ptr(), value);
10458 ASSERT(hash_set == value);
10459 }
10460
10462
10463 friend class Class;
10464 friend class Symbols;
10465 friend class StringSlice; // SetHash
10466 template <typename CharType>
10467 friend class CharArray; // SetHash
10468 friend class ConcatString; // SetHash
10469 friend class OneByteString;
10470 friend class TwoByteString;
10472 friend class RODataSerializationCluster; // SetHash
10473 friend class Pass2Visitor; // Stack "handle"
10474};
10475
10476// Synchronize with implementation in compiler (intrinsifier).
10478 public:
10479 StringHasher() : hash_(0) {}
10480 void Add(uint16_t code_unit) { hash_ = CombineHashes(hash_, code_unit); }
10481 void Add(const uint8_t* code_units, intptr_t len) {
10482 while (len > 0) {
10483 Add(*code_units);
10484 code_units++;
10485 len--;
10486 }
10487 }
10488 void Add(const uint16_t* code_units, intptr_t len) {
10489 while (len > 0) {
10490 Add(LoadUnaligned(code_units));
10491 code_units++;
10492 len--;
10493 }
10494 }
10495 void Add(const String& str, intptr_t begin_index, intptr_t len);
10496 intptr_t Finalize() { return FinalizeHash(hash_, String::kHashBits); }
10497
10498 private:
10499 uint32_t hash_;
10500};
10501
10502class OneByteString : public AllStatic {
10503 public:
10504 static uint16_t CharAt(const String& str, intptr_t index) {
10505 ASSERT(str.IsOneByteString());
10506 return OneByteString::CharAt(static_cast<OneByteStringPtr>(str.ptr()),
10507 index);
10508 }
10509
10510 static uint16_t CharAt(OneByteStringPtr str, intptr_t index) {
10511 ASSERT(index >= 0 && index < String::LengthOf(str));
10512 return str->untag()->data()[index];
10513 }
10514
10515 static void SetCharAt(const String& str, intptr_t index, uint8_t code_unit) {
10516 NoSafepointScope no_safepoint;
10517 *CharAddr(str, index) = code_unit;
10518 }
10519 static OneByteStringPtr EscapeSpecialCharacters(const String& str);
10520 // We use the same maximum elements for all strings.
10521 static constexpr intptr_t kBytesPerElement = 1;
10522 static constexpr intptr_t kMaxElements = String::kMaxElements;
10523 static constexpr intptr_t kMaxNewSpaceElements =
10524 (kNewAllocatableSize - sizeof(UntaggedOneByteString)) / kBytesPerElement;
10525
10527 static intptr_t elements_start_offset() {
10528 return sizeof(UntaggedOneByteString);
10529 }
10530 static constexpr intptr_t kElementSize = kBytesPerElement;
10531 };
10532
10533 static intptr_t data_offset() {
10535 }
10536
10537 static intptr_t UnroundedSize(OneByteStringPtr str) {
10538 return UnroundedSize(Smi::Value(str->untag()->length()));
10539 }
10540 static intptr_t UnroundedSize(intptr_t len) {
10541 return sizeof(UntaggedOneByteString) + (len * kBytesPerElement);
10542 }
10543 static intptr_t InstanceSize() {
10544 ASSERT(sizeof(UntaggedOneByteString) ==
10546 return 0;
10547 }
10548 static intptr_t InstanceSize(intptr_t len) {
10550 ASSERT(0 <= len && len <= kMaxElements);
10551 return String::RoundedAllocationSize(UnroundedSize(len));
10552 }
10553
10554 static OneByteStringPtr New(intptr_t len, Heap::Space space);
10555 static OneByteStringPtr New(const char* c_string,
10556 Heap::Space space = Heap::kNew) {
10557 return New(reinterpret_cast<const uint8_t*>(c_string), strlen(c_string),
10558 space);
10559 }
10560 static OneByteStringPtr New(const uint8_t* characters,
10561 intptr_t len,
10562 Heap::Space space);
10563 static OneByteStringPtr New(const uint16_t* characters,
10564 intptr_t len,
10565 Heap::Space space);
10566 static OneByteStringPtr New(const int32_t* characters,
10567 intptr_t len,
10568 Heap::Space space);
10569 static OneByteStringPtr New(const String& str, Heap::Space space);
10570 // 'other' must be OneByteString.
10571 static OneByteStringPtr New(const String& other_one_byte_string,
10572 intptr_t other_start_index,
10573 intptr_t other_len,
10574 Heap::Space space);
10575
10576 static OneByteStringPtr New(const TypedDataBase& other_typed_data,
10577 intptr_t other_start_index,
10578 intptr_t other_len,
10579 Heap::Space space = Heap::kNew);
10580
10581 static OneByteStringPtr Concat(const String& str1,
10582 const String& str2,
10583 Heap::Space space);
10584 static OneByteStringPtr ConcatAll(const Array& strings,
10585 intptr_t start,
10586 intptr_t end,
10587 intptr_t len,
10588 Heap::Space space);
10589
10590 static OneByteStringPtr Transform(int32_t (*mapping)(int32_t ch),
10591 const String& str,
10592 Heap::Space space);
10593
10594 // High performance version of substring for one-byte strings.
10595 // "str" must be OneByteString.
10596 static OneByteStringPtr SubStringUnchecked(const String& str,
10597 intptr_t begin_index,
10598 intptr_t length,
10599 Heap::Space space);
10600
10601 static const ClassId kClassId = kOneByteStringCid;
10602
10603 static OneByteStringPtr null() {
10604 return static_cast<OneByteStringPtr>(Object::null());
10605 }
10606
10607 private:
10608 static OneByteStringPtr raw(const String& str) {
10609 return static_cast<OneByteStringPtr>(str.ptr());
10610 }
10611
10612 static const UntaggedOneByteString* untag(const String& str) {
10613 return reinterpret_cast<const UntaggedOneByteString*>(str.untag());
10614 }
10615
10616 static uint8_t* CharAddr(const String& str, intptr_t index) {
10617 ASSERT((index >= 0) && (index < str.Length()));
10618 ASSERT(str.IsOneByteString());
10619 return &str.UnsafeMutableNonPointer(untag(str)->data())[index];
10620 }
10621
10622 static uint8_t* DataStart(const String& str) {
10623 ASSERT(str.IsOneByteString());
10624 return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
10625 }
10626
10628
10629 friend class Class;
10631 friend class ImageWriter;
10632 friend class String;
10633 friend class StringHasher;
10634 friend class Symbols;
10635 friend class Utf8;
10637 friend class Deserializer;
10638 friend class JSONWriter;
10639};
10640
10641class TwoByteString : public AllStatic {
10642 public:
10643 static uint16_t CharAt(const String& str, intptr_t index) {
10644 ASSERT(str.IsTwoByteString());
10645 return TwoByteString::CharAt(static_cast<TwoByteStringPtr>(str.ptr()),
10646 index);
10647 }
10648
10649 static uint16_t CharAt(TwoByteStringPtr str, intptr_t index) {
10650 ASSERT(index >= 0 && index < String::LengthOf(str));
10651 return str->untag()->data()[index];
10652 }
10653
10654 static void SetCharAt(const String& str, intptr_t index, uint16_t ch) {
10655 NoSafepointScope no_safepoint;
10656 *CharAddr(str, index) = ch;
10657 }
10658
10659 static TwoByteStringPtr EscapeSpecialCharacters(const String& str);
10660
10661 // We use the same maximum elements for all strings.
10662 static constexpr intptr_t kBytesPerElement = 2;
10663 static constexpr intptr_t kMaxElements = String::kMaxElements;
10664 static constexpr intptr_t kMaxNewSpaceElements =
10665 (kNewAllocatableSize - sizeof(UntaggedTwoByteString)) / kBytesPerElement;
10666
10668 static intptr_t elements_start_offset() {
10669 return sizeof(UntaggedTwoByteString);
10670 }
10671 static constexpr intptr_t kElementSize = kBytesPerElement;
10672 };
10673
10674 static intptr_t data_offset() {
10676 }
10677 static intptr_t UnroundedSize(TwoByteStringPtr str) {
10678 return UnroundedSize(Smi::Value(str->untag()->length()));
10679 }
10680 static intptr_t UnroundedSize(intptr_t len) {
10681 return sizeof(UntaggedTwoByteString) + (len * kBytesPerElement);
10682 }
10683 static intptr_t InstanceSize() {
10684 ASSERT(sizeof(UntaggedTwoByteString) ==
10686 return 0;
10687 }
10688 static intptr_t InstanceSize(intptr_t len) {
10690 ASSERT(0 <= len && len <= kMaxElements);
10691 return String::RoundedAllocationSize(UnroundedSize(len));
10692 }
10693
10694 static TwoByteStringPtr New(intptr_t len, Heap::Space space);
10695 static TwoByteStringPtr New(const uint16_t* characters,
10696 intptr_t len,
10697 Heap::Space space);
10698 static TwoByteStringPtr New(intptr_t utf16_len,
10699 const int32_t* characters,
10700 intptr_t len,
10701 Heap::Space space);
10702 static TwoByteStringPtr New(const String& str, Heap::Space space);
10703
10704 static TwoByteStringPtr New(const TypedDataBase& other_typed_data,
10705 intptr_t other_start_index,
10706 intptr_t other_len,
10707 Heap::Space space = Heap::kNew);
10708
10709 static TwoByteStringPtr Concat(const String& str1,
10710 const String& str2,
10711 Heap::Space space);
10712 static TwoByteStringPtr ConcatAll(const Array& strings,
10713 intptr_t start,
10714 intptr_t end,
10715 intptr_t len,
10716 Heap::Space space);
10717
10718 static TwoByteStringPtr Transform(int32_t (*mapping)(int32_t ch),
10719 const String& str,
10720 Heap::Space space);
10721
10722 static TwoByteStringPtr null() {
10723 return static_cast<TwoByteStringPtr>(Object::null());
10724 }
10725
10726 static const ClassId kClassId = kTwoByteStringCid;
10727
10728 private:
10729 static TwoByteStringPtr raw(const String& str) {
10730 return static_cast<TwoByteStringPtr>(str.ptr());
10731 }
10732
10733 static const UntaggedTwoByteString* untag(const String& str) {
10734 return reinterpret_cast<const UntaggedTwoByteString*>(str.untag());
10735 }
10736
10737 static uint16_t* CharAddr(const String& str, intptr_t index) {
10738 ASSERT((index >= 0) && (index < str.Length()));
10739 ASSERT(str.IsTwoByteString());
10740 return &str.UnsafeMutableNonPointer(untag(str)->data())[index];
10741 }
10742
10743 // Use this instead of CharAddr(0). It will not assert that the index is <
10744 // length.
10745 static uint16_t* DataStart(const String& str) {
10746 ASSERT(str.IsTwoByteString());
10747 return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
10748 }
10749
10751
10752 friend class Class;
10754 friend class ImageWriter;
10755 friend class String;
10756 friend class StringHasher;
10757 friend class Symbols;
10759 friend class JSONWriter;
10760};
10761
10762// Matches null_patch.dart / bool_patch.dart.
10763static constexpr intptr_t kNullIdentityHash = 2011;
10764static constexpr intptr_t kTrueIdentityHash = 1231;
10765static constexpr intptr_t kFalseIdentityHash = 1237;
10766
10767// Class Bool implements Dart core class bool.
10768class Bool : public Instance {
10769 public:
10770 bool value() const { return untag()->value_; }
10771
10772 static intptr_t InstanceSize() {
10773 return RoundedAllocationSize(sizeof(UntaggedBool));
10774 }
10775
10776 static const Bool& True() { return Object::bool_true(); }
10777
10778 static const Bool& False() { return Object::bool_false(); }
10779
10780 static const Bool& Get(bool value) {
10781 return value ? Bool::True() : Bool::False();
10782 }
10783
10784 virtual uint32_t CanonicalizeHash() const {
10785 return ptr() == True().ptr() ? kTrueIdentityHash : kFalseIdentityHash;
10786 }
10787
10788 private:
10790 friend class Class;
10791 friend class Object; // To initialize the true and false values.
10792};
10793
10794class Array : public Instance {
10795 public:
10796 // Returns `true` if we use card marking for arrays of length [array_length].
10797 static constexpr bool UseCardMarkingForAllocation(
10798 const intptr_t array_length) {
10799 return Array::InstanceSize(array_length) > kNewAllocatableSize;
10800 }
10801
10802 // WB invariant restoration code only applies to arrives which have at most
10803 // this many elements. Consequently WB elimination code should not eliminate
10804 // WB on arrays of larger lengths across instructions that can cause GC.
10805 // Note: we also can't restore WB invariant for arrays which use card marking.
10806 static constexpr intptr_t kMaxLengthForWriteBarrierElimination = 8;
10807
10808 intptr_t Length() const { return LengthOf(ptr()); }
10809 static intptr_t LengthOf(const ArrayPtr array) {
10810 return Smi::Value(array->untag()->length());
10811 }
10812
10813 static intptr_t length_offset() { return OFFSET_OF(UntaggedArray, length_); }
10814 static intptr_t data_offset() {
10816 }
10817 static intptr_t element_offset(intptr_t index) {
10819 kBytesPerElement * index;
10820 }
10821 static intptr_t index_at_offset(intptr_t offset_in_bytes) {
10822 intptr_t index = (offset_in_bytes - data_offset()) / kBytesPerElement;
10823 ASSERT(index >= 0);
10824 return index;
10825 }
10826
10828 static intptr_t elements_start_offset() { return Array::data_offset(); }
10829
10830 static constexpr intptr_t kElementSize = kCompressedWordSize;
10831 };
10832
10833 static bool Equals(ArrayPtr a, ArrayPtr b) {
10834 if (a == b) return true;
10835 if (a->IsRawNull() || b->IsRawNull()) return false;
10836 if (a->untag()->length() != b->untag()->length()) return false;
10837 if (a->untag()->type_arguments() != b->untag()->type_arguments()) {
10838 return false;
10839 }
10840 const intptr_t length = LengthOf(a);
10841 return memcmp(a->untag()->data(), b->untag()->data(),
10842 kBytesPerElement * length) == 0;
10843 }
10844 bool Equals(const Array& other) const {
10845 NoSafepointScope scope;
10846 return Equals(ptr(), other.ptr());
10847 }
10848
10849 static CompressedObjectPtr* DataOf(ArrayPtr array) {
10850 return array->untag()->data();
10851 }
10852
10853 template <std::memory_order order = std::memory_order_relaxed>
10854 ObjectPtr At(intptr_t index) const {
10855 return untag()->element<order>(index);
10856 }
10857 template <std::memory_order order = std::memory_order_relaxed>
10858 void SetAt(intptr_t index, const Object& value) const {
10859 untag()->set_element<order>(index, value.ptr());
10860 }
10861 template <std::memory_order order = std::memory_order_relaxed>
10862 void SetAt(intptr_t index, const Object& value, Thread* thread) const {
10863 untag()->set_element<order>(index, value.ptr(), thread);
10864 }
10865
10866 // Access to the array with acquire release semantics.
10867 ObjectPtr AtAcquire(intptr_t index) const {
10868 return untag()->element<std::memory_order_acquire>(index);
10869 }
10870 void SetAtRelease(intptr_t index, const Object& value) const {
10871 untag()->set_element<std::memory_order_release>(index, value.ptr());
10872 }
10873
10874 bool IsImmutable() const { return ptr()->GetClassId() == kImmutableArrayCid; }
10875
10876 // Position of element type in type arguments.
10877 static constexpr intptr_t kElementTypeTypeArgPos = 0;
10878
10879 virtual TypeArgumentsPtr GetTypeArguments() const {
10880 return untag()->type_arguments();
10881 }
10882 virtual void SetTypeArguments(const TypeArguments& value) const {
10883 // An Array is raw or takes one type argument. However, its type argument
10884 // vector may be longer than 1 due to a type optimization reusing the type
10885 // argument vector of the instantiator.
10886 ASSERT(value.IsNull() ||
10887 ((value.Length() >= 1) &&
10888 value.IsInstantiated() /*&& value.IsCanonical()*/));
10889 // TODO(asiva): Values read from a message snapshot are not properly marked
10890 // as canonical. See for example tests/isolate/mandel_isolate_test.dart.
10891 StoreArrayPointer(&untag()->type_arguments_, value.ptr());
10892 }
10893
10894 virtual bool CanonicalizeEquals(const Instance& other) const;
10895 virtual uint32_t CanonicalizeHash() const;
10896
10897 static constexpr intptr_t kBytesPerElement = ArrayTraits::kElementSize;
10898 static constexpr intptr_t kMaxElements = kSmiMax / kBytesPerElement;
10899 static constexpr intptr_t kMaxNewSpaceElements =
10900 (kNewAllocatableSize - sizeof(UntaggedArray)) / kBytesPerElement;
10901
10902 static intptr_t type_arguments_offset() {
10903 return OFFSET_OF(UntaggedArray, type_arguments_);
10904 }
10905
10906 static constexpr bool IsValidLength(intptr_t len) {
10907 return 0 <= len && len <= kMaxElements;
10908 }
10909
10910 static intptr_t InstanceSize() {
10911 ASSERT(sizeof(UntaggedArray) ==
10913 return 0;
10914 }
10915
10916 static constexpr intptr_t UnroundedSize(intptr_t len) {
10917 // Ensure that variable length data is not adding to the object length.
10918 ASSERT(sizeof(UntaggedArray) ==
10919 (sizeof(UntaggedInstance) + (2 * kBytesPerElement)));
10920 ASSERT(IsValidLength(len));
10921 return sizeof(UntaggedArray) + (len * kBytesPerElement);
10922 }
10923 static constexpr intptr_t InstanceSize(intptr_t len) {
10924 return RoundedAllocationSize(UnroundedSize(len));
10925 }
10926
10927 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
10928
10929 // Make the array immutable to Dart code by switching the class pointer
10930 // to ImmutableArray.
10931 void MakeImmutable() const;
10932
10933 static ArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew) {
10934 return New(kArrayCid, len, space);
10935 }
10936 // The result's type arguments and elements are GC-safe but not initialized to
10937 // null.
10938 static ArrayPtr NewUninitialized(intptr_t len,
10939 Heap::Space space = Heap::kNew) {
10940 return NewUninitialized(kArrayCid, len, space);
10941 }
10942 static ArrayPtr New(intptr_t len,
10943 const AbstractType& element_type,
10944 Heap::Space space = Heap::kNew);
10945
10946 // Creates and returns a new array with 'new_length'. Copies all elements from
10947 // 'source' to the new array. 'new_length' must be greater than or equal to
10948 // 'source.Length()'. 'source' can be null.
10949 static ArrayPtr Grow(const Array& source,
10950 intptr_t new_length,
10951 Heap::Space space = Heap::kNew);
10952
10953 // Truncates the array to a given length. 'new_length' must be less than
10954 // or equal to 'source.Length()'. The remaining unused part of the array is
10955 // marked as an Array object or a regular Object so that it can be traversed
10956 // during garbage collection.
10957 void Truncate(intptr_t new_length) const;
10958
10959 // Return an Array object that contains all the elements currently present
10960 // in the specified Growable Object Array. This is done by first truncating
10961 // the Growable Object Array's backing array to the currently used size and
10962 // returning the truncated backing array.
10963 // The backing array of the original Growable Object Array is
10964 // set to an empty array.
10965 // If the unique parameter is false, the function is allowed to return
10966 // a shared Array instance.
10967 static ArrayPtr MakeFixedLength(const GrowableObjectArray& growable_array,
10968 bool unique = false);
10969
10970 ArrayPtr Slice(intptr_t start, intptr_t count, bool with_type_argument) const;
10971 ArrayPtr Copy() const {
10972 return Slice(0, Length(), /*with_type_argument=*/true);
10973 }
10974
10975 protected:
10976 static ArrayPtr New(intptr_t class_id,
10977 intptr_t len,
10978 Heap::Space space = Heap::kNew);
10979 static ArrayPtr NewUninitialized(intptr_t class_id,
10980 intptr_t len,
10981 Heap::Space space = Heap::kNew);
10982
10983 private:
10984 CompressedObjectPtr const* ObjectAddr(intptr_t index) const {
10985 // TODO(iposva): Determine if we should throw an exception here.
10986 ASSERT((index >= 0) && (index < Length()));
10987 return &untag()->data()[index];
10988 }
10989
10990 void SetLength(intptr_t value) const { untag()->set_length(Smi::New(value)); }
10991 void SetLengthRelease(intptr_t value) const {
10992 untag()->set_length<std::memory_order_release>(Smi::New(value));
10993 }
10994
10995 template <typename type,
10996 std::memory_order order = std::memory_order_relaxed,
10997 typename value_type>
10998 void StoreArrayPointer(type const* addr, value_type value) const {
10999 ptr()->untag()->StoreArrayPointer<type, order, value_type>(addr, value);
11000 }
11001
11002 FINAL_HEAP_OBJECT_IMPLEMENTATION(Array, Instance);
11003 friend class Class;
11004 friend class ImmutableArray;
11005 friend class Object;
11006 friend class String;
11008};
11009
11011 public:
11012 static constexpr bool ContainsCompressedPointers() {
11013 return Array::ContainsCompressedPointers();
11014 }
11015
11016 static ImmutableArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);
11017
11018 static const ClassId kClassId = kImmutableArrayCid;
11019
11020 static intptr_t InstanceSize() { return Array::InstanceSize(); }
11021
11022 static intptr_t InstanceSize(intptr_t len) {
11023 return Array::InstanceSize(len);
11024 }
11025
11026 private:
11027 static intptr_t NextFieldOffset() {
11028 // Indicates this class cannot be extended by dart code.
11029 return -kWordSize;
11030 }
11031
11032 static ImmutableArrayPtr raw(const Array& array) {
11033 return static_cast<ImmutableArrayPtr>(array.ptr());
11034 }
11035
11036 friend class Class;
11037};
11038
11040 public:
11041 intptr_t Capacity() const {
11042 NoSafepointScope no_safepoint;
11043 ASSERT(!IsNull());
11044 return Smi::Value(DataArray()->length());
11045 }
11046 intptr_t Length() const {
11047 ASSERT(!IsNull());
11048 return Smi::Value(untag()->length());
11049 }
11050 void SetLength(intptr_t value) const {
11051 // This is only safe because we create a new Smi, which does not cause
11052 // heap allocation.
11053 untag()->set_length(Smi::New(value));
11054 }
11055
11056 ArrayPtr data() const { return untag()->data(); }
11057 void SetData(const Array& value) const { untag()->set_data(value.ptr()); }
11058
11059 ObjectPtr At(intptr_t index) const {
11060 NoSafepointScope no_safepoint;
11061 ASSERT(!IsNull());
11062 ASSERT(index < Length());
11063 return data()->untag()->element(index);
11064 }
11065 void SetAt(intptr_t index, const Object& value) const {
11066 ASSERT(!IsNull());
11067 ASSERT(index < Length());
11068
11069 // TODO(iposva): Add storing NoSafepointScope.
11070 data()->untag()->set_element(index, value.ptr());
11071 }
11072
11073 void Add(const Object& value, Heap::Space space = Heap::kNew) const;
11074
11075 void Grow(intptr_t new_capacity, Heap::Space space = Heap::kNew) const;
11076 ObjectPtr RemoveLast() const;
11077
11078 virtual TypeArgumentsPtr GetTypeArguments() const {
11079 return untag()->type_arguments();
11080 }
11081 virtual void SetTypeArguments(const TypeArguments& value) const {
11082 // A GrowableObjectArray is raw or takes one type argument. However, its
11083 // type argument vector may be longer than 1 due to a type optimization
11084 // reusing the type argument vector of the instantiator.
11085 ASSERT(value.IsNull() || ((value.Length() >= 1) && value.IsInstantiated() &&
11086 value.IsCanonical()));
11087
11088 untag()->set_type_arguments(value.ptr());
11089 }
11090
11091 // We don't expect a growable object array to be canonicalized.
11092 virtual bool CanonicalizeEquals(const Instance& other) const {
11093 UNREACHABLE();
11094 return false;
11095 }
11096
11097 // We don't expect a growable object array to be canonicalized.
11098 virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
11099 UNREACHABLE();
11100 return Instance::null();
11101 }
11102
11103 static intptr_t type_arguments_offset() {
11104 return OFFSET_OF(UntaggedGrowableObjectArray, type_arguments_);
11105 }
11106
11107 static intptr_t length_offset() {
11108 return OFFSET_OF(UntaggedGrowableObjectArray, length_);
11109 }
11110 static intptr_t data_offset() {
11112 }
11113
11114 static intptr_t InstanceSize() {
11115 return RoundedAllocationSize(sizeof(UntaggedGrowableObjectArray));
11116 }
11117
11118 static GrowableObjectArrayPtr New(Heap::Space space = Heap::kNew) {
11119 return New(kDefaultInitialCapacity, space);
11120 }
11121 static GrowableObjectArrayPtr New(intptr_t capacity,
11122 Heap::Space space = Heap::kNew);
11123 static GrowableObjectArrayPtr New(const Array& array,
11124 Heap::Space space = Heap::kNew);
11125
11126 static SmiPtr NoSafepointLength(const GrowableObjectArrayPtr array) {
11127 return array->untag()->length();
11128 }
11129
11130 static ArrayPtr NoSafepointData(const GrowableObjectArrayPtr array) {
11131 return array->untag()->data();
11132 }
11133
11134 private:
11135 UntaggedArray* DataArray() const { return data()->untag(); }
11136
11137 static constexpr int kDefaultInitialCapacity = 0;
11138
11139 FINAL_HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray, Instance);
11140 friend class Array;
11141 friend class Class;
11142};
11143
11144class Float32x4 : public Instance {
11145 public:
11146 static Float32x4Ptr New(float value0,
11147 float value1,
11148 float value2,
11149 float value3,
11150 Heap::Space space = Heap::kNew);
11151 static Float32x4Ptr New(simd128_value_t value,
11152 Heap::Space space = Heap::kNew);
11153
11154 float x() const;
11155 float y() const;
11156 float z() const;
11157 float w() const;
11158
11159 void set_x(float x) const;
11160 void set_y(float y) const;
11161 void set_z(float z) const;
11162 void set_w(float w) const;
11163
11164 simd128_value_t value() const;
11165 void set_value(simd128_value_t value) const;
11166
11167 static intptr_t InstanceSize() {
11168 return RoundedAllocationSize(sizeof(UntaggedFloat32x4));
11169 }
11170
11171 static intptr_t value_offset() {
11172 return OFFSET_OF(UntaggedFloat32x4, value_);
11173 }
11174
11175 virtual bool CanonicalizeEquals(const Instance& other) const;
11176 virtual uint32_t CanonicalizeHash() const;
11177
11178 private:
11180 friend class Class;
11181};
11182
11183class Int32x4 : public Instance {
11184 public:
11185 static Int32x4Ptr New(int32_t value0,
11186 int32_t value1,
11187 int32_t value2,
11188 int32_t value3,
11189 Heap::Space space = Heap::kNew);
11190 static Int32x4Ptr New(simd128_value_t value, Heap::Space space = Heap::kNew);
11191
11192 int32_t x() const;
11193 int32_t y() const;
11194 int32_t z() const;
11195 int32_t w() const;
11196
11197 void set_x(int32_t x) const;
11198 void set_y(int32_t y) const;
11199 void set_z(int32_t z) const;
11200 void set_w(int32_t w) const;
11201
11202 simd128_value_t value() const;
11203 void set_value(simd128_value_t value) const;
11204
11205 static intptr_t InstanceSize() {
11206 return RoundedAllocationSize(sizeof(UntaggedInt32x4));
11207 }
11208
11209 static intptr_t value_offset() { return OFFSET_OF(UntaggedInt32x4, value_); }
11210
11211 virtual bool CanonicalizeEquals(const Instance& other) const;
11212 virtual uint32_t CanonicalizeHash() const;
11213
11214 private:
11216 friend class Class;
11217};
11218
11219class Float64x2 : public Instance {
11220 public:
11221 static Float64x2Ptr New(double value0,
11222 double value1,
11223 Heap::Space space = Heap::kNew);
11224 static Float64x2Ptr New(simd128_value_t value,
11225 Heap::Space space = Heap::kNew);
11226
11227 double x() const;
11228 double y() const;
11229
11230 void set_x(double x) const;
11231 void set_y(double y) const;
11232
11233 simd128_value_t value() const;
11234 void set_value(simd128_value_t value) const;
11235
11236 static intptr_t InstanceSize() {
11237 return RoundedAllocationSize(sizeof(UntaggedFloat64x2));
11238 }
11239
11240 static intptr_t value_offset() {
11241 return OFFSET_OF(UntaggedFloat64x2, value_);
11242 }
11243
11244 virtual bool CanonicalizeEquals(const Instance& other) const;
11245 virtual uint32_t CanonicalizeHash() const;
11246
11247 private:
11249 friend class Class;
11250};
11251
11252// Packed representation of record shape (number of fields and field names).
11254 enum {
11255 kNumFieldsBits = 16,
11256 kFieldNamesIndexBits = kSmiBits - kNumFieldsBits,
11257 };
11259 using FieldNamesIndexBitField = BitField<intptr_t,
11260 intptr_t,
11261 NumFieldsBitField::kNextBit,
11262 kFieldNamesIndexBits>;
11263
11264 public:
11265 static constexpr intptr_t kNumFieldsMask = NumFieldsBitField::mask();
11266 static constexpr intptr_t kMaxNumFields = kNumFieldsMask;
11267 static constexpr intptr_t kFieldNamesIndexMask =
11268 FieldNamesIndexBitField::mask();
11269 static constexpr intptr_t kFieldNamesIndexShift =
11270 FieldNamesIndexBitField::shift();
11271 static constexpr intptr_t kMaxFieldNamesIndex = kFieldNamesIndexMask;
11272
11273 explicit RecordShape(intptr_t value) : value_(value) { ASSERT(value_ >= 0); }
11274 explicit RecordShape(SmiPtr smi_value) : value_(Smi::Value(smi_value)) {
11275 ASSERT(value_ >= 0);
11276 }
11277 RecordShape(intptr_t num_fields, intptr_t field_names_index)
11278 : value_(NumFieldsBitField::encode(num_fields) |
11279 FieldNamesIndexBitField::encode(field_names_index)) {
11280 ASSERT(value_ >= 0);
11281 }
11282 static RecordShape ForUnnamed(intptr_t num_fields) {
11283 return RecordShape(num_fields, 0);
11284 }
11285
11286 bool HasNamedFields() const { return field_names_index() != 0; }
11287
11288 intptr_t num_fields() const { return NumFieldsBitField::decode(value_); }
11289
11290 intptr_t field_names_index() const {
11291 return FieldNamesIndexBitField::decode(value_);
11292 }
11293
11294 SmiPtr AsSmi() const { return Smi::New(value_); }
11295
11296 intptr_t AsInt() const { return value_; }
11297
11298 bool operator==(const RecordShape& other) const {
11299 return value_ == other.value_;
11300 }
11301 bool operator!=(const RecordShape& other) const {
11302 return value_ != other.value_;
11303 }
11304
11305 // Registers record shape with [num_fields] and [field_names] in the current
11306 // isolate group.
11307 static RecordShape Register(Thread* thread,
11308 intptr_t num_fields,
11309 const Array& field_names);
11310
11311 // Retrieves an array of field names.
11312 ArrayPtr GetFieldNames(Thread* thread) const;
11313
11314 private:
11315 intptr_t value_;
11316
11318};
11319
11320// A RecordType represents the type of a record. It describes
11321// number of named and positional fields, field types and
11322// names of the named fields.
11323class RecordType : public AbstractType {
11324 public:
11325 virtual bool HasTypeClass() const { return false; }
11326 RecordTypePtr ToNullability(Nullability value, Heap::Space space) const;
11327 virtual classid_t type_class_id() const { return kIllegalCid; }
11328 virtual bool IsInstantiated(
11329 Genericity genericity = kAny,
11330 intptr_t num_free_fun_type_params = kAllFree) const;
11331 virtual bool IsEquivalent(
11332 const Instance& other,
11333 TypeEquality kind,
11334 FunctionTypeMapping* function_type_equivalence = nullptr) const;
11335
11336 virtual AbstractTypePtr InstantiateFrom(
11337 const TypeArguments& instantiator_type_arguments,
11338 const TypeArguments& function_type_arguments,
11339 intptr_t num_free_fun_type_params,
11340 Heap::Space space,
11341 FunctionTypeMapping* function_type_mapping = nullptr,
11342 intptr_t num_parent_type_args_adjustment = 0) const;
11343
11344 virtual AbstractTypePtr UpdateFunctionTypes(
11345 intptr_t num_parent_type_args_adjustment,
11346 intptr_t num_free_fun_type_params,
11347 Heap::Space space,
11348 FunctionTypeMapping* function_type_mapping) const;
11349
11350 virtual AbstractTypePtr Canonicalize(Thread* thread) const;
11351 virtual void EnumerateURIs(URIs* uris) const;
11352 virtual void PrintName(NameVisibility visibility,
11353 BaseTextBuffer* printer) const;
11354
11355 virtual uword ComputeHash() const;
11356
11357 bool IsSubtypeOf(
11358 const RecordType& other,
11359 Heap::Space space,
11360 FunctionTypeMapping* function_type_equivalence = nullptr) const;
11361
11362 RecordShape shape() const { return RecordShape(untag()->shape()); }
11363
11364 ArrayPtr field_types() const { return untag()->field_types(); }
11365
11366 AbstractTypePtr FieldTypeAt(intptr_t index) const;
11367 void SetFieldTypeAt(intptr_t index, const AbstractType& value) const;
11368
11369 // Names of the named fields, sorted.
11370 ArrayPtr GetFieldNames(Thread* thread) const;
11371
11372 intptr_t NumFields() const;
11373
11374 void Print(NameVisibility name_visibility, BaseTextBuffer* printer) const;
11375
11376 static intptr_t InstanceSize() {
11377 return RoundedAllocationSize(sizeof(UntaggedRecordType));
11378 }
11379
11380 static RecordTypePtr New(RecordShape shape,
11381 const Array& field_types,
11382 Nullability nullability = Nullability::kLegacy,
11383 Heap::Space space = Heap::kOld);
11384
11385 private:
11386 void set_shape(RecordShape shape) const;
11387 void set_field_types(const Array& value) const;
11388
11389 static RecordTypePtr New(Heap::Space space);
11390
11392 friend class Class;
11393 friend class ClassFinalizer;
11394 friend class Record;
11395};
11396
11397class Record : public Instance {
11398 public:
11399 intptr_t num_fields() const { return NumFields(ptr()); }
11400 static intptr_t NumFields(RecordPtr ptr) {
11401 return RecordShape(ptr->untag()->shape()).num_fields();
11402 }
11403
11404 RecordShape shape() const { return RecordShape(untag()->shape()); }
11405 static intptr_t shape_offset() { return OFFSET_OF(UntaggedRecord, shape_); }
11406
11407 ObjectPtr FieldAt(intptr_t field_index) const {
11408 return untag()->field(field_index);
11409 }
11410 void SetFieldAt(intptr_t field_index, const Object& value) const {
11411 untag()->set_field(field_index, value.ptr());
11412 }
11413
11414 static constexpr intptr_t kBytesPerElement = kCompressedWordSize;
11415 static constexpr intptr_t kMaxElements = RecordShape::kMaxNumFields;
11416
11418 static intptr_t elements_start_offset() { return sizeof(UntaggedRecord); }
11419 static constexpr intptr_t kElementSize = kBytesPerElement;
11420 };
11421
11422 static intptr_t field_offset(intptr_t index) {
11424 kBytesPerElement * index;
11425 }
11426 static intptr_t field_index_at_offset(intptr_t offset_in_bytes) {
11427 const intptr_t index =
11428 (offset_in_bytes - OFFSET_OF_RETURNED_VALUE(UntaggedRecord, data)) /
11429 kBytesPerElement;
11430 ASSERT(index >= 0);
11431 return index;
11432 }
11433
11434 static intptr_t InstanceSize() {
11435 ASSERT(sizeof(UntaggedRecord) ==
11437 return 0;
11438 }
11439
11440 static intptr_t InstanceSize(intptr_t num_fields) {
11441 return RoundedAllocationSize(sizeof(UntaggedRecord) +
11442 (num_fields * kBytesPerElement));
11443 }
11444
11445 static RecordPtr New(RecordShape shape, Heap::Space space = Heap::kNew);
11446
11447 virtual bool CanonicalizeEquals(const Instance& other) const;
11448 virtual uint32_t CanonicalizeHash() const;
11449 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
11450
11451 // Returns RecordType representing runtime type of this record instance.
11452 // It is not created eagerly when record instance is allocated because
11453 // it depends on runtime types of values if its fields, which can be
11454 // quite expensive to query.
11455 RecordTypePtr GetRecordType() const;
11456
11457 // Parses positional field name and return its index,
11458 // or -1 if [field_name] is not a valid positional field name.
11459 static intptr_t GetPositionalFieldIndexFromFieldName(
11460 const String& field_name);
11461
11462 // Returns index of the field with given name, or -1
11463 // if such field doesn't exist.
11464 // Supports positional field names ("$1", "$2", etc).
11465 intptr_t GetFieldIndexByName(Thread* thread, const String& field_name) const;
11466
11467 ArrayPtr GetFieldNames(Thread* thread) const {
11468 return shape().GetFieldNames(thread);
11469 }
11470
11471 private:
11473 friend class Class;
11474 friend class Object;
11475};
11476
11477class PointerBase : public Instance {
11478 public:
11479 static intptr_t data_offset() {
11480 return OFFSET_OF(UntaggedPointerBase, data_);
11481 }
11482};
11483
11485 public:
11486 static intptr_t length_offset() {
11487 return OFFSET_OF(UntaggedTypedDataBase, length_);
11488 }
11489
11490 SmiPtr length() const { return untag()->length(); }
11491
11492 intptr_t Length() const {
11493 ASSERT(!IsNull());
11494 return Smi::Value(untag()->length());
11495 }
11496
11497 intptr_t LengthInBytes() const {
11498 return ElementSizeInBytes(ptr()->GetClassId()) * Length();
11499 }
11500
11502 return ElementType(ptr()->GetClassId());
11503 }
11504
11505 intptr_t ElementSizeInBytes() const {
11506 return element_size(ElementType(ptr()->GetClassId()));
11507 }
11508
11509 static intptr_t ElementSizeInBytes(classid_t cid) {
11510 return element_size(ElementType(cid));
11511 }
11512
11515 return kUint8ArrayElement;
11516 } else if (IsTypedDataClassId(cid)) {
11517 const intptr_t index =
11518 (cid - kFirstTypedDataCid - kTypedDataCidRemainderInternal) /
11520 return static_cast<TypedDataElementType>(index);
11521 } else if (IsTypedDataViewClassId(cid)) {
11522 const intptr_t index =
11523 (cid - kFirstTypedDataCid - kTypedDataCidRemainderView) /
11525 return static_cast<TypedDataElementType>(index);
11526 } else if (IsExternalTypedDataClassId(cid)) {
11527 const intptr_t index =
11528 (cid - kFirstTypedDataCid - kTypedDataCidRemainderExternal) /
11530 return static_cast<TypedDataElementType>(index);
11531 } else {
11533 const intptr_t index =
11534 (cid - kFirstTypedDataCid - kTypedDataCidRemainderUnmodifiable) /
11536 return static_cast<TypedDataElementType>(index);
11537 }
11538 }
11539
11540 bool IsExternalOrExternalView() const;
11541 TypedDataViewPtr ViewFromTo(intptr_t start,
11542 intptr_t end,
11543 Heap::Space space = Heap::kNew) const;
11544
11545 void* DataAddr(intptr_t byte_offset) const {
11546 ASSERT((byte_offset == 0) ||
11547 ((byte_offset > 0) && (byte_offset < LengthInBytes())));
11548 return reinterpret_cast<void*>(Validate(untag()->data_) + byte_offset);
11549 }
11550
11551#define TYPED_GETTER_SETTER(name, type) \
11552 type Get##name(intptr_t byte_offset) const { \
11553 ASSERT(static_cast<uintptr_t>(byte_offset) <= \
11554 static_cast<uintptr_t>(LengthInBytes()) - sizeof(type)); \
11555 return LoadUnaligned( \
11556 reinterpret_cast<type*>(untag()->data_ + byte_offset)); \
11557 } \
11558 void Set##name(intptr_t byte_offset, type value) const { \
11559 ASSERT(static_cast<uintptr_t>(byte_offset) <= \
11560 static_cast<uintptr_t>(LengthInBytes()) - sizeof(type)); \
11561 StoreUnaligned(reinterpret_cast<type*>(untag()->data_ + byte_offset), \
11562 value); \
11563 }
11564
11565 TYPED_GETTER_SETTER(Int8, int8_t)
11566 TYPED_GETTER_SETTER(Uint8, uint8_t)
11567 TYPED_GETTER_SETTER(Int16, int16_t)
11568 TYPED_GETTER_SETTER(Uint16, uint16_t)
11569 TYPED_GETTER_SETTER(Int32, int32_t)
11570 TYPED_GETTER_SETTER(Uint32, uint32_t)
11571 TYPED_GETTER_SETTER(Int64, int64_t)
11572 TYPED_GETTER_SETTER(Uint64, uint64_t)
11573 TYPED_GETTER_SETTER(Float32, float)
11574 TYPED_GETTER_SETTER(Float64, double)
11575 TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
11576 TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
11577 TYPED_GETTER_SETTER(Float64x2, simd128_value_t)
11578
11579#undef TYPED_GETTER_SETTER
11580
11581 protected:
11582 void SetLength(intptr_t value) const {
11583 ASSERT(value <= Smi::kMaxValue);
11584 untag()->set_length(Smi::New(value));
11585 }
11586
11587 virtual uint8_t* Validate(uint8_t* data) const {
11588 return UnsafeMutableNonPointer(data);
11589 }
11590
11591 private:
11592 friend class Class;
11593
11594 static intptr_t element_size(intptr_t index) {
11595 ASSERT(0 <= index && index < kNumElementSizes);
11596 intptr_t size = element_size_table[index];
11597 ASSERT(size != 0);
11598 return size;
11599 }
11600 static constexpr intptr_t kNumElementSizes =
11601 ((kLastTypedDataCid + 1) - kFirstTypedDataCid) /
11603 static const intptr_t element_size_table[kNumElementSizes];
11604
11606};
11607
11608class TypedData : public TypedDataBase {
11609 public:
11610 virtual bool CanonicalizeEquals(const Instance& other) const;
11611 virtual uint32_t CanonicalizeHash() const;
11612
11613#define TYPED_GETTER_SETTER(name, type) \
11614 type Get##name(intptr_t byte_offset) const { \
11615 ASSERT(static_cast<uintptr_t>(byte_offset) <= \
11616 static_cast<uintptr_t>(LengthInBytes()) - sizeof(type)); \
11617 return LoadUnaligned( \
11618 reinterpret_cast<const type*>(untag()->data() + byte_offset)); \
11619 } \
11620 void Set##name(intptr_t byte_offset, type value) const { \
11621 ASSERT(static_cast<uintptr_t>(byte_offset) <= \
11622 static_cast<uintptr_t>(LengthInBytes()) - sizeof(type)); \
11623 return StoreUnaligned( \
11624 reinterpret_cast<type*>(untag()->data() + byte_offset), value); \
11625 }
11626
11627 TYPED_GETTER_SETTER(Int8, int8_t)
11628 TYPED_GETTER_SETTER(Uint8, uint8_t)
11629 TYPED_GETTER_SETTER(Int16, int16_t)
11630 TYPED_GETTER_SETTER(Uint16, uint16_t)
11631 TYPED_GETTER_SETTER(Int32, int32_t)
11632 TYPED_GETTER_SETTER(Uint32, uint32_t)
11633 TYPED_GETTER_SETTER(Int64, int64_t)
11634 TYPED_GETTER_SETTER(Uint64, uint64_t)
11635 TYPED_GETTER_SETTER(Float32, float)
11636 TYPED_GETTER_SETTER(Float64, double)
11640
11641#undef TYPED_GETTER_SETTER
11642
11643 static intptr_t payload_offset() {
11644 return UntaggedTypedData::payload_offset();
11645 }
11646
11647 static intptr_t InstanceSize() {
11648 ASSERT(sizeof(UntaggedTypedData) ==
11650 return 0;
11651 }
11652
11653 static intptr_t InstanceSize(intptr_t lengthInBytes) {
11654 ASSERT(0 <= lengthInBytes && lengthInBytes <= kSmiMax);
11655 return RoundedAllocationSize(sizeof(UntaggedTypedData) + lengthInBytes);
11656 }
11657
11658 static intptr_t MaxElements(intptr_t class_id) {
11659 ASSERT(IsTypedDataClassId(class_id));
11660 return (kSmiMax / ElementSizeInBytes(class_id));
11661 }
11662
11663 static intptr_t MaxNewSpaceElements(intptr_t class_id) {
11664 ASSERT(IsTypedDataClassId(class_id));
11665 return (kNewAllocatableSize - sizeof(UntaggedTypedData)) /
11666 ElementSizeInBytes(class_id);
11667 }
11668
11669 static TypedDataPtr New(intptr_t class_id,
11670 intptr_t len,
11671 Heap::Space space = Heap::kNew);
11672
11673 static TypedDataPtr Grow(const TypedData& current,
11674 intptr_t len,
11675 Heap::Space space = Heap::kNew);
11676
11677 static bool IsTypedData(const Instance& obj) {
11678 ASSERT(!obj.IsNull());
11679 intptr_t cid = obj.ptr()->GetClassId();
11680 return IsTypedDataClassId(cid);
11681 }
11682
11683 protected:
11684 void RecomputeDataField() { ptr()->untag()->RecomputeDataField(); }
11685
11686 private:
11687 // Provides const access to non-pointer, non-aligned data within the object.
11688 // Such access does not need a write barrier, but it is *not* GC-safe, since
11689 // the object might move.
11690 //
11691 // Therefore this method is private and the call-sites in this class need to
11692 // ensure the returned pointer does not escape.
11693 template <typename FieldType>
11694 const FieldType* ReadOnlyDataAddr(intptr_t byte_offset) const {
11695 return reinterpret_cast<const FieldType*>((untag()->data()) + byte_offset);
11696 }
11697
11698 FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedData, TypedDataBase);
11699 friend class Class;
11700 friend class ExternalTypedData;
11701 friend class TypedDataView;
11702};
11703
11705 public:
11706 // Alignment of data when serializing ExternalTypedData in a clustered
11707 // snapshot. Should be independent of word size.
11708 static constexpr int kDataSerializationAlignment = 8;
11709
11710 FinalizablePersistentHandle* AddFinalizer(void* peer,
11712 intptr_t external_size) const;
11713
11714 static intptr_t InstanceSize() {
11715 return RoundedAllocationSize(sizeof(UntaggedExternalTypedData));
11716 }
11717
11718 static intptr_t MaxElements(intptr_t class_id) {
11720 return (kSmiMax / ElementSizeInBytes(class_id));
11721 }
11722
11723 static ExternalTypedDataPtr New(
11724 intptr_t class_id,
11725 uint8_t* data,
11726 intptr_t len,
11727 Heap::Space space = Heap::kNew,
11728 bool perform_eager_msan_initialization_check = true);
11729
11730 static ExternalTypedDataPtr NewFinalizeWithFree(uint8_t* data, intptr_t len);
11731
11732 static bool IsExternalTypedData(const Instance& obj) {
11733 ASSERT(!obj.IsNull());
11734 intptr_t cid = obj.ptr()->GetClassId();
11736 }
11737
11738 protected:
11739 virtual uint8_t* Validate(uint8_t* data) const { return data; }
11740
11741 void SetLength(intptr_t value) const {
11742 ASSERT(value <= Smi::kMaxValue);
11743 untag()->set_length(Smi::New(value));
11744 }
11745
11746 void SetData(uint8_t* data) const {
11747 ASSERT(!IsolateGroup::Current()->heap()->Contains(
11748 reinterpret_cast<uword>(data)));
11749 StoreNonPointer(&untag()->data_, data);
11750 }
11751
11752 private:
11754 friend class Class;
11755};
11756
11758 public:
11759 static TypedDataViewPtr New(intptr_t class_id,
11760 Heap::Space space = Heap::kNew);
11761 static TypedDataViewPtr New(intptr_t class_id,
11762 const TypedDataBase& typed_data,
11763 intptr_t offset_in_bytes,
11764 intptr_t length,
11765 Heap::Space space = Heap::kNew);
11766
11767 static intptr_t InstanceSize() {
11768 return RoundedAllocationSize(sizeof(UntaggedTypedDataView));
11769 }
11770
11771 static InstancePtr Data(const TypedDataView& view) {
11772 return view.typed_data();
11773 }
11774
11775 static SmiPtr OffsetInBytes(const TypedDataView& view) {
11776 return view.offset_in_bytes();
11777 }
11778
11779 static bool IsExternalTypedDataView(const TypedDataView& view_obj) {
11780 const auto& data = Instance::Handle(Data(view_obj));
11781 intptr_t cid = data.ptr()->GetClassId();
11784 }
11785
11786 static intptr_t typed_data_offset() {
11787 return OFFSET_OF(UntaggedTypedDataView, typed_data_);
11788 }
11789
11790 static intptr_t offset_in_bytes_offset() {
11791 return OFFSET_OF(UntaggedTypedDataView, offset_in_bytes_);
11792 }
11793
11794 TypedDataBasePtr typed_data() const { return untag()->typed_data(); }
11795
11796 void InitializeWith(const TypedDataBase& typed_data,
11797 intptr_t offset_in_bytes,
11798 intptr_t length) {
11799 const classid_t cid = typed_data.GetClassId();
11801 untag()->set_typed_data(typed_data.ptr());
11802 untag()->set_length(Smi::New(length));
11803 untag()->set_offset_in_bytes(Smi::New(offset_in_bytes));
11804
11805 // Update the inner pointer.
11806 RecomputeDataField();
11807 }
11808
11809 SmiPtr offset_in_bytes() const { return untag()->offset_in_bytes(); }
11810
11811 protected:
11812 virtual uint8_t* Validate(uint8_t* data) const { return data; }
11813
11814 private:
11815 void RecomputeDataField() const { ptr()->untag()->RecomputeDataField(); }
11816
11817 void Clear() {
11818 untag()->set_length(Smi::New(0));
11819 untag()->set_offset_in_bytes(Smi::New(0));
11820 StoreNonPointer(&untag()->data_, nullptr);
11821 untag()->set_typed_data(TypedDataBase::RawCast(Object::null()));
11822 }
11823
11824 FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedDataView, TypedDataBase);
11825 friend class Class;
11826 friend class DeferredObject;
11827 friend class Object;
11829};
11830
11831class ByteBuffer : public AllStatic {
11832 public:
11833 static constexpr bool ContainsCompressedPointers() {
11834 return Instance::ContainsCompressedPointers();
11835 }
11836
11837 static InstancePtr Data(const Instance& view_obj) {
11838 ASSERT(!view_obj.IsNull());
11839 return reinterpret_cast<CompressedInstancePtr*>(
11840 reinterpret_cast<uword>(view_obj.untag()) + data_offset())
11841 ->Decompress(view_obj.untag()->heap_base());
11842 }
11843
11844 static intptr_t NumberOfFields() { return kNumFields; }
11845
11846 static intptr_t data_offset() {
11847 return sizeof(UntaggedObject) + (kCompressedWordSize * kDataIndex);
11848 }
11849
11850 private:
11851 enum {
11852 kDataIndex = 0,
11853 kNumFields = 1,
11854 };
11855};
11856
11857class Pointer : public Instance {
11858 public:
11859 static PointerPtr New(uword native_address, Heap::Space space = Heap::kNew);
11860
11861 static intptr_t InstanceSize() {
11862 return RoundedAllocationSize(sizeof(UntaggedPointer));
11863 }
11864
11865 static bool IsPointer(const Instance& obj);
11866
11867 size_t NativeAddress() const {
11868 return reinterpret_cast<size_t>(untag()->data_);
11869 }
11870
11871 void SetNativeAddress(size_t address) const {
11872 uint8_t* value = reinterpret_cast<uint8_t*>(address);
11873 StoreNonPointer(&untag()->data_, value);
11874 }
11875
11876 static intptr_t type_arguments_offset() {
11877 return OFFSET_OF(UntaggedPointer, type_arguments_);
11878 }
11879
11880 static constexpr intptr_t kNativeTypeArgPos = 0;
11881
11882 // Fetches the NativeType type argument.
11883 AbstractTypePtr type_argument() const {
11884 TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
11885 return type_args.TypeAtNullSafe(Pointer::kNativeTypeArgPos);
11886 }
11887
11888 private:
11890
11891 friend class Class;
11892};
11893
11894class DynamicLibrary : public Instance {
11895 public:
11896 static DynamicLibraryPtr New(void* handle,
11897 bool canBeClosed,
11898 Heap::Space space = Heap::kNew);
11899
11900 static intptr_t InstanceSize() {
11901 return RoundedAllocationSize(sizeof(UntaggedDynamicLibrary));
11902 }
11903
11904 static bool IsDynamicLibrary(const Instance& obj) {
11905 ASSERT(!obj.IsNull());
11906 intptr_t cid = obj.ptr()->GetClassId();
11908 }
11909
11910 void* GetHandle() const {
11911 ASSERT(!IsNull());
11912 return untag()->handle_;
11913 }
11914
11915 void SetHandle(void* value) const {
11916 StoreNonPointer(&untag()->handle_, value);
11917 }
11918
11919 bool CanBeClosed() const {
11920 ASSERT(!IsNull());
11921 return untag()->canBeClosed_;
11922 }
11923
11924 void SetCanBeClosed(bool value) const {
11925 ASSERT(!IsNull());
11926 StoreNonPointer(&untag()->canBeClosed_, value);
11927 }
11928
11929 bool IsClosed() const {
11930 ASSERT(!IsNull());
11931 return untag()->isClosed_;
11932 }
11933
11934 void SetClosed(bool value) const {
11935 StoreNonPointer(&untag()->isClosed_, value);
11936 }
11937
11938 private:
11940
11941 friend class Class;
11942};
11943
11944class LinkedHashBase : public Instance {
11945 public:
11946 // Keep consistent with _indexSizeToHashMask in compact_hash.dart.
11947 static intptr_t IndexSizeToHashMask(intptr_t index_size) {
11948 ASSERT(index_size >= kInitialIndexSize);
11949 intptr_t index_bits = Utils::BitLength(index_size) - 2;
11950#if defined(HAS_SMI_63_BITS)
11951 return (1 << (32 - index_bits)) - 1;
11952#else
11953 return (1 << (Object::kHashBits - index_bits)) - 1;
11954#endif
11955 }
11956 static intptr_t InstanceSize() {
11957 return RoundedAllocationSize(sizeof(UntaggedLinkedHashBase));
11958 }
11959
11960 static intptr_t type_arguments_offset() {
11961 return OFFSET_OF(UntaggedLinkedHashBase, type_arguments_);
11962 }
11963
11964 static intptr_t index_offset() {
11965 return OFFSET_OF(UntaggedLinkedHashBase, index_);
11966 }
11967
11968 static intptr_t data_offset() {
11969 return OFFSET_OF(UntaggedLinkedHashBase, data_);
11970 }
11971
11972 static intptr_t hash_mask_offset() {
11973 return OFFSET_OF(UntaggedLinkedHashBase, hash_mask_);
11974 }
11975
11976 static intptr_t used_data_offset() {
11977 return OFFSET_OF(UntaggedLinkedHashBase, used_data_);
11978 }
11979
11980 static intptr_t deleted_keys_offset() {
11981 return OFFSET_OF(UntaggedLinkedHashBase, deleted_keys_);
11982 }
11983
11984 static const LinkedHashBase& Cast(const Object& obj) {
11985 ASSERT(obj.IsMap() || obj.IsSet());
11986 return static_cast<const LinkedHashBase&>(obj);
11987 }
11988
11989 bool IsImmutable() const {
11990 return GetClassId() == kConstMapCid || GetClassId() == kConstSetCid;
11991 }
11992
11993 virtual TypeArgumentsPtr GetTypeArguments() const {
11994 return untag()->type_arguments();
11995 }
11996 virtual void SetTypeArguments(const TypeArguments& value) const {
11997 const intptr_t num_type_args = IsMap() ? 2 : 1;
11998 ASSERT(value.IsNull() ||
11999 ((value.Length() >= num_type_args) &&
12000 value.IsInstantiated() /*&& value.IsCanonical()*/));
12001 // TODO(asiva): Values read from a message snapshot are not properly marked
12002 // as canonical. See for example tests/isolate/message3_test.dart.
12003 untag()->set_type_arguments(value.ptr());
12004 }
12005
12006 TypedDataPtr index() const { return untag()->index(); }
12007 void set_index(const TypedData& value) const {
12008 ASSERT(!value.IsNull());
12009 untag()->set_index(value.ptr());
12010 }
12011
12012 ArrayPtr data() const { return untag()->data(); }
12013 void set_data(const Array& value) const { untag()->set_data(value.ptr()); }
12014
12015 SmiPtr hash_mask() const { return untag()->hash_mask(); }
12016 void set_hash_mask(intptr_t value) const {
12017 untag()->set_hash_mask(Smi::New(value));
12018 }
12019
12020 SmiPtr used_data() const { return untag()->used_data(); }
12021 void set_used_data(intptr_t value) const {
12022 untag()->set_used_data(Smi::New(value));
12023 }
12024
12025 SmiPtr deleted_keys() const { return untag()->deleted_keys(); }
12026 void set_deleted_keys(intptr_t value) const {
12027 untag()->set_deleted_keys(Smi::New(value));
12028 }
12029
12030 intptr_t Length() const {
12031 // The map or set may be uninitialized.
12032 if (untag()->used_data() == Object::null()) return 0;
12033 if (untag()->deleted_keys() == Object::null()) return 0;
12034
12035 intptr_t used = Smi::Value(untag()->used_data());
12036 if (IsMap()) {
12037 used >>= 1;
12038 }
12039 const intptr_t deleted = Smi::Value(untag()->deleted_keys());
12040 return used - deleted;
12041 }
12042
12043 // We do not compute the indices in the VM, but we do precompute the hash
12044 // mask to avoid a load acquire barrier on reading the combination of index
12045 // and hash mask.
12046 void ComputeAndSetHashMask() const;
12047
12048 virtual bool CanonicalizeEquals(const Instance& other) const;
12049 virtual uint32_t CanonicalizeHash() const;
12050 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
12051
12052 protected:
12053 // Keep this in sync with Dart implementation (lib/compact_hash.dart).
12054 static constexpr intptr_t kInitialIndexBits = 2;
12055 static constexpr intptr_t kInitialIndexSize = 1 << (kInitialIndexBits + 1);
12056
12057 private:
12058 LinkedHashBasePtr ptr() const { return static_cast<LinkedHashBasePtr>(ptr_); }
12059 UntaggedLinkedHashBase* untag() const {
12060 ASSERT(ptr() != null());
12061 return const_cast<UntaggedLinkedHashBase*>(ptr()->untag());
12062 }
12063
12064 friend class Class;
12066 friend class LinkedHashBaseDeserializationCluster;
12067};
12068
12070 public:
12071 static constexpr bool ContainsCompressedPointers() {
12072 return LinkedHashBase::ContainsCompressedPointers();
12073 }
12074
12075 static intptr_t data_offset() { return LinkedHashBase::data_offset(); }
12076};
12077
12078// Corresponds to
12079// - _Map in dart:collection
12080// - "new Map()",
12081// - non-const map literals, and
12082// - the default constructor of LinkedHashMap in dart:collection.
12083class Map : public LinkedHashBase {
12084 public:
12085 static intptr_t InstanceSize() {
12086 return RoundedAllocationSize(sizeof(UntaggedMap));
12087 }
12088
12089 // Allocates a map with some default capacity, just like "new Map()".
12090 static MapPtr NewDefault(intptr_t class_id = kMapCid,
12091 Heap::Space space = Heap::kNew);
12092 static MapPtr New(intptr_t class_id,
12093 const Array& data,
12094 const TypedData& index,
12095 intptr_t hash_mask,
12096 intptr_t used_data,
12097 intptr_t deleted_keys,
12098 Heap::Space space = Heap::kNew);
12099
12100 // This iterator differs somewhat from its Dart counterpart (_CompactIterator
12101 // in runtime/lib/compact_hash.dart):
12102 // - There are no checks for concurrent modifications.
12103 // - Accessing a key or value before the first call to MoveNext and after
12104 // MoveNext returns false will result in crashes.
12105 class Iterator : public ValueObject {
12106 public:
12107 explicit Iterator(const Map& map)
12108 : data_(Array::Handle(map.data())),
12109 scratch_(Object::Handle()),
12110 offset_(-2),
12111 length_(Smi::Value(map.used_data())) {}
12112
12113 bool MoveNext() {
12114 while (true) {
12115 offset_ += 2;
12116 if (offset_ >= length_) {
12117 return false;
12118 }
12119 scratch_ = data_.At(offset_);
12120 if (scratch_.ptr() != data_.ptr()) {
12121 // Slot is not deleted (self-reference indicates deletion).
12122 return true;
12123 }
12124 }
12125 }
12126
12127 ObjectPtr CurrentKey() const { return data_.At(offset_); }
12128
12129 ObjectPtr CurrentValue() const { return data_.At(offset_ + 1); }
12130
12131 private:
12132 const Array& data_;
12133 Object& scratch_;
12134 intptr_t offset_;
12135 const intptr_t length_;
12136 };
12137
12138 private:
12140
12141 // Allocate a map, but leave all fields set to null.
12142 // Used during deserialization (since map might contain itself as key/value).
12143 static MapPtr NewUninitialized(intptr_t class_id,
12144 Heap::Space space = Heap::kNew);
12145
12146 friend class Class;
12147 friend class ConstMap;
12149};
12150
12151// Corresponds to
12152// - _ConstMap in dart:collection
12153// - const map literals
12154class ConstMap : public AllStatic {
12155 public:
12156 static constexpr bool ContainsCompressedPointers() {
12157 return Map::ContainsCompressedPointers();
12158 }
12159
12160 static ConstMapPtr NewDefault(Heap::Space space = Heap::kNew);
12161
12162 static ConstMapPtr NewUninitialized(Heap::Space space = Heap::kNew);
12163
12164 static const ClassId kClassId = kConstMapCid;
12165
12166 static intptr_t InstanceSize() { return Map::InstanceSize(); }
12167
12168 private:
12169 static intptr_t NextFieldOffset() {
12170 // Indicates this class cannot be extended by dart code.
12171 return -kWordSize;
12172 }
12173
12174 static ConstMapPtr raw(const Map& map) {
12175 return static_cast<ConstMapPtr>(map.ptr());
12176 }
12177
12178 friend class Class;
12179};
12180
12181// Corresponds to
12182// - _Set in dart:collection,
12183// - "new Set()",
12184// - non-const set literals, and
12185// - the default constructor of LinkedHashSet in dart:collection.
12186class Set : public LinkedHashBase {
12187 public:
12188 static intptr_t InstanceSize() {
12189 return RoundedAllocationSize(sizeof(UntaggedSet));
12190 }
12191
12192 // Allocates a set with some default capacity, just like "new Set()".
12193 static SetPtr NewDefault(intptr_t class_id = kSetCid,
12194 Heap::Space space = Heap::kNew);
12195 static SetPtr New(intptr_t class_id,
12196 const Array& data,
12197 const TypedData& index,
12198 intptr_t hash_mask,
12199 intptr_t used_data,
12200 intptr_t deleted_keys,
12201 Heap::Space space = Heap::kNew);
12202
12203 // This iterator differs somewhat from its Dart counterpart (_CompactIterator
12204 // in runtime/lib/compact_hash.dart):
12205 // - There are no checks for concurrent modifications.
12206 // - Accessing a key or value before the first call to MoveNext and after
12207 // MoveNext returns false will result in crashes.
12208 class Iterator : public ValueObject {
12209 public:
12210 explicit Iterator(const Set& set)
12211 : data_(Array::Handle(set.data())),
12212 scratch_(Object::Handle()),
12213 offset_(-1),
12214 length_(Smi::Value(set.used_data())) {}
12215
12216 bool MoveNext() {
12217 while (true) {
12218 offset_++;
12219 if (offset_ >= length_) {
12220 return false;
12221 }
12222 scratch_ = data_.At(offset_);
12223 if (scratch_.ptr() != data_.ptr()) {
12224 // Slot is not deleted (self-reference indicates deletion).
12225 return true;
12226 }
12227 }
12228 }
12229
12230 ObjectPtr CurrentKey() const { return data_.At(offset_); }
12231
12232 private:
12233 const Array& data_;
12234 Object& scratch_;
12235 intptr_t offset_;
12236 const intptr_t length_;
12237 };
12238
12239 private:
12241
12242 // Allocate a set, but leave all fields set to null.
12243 // Used during deserialization (since set might contain itself as key/value).
12244 static SetPtr NewUninitialized(intptr_t class_id,
12245 Heap::Space space = Heap::kNew);
12246
12247 friend class Class;
12248 friend class ConstSet;
12250};
12251
12252// Corresponds to
12253// - _ConstSet in dart:collection
12254// - const set literals
12255class ConstSet : public AllStatic {
12256 public:
12257 static constexpr bool ContainsCompressedPointers() {
12258 return Set::ContainsCompressedPointers();
12259 }
12260
12261 static ConstSetPtr NewDefault(Heap::Space space = Heap::kNew);
12262
12263 static ConstSetPtr NewUninitialized(Heap::Space space = Heap::kNew);
12264
12265 static const ClassId kClassId = kConstSetCid;
12266
12267 static intptr_t InstanceSize() { return Set::InstanceSize(); }
12268
12269 private:
12270 static intptr_t NextFieldOffset() {
12271 // Indicates this class cannot be extended by dart code.
12272 return -kWordSize;
12273 }
12274
12275 static ConstSetPtr raw(const Set& map) {
12276 return static_cast<ConstSetPtr>(map.ptr());
12277 }
12278
12279 friend class Class;
12280};
12281
12282class Closure : public Instance {
12283 public:
12284#if defined(DART_PRECOMPILED_RUNTIME)
12285 uword entry_point() const { return untag()->entry_point_; }
12286 void set_entry_point(uword entry_point) const {
12287 StoreNonPointer(&untag()->entry_point_, entry_point);
12288 }
12289 static intptr_t entry_point_offset() {
12290 return OFFSET_OF(UntaggedClosure, entry_point_);
12291 }
12292#endif
12293
12294 TypeArgumentsPtr instantiator_type_arguments() const {
12295 return untag()->instantiator_type_arguments();
12296 }
12298 untag()->set_instantiator_type_arguments(args.ptr());
12299 }
12301 return OFFSET_OF(UntaggedClosure, instantiator_type_arguments_);
12302 }
12303
12304 TypeArgumentsPtr function_type_arguments() const {
12305 return untag()->function_type_arguments();
12306 }
12308 untag()->set_function_type_arguments(args.ptr());
12309 }
12311 return OFFSET_OF(UntaggedClosure, function_type_arguments_);
12312 }
12313
12314 TypeArgumentsPtr delayed_type_arguments() const {
12315 return untag()->delayed_type_arguments();
12316 }
12318 untag()->set_delayed_type_arguments(args.ptr());
12319 }
12321 return OFFSET_OF(UntaggedClosure, delayed_type_arguments_);
12322 }
12323
12324 FunctionPtr function() const { return untag()->function(); }
12325 static intptr_t function_offset() {
12326 return OFFSET_OF(UntaggedClosure, function_);
12327 }
12328 static FunctionPtr FunctionOf(ClosurePtr closure) {
12329 return closure.untag()->function();
12330 }
12331
12332 ObjectPtr RawContext() const { return untag()->context(); }
12333
12334 ContextPtr GetContext() const {
12336 return Context::RawCast(RawContext());
12337 }
12338
12339 InstancePtr GetImplicitClosureReceiver() const {
12341 return Instance::RawCast(RawContext());
12342 }
12343
12344 static intptr_t context_offset() {
12345 return OFFSET_OF(UntaggedClosure, context_);
12346 }
12347
12348 // Returns whether the closure is generic, that is, it has a generic closure
12349 // function and no delayed type arguments.
12350 bool IsGeneric() const {
12351 return delayed_type_arguments() == Object::empty_type_arguments().ptr();
12352 }
12353
12354 SmiPtr hash() const { return untag()->hash(); }
12355 static intptr_t hash_offset() { return OFFSET_OF(UntaggedClosure, hash_); }
12356
12357 static intptr_t InstanceSize() {
12358 return RoundedAllocationSize(sizeof(UntaggedClosure));
12359 }
12360
12361 virtual void CanonicalizeFieldsLocked(Thread* thread) const;
12362 virtual bool CanonicalizeEquals(const Instance& other) const;
12363 virtual uint32_t CanonicalizeHash() const {
12364 return Function::Handle(function()).Hash();
12365 }
12366 uword ComputeHash() const;
12367
12368 static ClosurePtr New(const TypeArguments& instantiator_type_arguments,
12369 const TypeArguments& function_type_arguments,
12370 const Function& function,
12371 const Object& context,
12372 Heap::Space space = Heap::kNew);
12373
12374 static ClosurePtr New(const TypeArguments& instantiator_type_arguments,
12375 const TypeArguments& function_type_arguments,
12376 const TypeArguments& delayed_type_arguments,
12377 const Function& function,
12378 const Object& context,
12379 Heap::Space space = Heap::kNew);
12380
12381 FunctionTypePtr GetInstantiatedSignature(Zone* zone) const;
12382
12383 private:
12385 friend class Class;
12386};
12387
12388// Corresponds to _Capability in dart:isolate.
12389class Capability : public Instance {
12390 public:
12391 uint64_t Id() const { return untag()->id_; }
12392
12393 static intptr_t InstanceSize() {
12394 return RoundedAllocationSize(sizeof(UntaggedCapability));
12395 }
12396 static CapabilityPtr New(uint64_t id, Heap::Space space = Heap::kNew);
12397
12398 private:
12400 friend class Class;
12401};
12402
12403// Corresponds to _RawReceivePort in dart:isolate.
12404class ReceivePort : public Instance {
12405 public:
12406 SendPortPtr send_port() const { return untag()->send_port(); }
12407 static intptr_t send_port_offset() {
12409 }
12410 Dart_Port Id() const { return send_port()->untag()->id_; }
12411
12412 InstancePtr handler() const { return untag()->handler(); }
12413 void set_handler(const Instance& value) const {
12414 untag()->set_handler(value.ptr());
12415 }
12416 static intptr_t handler_offset() {
12417 return OFFSET_OF(UntaggedReceivePort, handler_);
12418 }
12419
12420 bool is_open() const {
12421 return IsOpen::decode(Smi::Value(untag()->bitfield()));
12422 }
12423 void set_is_open(bool value) const {
12424 const auto updated = IsOpen::update(value, Smi::Value(untag()->bitfield()));
12425 untag()->set_bitfield(Smi::New(updated));
12426 }
12427
12428 bool keep_isolate_alive() const {
12429 return IsKeepIsolateAlive::decode(Smi::Value(untag()->bitfield()));
12430 }
12431 void set_keep_isolate_alive(bool value) const {
12432 const auto updated =
12433 IsKeepIsolateAlive::update(value, Smi::Value(untag()->bitfield()));
12434 untag()->set_bitfield(Smi::New(updated));
12435 }
12436
12437#if !defined(PRODUCT)
12438 StackTracePtr allocation_location() const {
12439 return untag()->allocation_location();
12440 }
12441
12442 StringPtr debug_name() const { return untag()->debug_name(); }
12443#endif
12444
12445 static intptr_t InstanceSize() {
12446 return RoundedAllocationSize(sizeof(UntaggedReceivePort));
12447 }
12448 static ReceivePortPtr New(Dart_Port id,
12449 const String& debug_name,
12450 Heap::Space space = Heap::kNew);
12451
12452 private:
12453 class IsOpen : public BitField<intptr_t, bool, 0, 1> {};
12454 class IsKeepIsolateAlive
12455 : public BitField<intptr_t, bool, IsOpen::kNextBit, 1> {};
12456
12457 FINAL_HEAP_OBJECT_IMPLEMENTATION(ReceivePort, Instance);
12458 friend class Class;
12459};
12460
12461// Corresponds to _SendPort in dart:isolate.
12462class SendPort : public Instance {
12463 public:
12464 Dart_Port Id() const { return untag()->id_; }
12465
12466 Dart_Port origin_id() const { return untag()->origin_id_; }
12467 void set_origin_id(Dart_Port id) const {
12468 ASSERT(origin_id() == 0);
12469 StoreNonPointer(&(untag()->origin_id_), id);
12470 }
12471
12472 static intptr_t InstanceSize() {
12473 return RoundedAllocationSize(sizeof(UntaggedSendPort));
12474 }
12475 static SendPortPtr New(Dart_Port id, Heap::Space space = Heap::kNew);
12476 static SendPortPtr New(Dart_Port id,
12477 Dart_Port origin_id,
12478 Heap::Space space = Heap::kNew);
12479
12480 private:
12482 friend class Class;
12483};
12484
12485// This is allocated when new instance of TransferableTypedData is created in
12486// [TransferableTypedData::New].
12488 public:
12489 // [data] backing store should be malloc'ed, not new'ed.
12490 TransferableTypedDataPeer(uint8_t* data, intptr_t length)
12491 : data_(data), length_(length), handle_(nullptr) {}
12492
12494
12495 uint8_t* data() const { return data_; }
12496 intptr_t length() const { return length_; }
12499
12500 void ClearData() {
12501 data_ = nullptr;
12502 length_ = 0;
12503 handle_ = nullptr;
12504 }
12505
12506 private:
12507 uint8_t* data_;
12508 intptr_t length_;
12510
12512};
12513
12515 public:
12516 static TransferableTypedDataPtr New(uint8_t* data, intptr_t len);
12517
12518 static intptr_t InstanceSize() {
12519 return RoundedAllocationSize(sizeof(UntaggedTransferableTypedData));
12520 }
12521
12522 private:
12524 friend class Class;
12525};
12526
12527class DebuggerStackTrace;
12528
12529// Internal stacktrace object used in exceptions for printing stack traces.
12530class StackTrace : public Instance {
12531 public:
12532 static constexpr int kPreallocatedStackdepth = 90;
12533
12534 intptr_t Length() const;
12535
12536 StackTracePtr async_link() const { return untag()->async_link(); }
12537 void set_async_link(const StackTrace& async_link) const;
12538 void set_expand_inlined(bool value) const;
12539
12540 ArrayPtr code_array() const { return untag()->code_array(); }
12541 ObjectPtr CodeAtFrame(intptr_t frame_index) const;
12542 void SetCodeAtFrame(intptr_t frame_index, const Object& code) const;
12543
12544 TypedDataPtr pc_offset_array() const { return untag()->pc_offset_array(); }
12545 uword PcOffsetAtFrame(intptr_t frame_index) const;
12546 void SetPcOffsetAtFrame(intptr_t frame_index, uword pc_offset) const;
12547
12548 bool skip_sync_start_in_parent_stack() const;
12549 void set_skip_sync_start_in_parent_stack(bool value) const;
12550
12551 // The number of frames that should be cut off the top of an async stack trace
12552 // if it's appended to a synchronous stack trace along a sync-async call.
12553 //
12554 // Without cropping, the border would look like:
12555 //
12556 // <async function>
12557 // ---------------------------
12558 // <asynchronous gap marker>
12559 // <async function>
12560 //
12561 // Since it's not actually an async call, we crop off the last two
12562 // frames when concatenating the sync and async stacktraces.
12563 static constexpr intptr_t kSyncAsyncCroppedFrames = 2;
12564
12565 static intptr_t InstanceSize() {
12566 return RoundedAllocationSize(sizeof(UntaggedStackTrace));
12567 }
12568 static StackTracePtr New(const Array& code_array,
12569 const TypedData& pc_offset_array,
12570 Heap::Space space = Heap::kNew);
12571
12572 static StackTracePtr New(const Array& code_array,
12573 const TypedData& pc_offset_array,
12574 const StackTrace& async_link,
12575 bool skip_sync_start_in_parent_stack,
12576 Heap::Space space = Heap::kNew);
12577
12578 private:
12579 void set_code_array(const Array& code_array) const;
12580 void set_pc_offset_array(const TypedData& pc_offset_array) const;
12581 bool expand_inlined() const;
12582
12584 friend class Class;
12586};
12587
12588class SuspendState : public Instance {
12589 public:
12590 // :suspend_state local variable index
12591 static constexpr intptr_t kSuspendStateVarIndex = 0;
12592
12593 static intptr_t HeaderSize() { return sizeof(UntaggedSuspendState); }
12594 static intptr_t UnroundedSize(SuspendStatePtr ptr) {
12595 return UnroundedSize(ptr->untag()->frame_capacity());
12596 }
12597 static intptr_t UnroundedSize(intptr_t frame_capacity) {
12598 return HeaderSize() + frame_capacity;
12599 }
12600 static intptr_t InstanceSize() {
12603 return 0;
12604 }
12605 static intptr_t InstanceSize(intptr_t frame_capacity) {
12606 return RoundedAllocationSize(UnroundedSize(frame_capacity));
12607 }
12608
12609 // Number of extra words reserved for growth of frame size
12610 // during SuspendState allocation. Frames do not grow in AOT.
12611 static intptr_t FrameSizeGrowthGap() {
12613 }
12614
12615#if !defined(DART_PRECOMPILED_RUNTIME)
12616 static intptr_t frame_capacity_offset() {
12617 return OFFSET_OF(UntaggedSuspendState, frame_capacity_);
12618 }
12619#endif
12620 static intptr_t frame_size_offset() {
12621 return OFFSET_OF(UntaggedSuspendState, frame_size_);
12622 }
12623 static intptr_t pc_offset() { return OFFSET_OF(UntaggedSuspendState, pc_); }
12624 static intptr_t function_data_offset() {
12625 return OFFSET_OF(UntaggedSuspendState, function_data_);
12626 }
12627 static intptr_t then_callback_offset() {
12628 return OFFSET_OF(UntaggedSuspendState, then_callback_);
12629 }
12630 static intptr_t error_callback_offset() {
12631 return OFFSET_OF(UntaggedSuspendState, error_callback_);
12632 }
12633 static intptr_t payload_offset() {
12634 return UntaggedSuspendState::payload_offset();
12635 }
12636
12637 static SuspendStatePtr New(intptr_t frame_size,
12638 const Instance& function_data,
12639 Heap::Space space = Heap::kNew);
12640
12641 // Makes a copy of [src] object.
12642 // The object should be holding a suspended frame.
12643 static SuspendStatePtr Clone(Thread* thread,
12644 const SuspendState& src,
12645 Heap::Space space = Heap::kNew);
12646
12647 uword pc() const { return untag()->pc_; }
12648
12649 intptr_t frame_size() const { return untag()->frame_size_; }
12650
12651 InstancePtr function_data() const { return untag()->function_data(); }
12652
12653 ClosurePtr then_callback() const { return untag()->then_callback(); }
12654
12655 ClosurePtr error_callback() const { return untag()->error_callback(); }
12656
12657 // Returns Code object corresponding to the suspended function.
12658 CodePtr GetCodeObject() const;
12659
12660 private:
12661#if !defined(DART_PRECOMPILED_RUNTIME)
12662 void set_frame_capacity(intptr_t frame_capcity) const;
12663#endif
12664 void set_frame_size(intptr_t frame_size) const;
12665 void set_pc(uword pc) const;
12666 void set_function_data(const Instance& function_data) const;
12667 void set_then_callback(const Closure& then_callback) const;
12668 void set_error_callback(const Closure& error_callback) const;
12669
12670 uint8_t* payload() const { return untag()->payload(); }
12671
12672 FINAL_HEAP_OBJECT_IMPLEMENTATION(SuspendState, Instance);
12673 friend class Class;
12674};
12675
12677 public:
12678 // Flags are passed to a regex object as follows:
12679 // 'i': ignore case, 'g': do global matches, 'm': pattern is multi line,
12680 // 'u': pattern is full Unicode, not just BMP, 's': '.' in pattern matches
12681 // all characters including line terminators.
12682 enum Flags {
12684 kGlobal = 1,
12685 kIgnoreCase = 2,
12686 kMultiLine = 4,
12687 kUnicode = 8,
12688 kDotAll = 16,
12689 };
12690
12691 static constexpr int kDefaultFlags = 0;
12692
12693 RegExpFlags() : value_(kDefaultFlags) {}
12694 explicit RegExpFlags(int value) : value_(value) {}
12695
12696 inline bool IsGlobal() const { return (value_ & kGlobal) != 0; }
12697 inline bool IgnoreCase() const { return (value_ & kIgnoreCase) != 0; }
12698 inline bool IsMultiLine() const { return (value_ & kMultiLine) != 0; }
12699 inline bool IsUnicode() const { return (value_ & kUnicode) != 0; }
12700 inline bool IsDotAll() const { return (value_ & kDotAll) != 0; }
12701
12703 // Both unicode and ignore_case flags are set. We need to use ICU to find
12704 // the closure over case equivalents.
12705 return IsUnicode() && IgnoreCase();
12706 }
12707
12708 void SetGlobal() { value_ |= kGlobal; }
12709 void SetIgnoreCase() { value_ |= kIgnoreCase; }
12710 void SetMultiLine() { value_ |= kMultiLine; }
12711 void SetUnicode() { value_ |= kUnicode; }
12712 void SetDotAll() { value_ |= kDotAll; }
12713
12714 const char* ToCString() const;
12715
12716 int value() const { return value_; }
12717
12718 bool operator==(const RegExpFlags& other) const {
12719 return value_ == other.value_;
12720 }
12721 bool operator!=(const RegExpFlags& other) const {
12722 return value_ != other.value_;
12723 }
12724
12725 private:
12726 int value_;
12727};
12728
12729// Internal JavaScript regular expression object.
12730class RegExp : public Instance {
12731 public:
12732 // Meaning of RegExType:
12733 // kUninitialized: the type of th regexp has not been initialized yet.
12734 // kSimple: A simple pattern to match against, using string indexOf operation.
12735 // kComplex: A complex pattern to match.
12737 kUninitialized = 0,
12738 kSimple = 1,
12739 kComplex = 2,
12740 };
12741
12742 enum {
12743 kTypePos = 0,
12744 kTypeSize = 2,
12745 kFlagsPos = 2,
12746 kFlagsSize = 5,
12747 };
12748
12749 class TypeBits : public BitField<int8_t, RegExType, kTypePos, kTypeSize> {};
12750 class GlobalBit : public BitField<int8_t, bool, kFlagsPos, 1> {};
12751 class IgnoreCaseBit : public BitField<int8_t, bool, GlobalBit::kNextBit, 1> {
12752 };
12754 : public BitField<int8_t, bool, IgnoreCaseBit::kNextBit, 1> {};
12755 class UnicodeBit : public BitField<int8_t, bool, MultiLineBit::kNextBit, 1> {
12756 };
12757 class DotAllBit : public BitField<int8_t, bool, UnicodeBit::kNextBit, 1> {};
12758
12759 class FlagsBits : public BitField<int8_t, int8_t, kFlagsPos, kFlagsSize> {};
12760
12761 bool is_initialized() const { return (type() != kUninitialized); }
12762 bool is_simple() const { return (type() == kSimple); }
12763 bool is_complex() const { return (type() == kComplex); }
12764
12765 intptr_t num_registers(bool is_one_byte) const {
12766 return LoadNonPointer<intptr_t, std::memory_order_relaxed>(
12767 is_one_byte ? &untag()->num_one_byte_registers_
12768 : &untag()->num_two_byte_registers_);
12769 }
12770
12771 StringPtr pattern() const { return untag()->pattern(); }
12772 intptr_t num_bracket_expressions() const {
12773 return untag()->num_bracket_expressions_;
12774 }
12775 ArrayPtr capture_name_map() const { return untag()->capture_name_map(); }
12776
12777 TypedDataPtr bytecode(bool is_one_byte, bool sticky) const {
12778 if (sticky) {
12779 return TypedData::RawCast(
12780 is_one_byte ? untag()->one_byte_sticky<std::memory_order_acquire>()
12781 : untag()->two_byte_sticky<std::memory_order_acquire>());
12782 } else {
12783 return TypedData::RawCast(
12784 is_one_byte ? untag()->one_byte<std::memory_order_acquire>()
12785 : untag()->two_byte<std::memory_order_acquire>());
12786 }
12787 }
12788
12789 static intptr_t function_offset(intptr_t cid, bool sticky) {
12790 if (sticky) {
12791 switch (cid) {
12792 case kOneByteStringCid:
12793 return OFFSET_OF(UntaggedRegExp, one_byte_sticky_);
12794 case kTwoByteStringCid:
12795 return OFFSET_OF(UntaggedRegExp, two_byte_sticky_);
12796 }
12797 } else {
12798 switch (cid) {
12799 case kOneByteStringCid:
12800 return OFFSET_OF(UntaggedRegExp, one_byte_);
12801 case kTwoByteStringCid:
12802 return OFFSET_OF(UntaggedRegExp, two_byte_);
12803 }
12804 }
12805
12806 UNREACHABLE();
12807 return -1;
12808 }
12809
12810 FunctionPtr function(intptr_t cid, bool sticky) const {
12811 if (sticky) {
12812 switch (cid) {
12813 case kOneByteStringCid:
12814 return static_cast<FunctionPtr>(untag()->one_byte_sticky());
12815 case kTwoByteStringCid:
12816 return static_cast<FunctionPtr>(untag()->two_byte_sticky());
12817 }
12818 } else {
12819 switch (cid) {
12820 case kOneByteStringCid:
12821 return static_cast<FunctionPtr>(untag()->one_byte());
12822 case kTwoByteStringCid:
12823 return static_cast<FunctionPtr>(untag()->two_byte());
12824 }
12825 }
12826
12827 UNREACHABLE();
12828 return Function::null();
12829 }
12830
12831 void set_pattern(const String& pattern) const;
12832 void set_function(intptr_t cid, bool sticky, const Function& value) const;
12833 void set_bytecode(bool is_one_byte,
12834 bool sticky,
12835 const TypedData& bytecode) const;
12836
12837 void set_num_bracket_expressions(SmiPtr value) const;
12838 void set_num_bracket_expressions(const Smi& value) const;
12839 void set_num_bracket_expressions(intptr_t value) const;
12840 void set_capture_name_map(const Array& array) const;
12841 void set_is_global() const {
12842 untag()->type_flags_.UpdateBool<GlobalBit>(true);
12843 }
12844 void set_is_ignore_case() const {
12845 untag()->type_flags_.UpdateBool<IgnoreCaseBit>(true);
12846 }
12847 void set_is_multi_line() const {
12848 untag()->type_flags_.UpdateBool<MultiLineBit>(true);
12849 }
12850 void set_is_unicode() const {
12851 untag()->type_flags_.UpdateBool<UnicodeBit>(true);
12852 }
12853 void set_is_dot_all() const {
12854 untag()->type_flags_.UpdateBool<DotAllBit>(true);
12855 }
12856 void set_is_simple() const { set_type(kSimple); }
12857 void set_is_complex() const { set_type(kComplex); }
12858 void set_num_registers(bool is_one_byte, intptr_t value) const {
12859 StoreNonPointer<intptr_t, intptr_t, std::memory_order_relaxed>(
12860 is_one_byte ? &untag()->num_one_byte_registers_
12861 : &untag()->num_two_byte_registers_,
12862 value);
12863 }
12864
12866 return RegExpFlags(untag()->type_flags_.Read<FlagsBits>());
12867 }
12869 untag()->type_flags_.Update<FlagsBits>(flags.value());
12870 }
12871
12872 virtual bool CanonicalizeEquals(const Instance& other) const;
12873 virtual uint32_t CanonicalizeHash() const;
12874
12875 static intptr_t InstanceSize() {
12876 return RoundedAllocationSize(sizeof(UntaggedRegExp));
12877 }
12878
12879 static RegExpPtr New(Zone* zone, Heap::Space space = Heap::kNew);
12880
12881 private:
12882 void set_type(RegExType type) const {
12883 untag()->type_flags_.Update<TypeBits>(type);
12884 }
12885 RegExType type() const { return untag()->type_flags_.Read<TypeBits>(); }
12886
12887 FINAL_HEAP_OBJECT_IMPLEMENTATION(RegExp, Instance);
12888 friend class Class;
12889};
12890
12891// Corresponds to _WeakProperty in dart:core.
12892class WeakProperty : public Instance {
12893 public:
12894 ObjectPtr key() const { return untag()->key(); }
12895 void set_key(const Object& key) const { untag()->set_key(key.ptr()); }
12896 static intptr_t key_offset() { return OFFSET_OF(UntaggedWeakProperty, key_); }
12897
12898 ObjectPtr value() const { return untag()->value(); }
12899 void set_value(const Object& value) const { untag()->set_value(value.ptr()); }
12900 static intptr_t value_offset() {
12901 return OFFSET_OF(UntaggedWeakProperty, value_);
12902 }
12903
12904 static WeakPropertyPtr New(Heap::Space space = Heap::kNew);
12905
12906 static intptr_t InstanceSize() {
12907 return RoundedAllocationSize(sizeof(UntaggedWeakProperty));
12908 }
12909
12910 private:
12912 friend class Class;
12913};
12914
12915// Corresponds to _WeakReference in dart:core.
12916class WeakReference : public Instance {
12917 public:
12918 ObjectPtr target() const { return untag()->target(); }
12919 void set_target(const Object& target) const {
12920 untag()->set_target(target.ptr());
12921 }
12922 static intptr_t target_offset() {
12923 return OFFSET_OF(UntaggedWeakReference, target_);
12924 }
12925
12926 static intptr_t type_arguments_offset() {
12927 return OFFSET_OF(UntaggedWeakReference, type_arguments_);
12928 }
12929
12930 static WeakReferencePtr New(Heap::Space space = Heap::kNew);
12931
12932 static intptr_t InstanceSize() {
12933 return RoundedAllocationSize(sizeof(UntaggedWeakReference));
12934 }
12935
12936 private:
12938 friend class Class;
12939};
12940
12941class FinalizerBase;
12942class FinalizerEntry : public Instance {
12943 public:
12944 ObjectPtr value() const { return untag()->value(); }
12945 void set_value(const Object& value) const { untag()->set_value(value.ptr()); }
12946 static intptr_t value_offset() {
12947 return OFFSET_OF(UntaggedFinalizerEntry, value_);
12948 }
12949
12950 ObjectPtr detach() const { return untag()->detach(); }
12951 void set_detach(const Object& value) const {
12952 untag()->set_detach(value.ptr());
12953 }
12954 static intptr_t detach_offset() {
12955 return OFFSET_OF(UntaggedFinalizerEntry, detach_);
12956 }
12957
12958 ObjectPtr token() const { return untag()->token(); }
12959 void set_token(const Object& value) const { untag()->set_token(value.ptr()); }
12960 static intptr_t token_offset() {
12961 return OFFSET_OF(UntaggedFinalizerEntry, token_);
12962 }
12963
12964 FinalizerBasePtr finalizer() const { return untag()->finalizer(); }
12965 void set_finalizer(const FinalizerBase& value) const;
12966 static intptr_t finalizer_offset() {
12967 return OFFSET_OF(UntaggedFinalizerEntry, finalizer_);
12968 }
12969
12970 FinalizerEntryPtr next() const { return untag()->next(); }
12971 void set_next(const FinalizerEntry& value) const {
12972 untag()->set_next(value.ptr());
12973 }
12974 static intptr_t next_offset() {
12975 return OFFSET_OF(UntaggedFinalizerEntry, next_);
12976 }
12977
12978 intptr_t external_size() const { return untag()->external_size(); }
12979 void set_external_size(intptr_t value) const {
12980 untag()->set_external_size(value);
12981 }
12982 static intptr_t external_size_offset() {
12983 return OFFSET_OF(UntaggedFinalizerEntry, external_size_);
12984 }
12985
12986 static intptr_t InstanceSize() {
12987 return RoundedAllocationSize(sizeof(UntaggedFinalizerEntry));
12988 }
12989
12990 // Allocates a new FinalizerEntry, initializing the external size (to 0) and
12991 // finalizer.
12992 //
12993 // Should only be used for object tests.
12994 //
12995 // Does not initialize `value`, `token`, and `detach` to allow for flexible
12996 // testing code setting those manually.
12997 //
12998 // Does _not_ add the entry to the finalizer. We could add the entry to
12999 // finalizer.all_entries.data, but we have no way of initializing the hashset
13000 // index.
13001 static FinalizerEntryPtr New(const FinalizerBase& finalizer,
13002 Heap::Space space = Heap::kNew);
13003
13004 private:
13006 friend class Class;
13007};
13008
13009class FinalizerBase : public Instance {
13010 public:
13011 static intptr_t isolate_offset() {
13012 return OFFSET_OF(UntaggedFinalizerBase, isolate_);
13013 }
13014 Isolate* isolate() const { return untag()->isolate_; }
13015 void set_isolate(Isolate* value) const { untag()->isolate_ = value; }
13016
13017 static intptr_t detachments_offset() {
13018 return OFFSET_OF(UntaggedFinalizerBase, detachments_);
13019 }
13020
13021 SetPtr all_entries() const { return untag()->all_entries(); }
13022 void set_all_entries(const Set& value) const {
13023 untag()->set_all_entries(value.ptr());
13024 }
13025 static intptr_t all_entries_offset() {
13026 return OFFSET_OF(UntaggedFinalizerBase, all_entries_);
13027 }
13028
13029 FinalizerEntryPtr entries_collected() const {
13030 return untag()->entries_collected();
13031 }
13032 void set_entries_collected(const FinalizerEntry& value) const {
13033 untag()->set_entries_collected(value.ptr());
13034 }
13035 static intptr_t entries_collected_offset() {
13036 return OFFSET_OF(UntaggedFinalizer, entries_collected_);
13037 }
13038
13039 private:
13041 friend class Class;
13042};
13043
13044class Finalizer : public FinalizerBase {
13045 public:
13046 static intptr_t type_arguments_offset() {
13047 return OFFSET_OF(UntaggedFinalizer, type_arguments_);
13048 }
13049
13050 ObjectPtr callback() const { return untag()->callback(); }
13051 static intptr_t callback_offset() {
13052 return OFFSET_OF(UntaggedFinalizer, callback_);
13053 }
13054
13055 static intptr_t InstanceSize() {
13056 return RoundedAllocationSize(sizeof(UntaggedFinalizer));
13057 }
13058
13059 static FinalizerPtr New(Heap::Space space = Heap::kNew);
13060
13061 private:
13063 friend class Class;
13064};
13065
13067 public:
13068 typedef void (*Callback)(void*);
13069
13070 PointerPtr callback() const { return untag()->callback(); }
13071 void set_callback(const Pointer& value) const {
13072 untag()->set_callback(value.ptr());
13073 }
13074 static intptr_t callback_offset() {
13075 return OFFSET_OF(UntaggedNativeFinalizer, callback_);
13076 }
13077
13078 static intptr_t InstanceSize() {
13079 return RoundedAllocationSize(sizeof(UntaggedNativeFinalizer));
13080 }
13081
13082 static NativeFinalizerPtr New(Heap::Space space = Heap::kNew);
13083
13084 void RunCallback(const FinalizerEntry& entry,
13085 const char* trace_context) const;
13086
13087 private:
13089 friend class Class;
13090};
13091
13093 public:
13094 ObjectPtr referent() const { return untag()->referent(); }
13095
13096 void set_referent(const Object& referent) const {
13097 untag()->set_referent(referent.ptr());
13098 }
13099
13100 AbstractTypePtr GetAbstractTypeReferent() const;
13101
13102 ClassPtr GetClassReferent() const;
13103
13104 FieldPtr GetFieldReferent() const;
13105
13106 FunctionPtr GetFunctionReferent() const;
13107
13108 FunctionTypePtr GetFunctionTypeReferent() const;
13109
13110 LibraryPtr GetLibraryReferent() const;
13111
13112 TypeParameterPtr GetTypeParameterReferent() const;
13113
13114 static MirrorReferencePtr New(const Object& referent,
13115 Heap::Space space = Heap::kNew);
13116
13117 static intptr_t InstanceSize() {
13118 return RoundedAllocationSize(sizeof(UntaggedMirrorReference));
13119 }
13120
13121 private:
13123 friend class Class;
13124};
13125
13126class UserTag : public Instance {
13127 public:
13128 uword tag() const { return untag()->tag(); }
13129 void set_tag(uword t) const {
13130 ASSERT(t >= UserTags::kUserTagIdOffset);
13131 ASSERT(t < UserTags::kUserTagIdOffset + UserTags::kMaxUserTags);
13132 StoreNonPointer(&untag()->tag_, t);
13133 }
13134
13135 bool streamable() const { return untag()->streamable(); }
13136 void set_streamable(bool streamable) {
13137 StoreNonPointer(&untag()->streamable_, streamable);
13138 }
13139
13140 static intptr_t tag_offset() { return OFFSET_OF(UntaggedUserTag, tag_); }
13141
13142 StringPtr label() const { return untag()->label(); }
13143
13144 UserTagPtr MakeActive() const;
13145
13146 static intptr_t InstanceSize() {
13147 return RoundedAllocationSize(sizeof(UntaggedUserTag));
13148 }
13149
13150 static UserTagPtr New(const String& label, Heap::Space space = Heap::kOld);
13151 static UserTagPtr DefaultTag();
13152
13153 static bool TagTableIsFull(Thread* thread);
13154 static UserTagPtr FindTagById(const Isolate* isolate, uword tag_id);
13155 static UserTagPtr FindTagInIsolate(Isolate* isolate,
13156 Thread* thread,
13157 const String& label);
13158
13159 private:
13160 static UserTagPtr FindTagInIsolate(Thread* thread, const String& label);
13161 static void AddTagToIsolate(Thread* thread, const UserTag& tag);
13162
13163 void set_label(const String& tag_label) const {
13164 untag()->set_label(tag_label.ptr());
13165 }
13166
13167 FINAL_HEAP_OBJECT_IMPLEMENTATION(UserTag, Instance);
13168 friend class Class;
13169};
13170
13171// Represents abstract FutureOr class in dart:async.
13172class FutureOr : public Instance {
13173 public:
13174 static intptr_t InstanceSize() {
13175 return RoundedAllocationSize(sizeof(UntaggedFutureOr));
13176 }
13177
13178 virtual TypeArgumentsPtr GetTypeArguments() const {
13179 return untag()->type_arguments();
13180 }
13181 static intptr_t type_arguments_offset() {
13182 return OFFSET_OF(UntaggedFutureOr, type_arguments_);
13183 }
13184
13185 private:
13187
13188 friend class Class;
13189};
13190
13191// Breaking cycles and loops.
13192ClassPtr Object::clazz() const {
13193 uword raw_value = static_cast<uword>(ptr_);
13194 if ((raw_value & kSmiTagMask) == kSmiTag) {
13195 return Smi::Class();
13196 }
13198}
13199
13200DART_FORCE_INLINE
13201void Object::setPtr(ObjectPtr value, intptr_t default_cid) {
13202 ptr_ = value;
13203 intptr_t cid = value->GetClassIdMayBeSmi();
13204 // Free-list elements cannot be wrapped in a handle.
13207 if (cid == kNullCid) {
13208 cid = default_cid;
13209 } else if (cid >= kNumPredefinedCids) {
13210 cid = kInstanceCid;
13211 }
13212 set_vtable(builtin_vtables_[cid]);
13213}
13214
13215intptr_t Field::HostOffset() const {
13216 ASSERT(is_instance()); // Valid only for dart instance fields.
13217 return (Smi::Value(untag()->host_offset_or_field_id()) * kCompressedWordSize);
13218}
13219
13220intptr_t Field::TargetOffset() const {
13221 ASSERT(is_instance()); // Valid only for dart instance fields.
13222#if !defined(DART_PRECOMPILED_RUNTIME)
13223 return (untag()->target_offset_ * compiler::target::kCompressedWordSize);
13224#else
13225 return HostOffset();
13226#endif // !defined(DART_PRECOMPILED_RUNTIME)
13227}
13228
13229inline intptr_t Field::TargetOffsetOf(const FieldPtr field) {
13230#if !defined(DART_PRECOMPILED_RUNTIME)
13231 return field->untag()->target_offset_;
13232#else
13233 return Smi::Value(field->untag()->host_offset_or_field_id());
13234#endif // !defined(DART_PRECOMPILED_RUNTIME)
13235}
13236
13237void Field::SetOffset(intptr_t host_offset_in_bytes,
13238 intptr_t target_offset_in_bytes) const {
13239 ASSERT(is_instance()); // Valid only for dart instance fields.
13241 untag()->set_host_offset_or_field_id(
13242 Smi::New(host_offset_in_bytes / kCompressedWordSize));
13243#if !defined(DART_PRECOMPILED_RUNTIME)
13244 ASSERT(compiler::target::kCompressedWordSize != 0);
13246 &untag()->target_offset_,
13247 target_offset_in_bytes / compiler::target::kCompressedWordSize);
13248#else
13249 ASSERT(host_offset_in_bytes == target_offset_in_bytes);
13250#endif // !defined(DART_PRECOMPILED_RUNTIME)
13251}
13252
13254 ASSERT(is_static()); // Valid only for static dart fields.
13255 return Isolate::Current()->field_table()->At(field_id());
13256}
13257
13258inline intptr_t Field::field_id() const {
13259 return Smi::Value(untag()->host_offset_or_field_id());
13260}
13261
13262void Field::set_field_id(intptr_t field_id) const {
13264 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
13265 set_field_id_unsafe(field_id);
13266}
13267
13268void Field::set_field_id_unsafe(intptr_t field_id) const {
13269 ASSERT(is_static());
13270 untag()->set_host_offset_or_field_id(Smi::New(field_id));
13271}
13272
13273intptr_t WeakArray::LengthOf(const WeakArrayPtr array) {
13274 return Smi::Value(array->untag()->length());
13275}
13276
13277void Context::SetAt(intptr_t index, const Object& value) const {
13278 untag()->set_element(index, value.ptr());
13279}
13280
13281intptr_t Instance::GetNativeField(int index) const {
13282 ASSERT(IsValidNativeIndex(index));
13283 NoSafepointScope no_safepoint;
13284 TypedDataPtr native_fields = static_cast<TypedDataPtr>(
13285 NativeFieldsAddr()->Decompress(untag()->heap_base()));
13286 if (native_fields == TypedData::null()) {
13287 return 0;
13288 }
13289 return reinterpret_cast<intptr_t*>(native_fields->untag()->data())[index];
13290}
13291
13292void Instance::GetNativeFields(uint16_t num_fields,
13293 intptr_t* field_values) const {
13294 NoSafepointScope no_safepoint;
13295 ASSERT(num_fields == NumNativeFields());
13296 ASSERT(field_values != nullptr);
13297 TypedDataPtr native_fields = static_cast<TypedDataPtr>(
13298 NativeFieldsAddr()->Decompress(untag()->heap_base()));
13299 if (native_fields == TypedData::null()) {
13300 for (intptr_t i = 0; i < num_fields; i++) {
13301 field_values[i] = 0;
13302 }
13303 }
13304 intptr_t* fields =
13305 reinterpret_cast<intptr_t*>(native_fields->untag()->data());
13306 for (intptr_t i = 0; i < num_fields; i++) {
13307 field_values[i] = fields[i];
13308 }
13309}
13310
13311bool String::Equals(const String& str) const {
13312 if (ptr() == str.ptr()) {
13313 return true; // Both handles point to the same raw instance.
13314 }
13315 if (str.IsNull()) {
13316 return false;
13317 }
13318 if (IsCanonical() && str.IsCanonical()) {
13319 return false; // Two symbols that aren't identical aren't equal.
13320 }
13321 if (HasHash() && str.HasHash() && (Hash() != str.Hash())) {
13322 return false; // Both sides have hash codes and they do not match.
13323 }
13324 return Equals(str, 0, str.Length());
13325}
13326
13327intptr_t Library::UrlHash() const {
13328 intptr_t result = String::GetCachedHash(url());
13329 ASSERT(result != 0);
13330 return result;
13331}
13332
13333void MegamorphicCache::SetEntry(const Array& array,
13334 intptr_t index,
13335 const Smi& class_id,
13336 const Object& target) {
13337 ASSERT(target.IsNull() || target.IsFunction() || target.IsSmi());
13338 array.SetAt((index * kEntryLength) + kClassIdIndex, class_id);
13339 array.SetAt((index * kEntryLength) + kTargetFunctionIndex, target);
13340}
13341
13342ObjectPtr MegamorphicCache::GetClassId(const Array& array, intptr_t index) {
13343 return array.At((index * kEntryLength) + kClassIdIndex);
13344}
13345
13346ObjectPtr MegamorphicCache::GetTargetFunction(const Array& array,
13347 intptr_t index) {
13348 return array.At((index * kEntryLength) + kTargetFunctionIndex);
13349}
13350
13352 ASSERT(IsFinalized());
13353 intptr_t result = Smi::Value(untag()->hash());
13354 if (result != 0) {
13355 return result;
13356 }
13357 return ComputeHash();
13358}
13359
13360inline void AbstractType::SetHash(intptr_t value) const {
13361 // This is only safe because we create a new Smi, which does not cause
13362 // heap allocation.
13363 untag()->set_hash(Smi::New(value));
13364}
13365
13366inline intptr_t RecordType::NumFields() const {
13367 return Array::LengthOf(field_types());
13368}
13369
13371 if (IsNull()) return kAllDynamicHash;
13372 intptr_t result = Smi::Value(untag()->hash());
13373 if (result != 0) {
13374 return result;
13375 }
13376 return ComputeHash();
13377}
13378
13379inline void TypeArguments::SetHash(intptr_t value) const {
13380 // This is only safe because we create a new Smi, which does not cause
13381 // heap allocation.
13382 untag()->set_hash(Smi::New(value));
13383}
13384
13385inline uint16_t String::CharAt(StringPtr str, intptr_t index) {
13386 switch (str->GetClassId()) {
13387 case kOneByteStringCid:
13388 return OneByteString::CharAt(static_cast<OneByteStringPtr>(str), index);
13389 case kTwoByteStringCid:
13390 return TwoByteString::CharAt(static_cast<TwoByteStringPtr>(str), index);
13391 }
13392 UNREACHABLE();
13393 return 0;
13394}
13395
13396// A view on an [Array] as a list of tuples, optionally starting at an offset.
13397//
13398// Example: We store a list of (kind, function, code) tuples into the
13399// [Code::static_calls_target_table] array of type [Array].
13400//
13401// This helper class can then be used via
13402//
13403// using CallTableView = ArrayOfTuplesView<
13404// Code::Kind, std::tuple<Smi, Function, Code>>;
13405//
13406// auto& array = Array::Handle(code.static_calls_targets_table());
13407// CallTableView static_calls(array);
13408//
13409// // Using convenient for loop.
13410// auto& function = Function::Handle();
13411// for (auto& call : static_calls) {
13412// function = call.Get<Code::kSCallTableFunctionTarget>();
13413// call.Set<Code::kSCallTableFunctionTarget>(function);
13414// }
13415//
13416// // Using manual loop.
13417// auto& function = Function::Handle();
13418// for (intptr_t i = 0; i < static_calls.Length(); ++i) {
13419// auto call = static_calls[i];
13420// function = call.Get<Code::kSCallTableFunctionTarget>();
13421// call.Set<Code::kSCallTableFunctionTarget>(function);
13422// }
13423//
13424//
13425// Template parameters:
13426//
13427// * [EnumType] must be a normal enum which enumerates the entries of the
13428// tuple
13429//
13430// * [kStartOffset] is the offset at which the first tuple in the array
13431// starts (can be 0).
13432//
13433// * [TupleT] must be a std::tuple<...> where "..." are the heap object handle
13434// classes (e.g. 'Code', 'Smi', 'Object')
13435template <typename EnumType, typename TupleT, int kStartOffset = 0>
13437 public:
13438 static constexpr intptr_t EntrySize = std::tuple_size<TupleT>::value;
13439
13440 class Iterator;
13441
13443 public:
13444 TupleView(const Array& array, intptr_t index)
13445 : array_(array), index_(index) {}
13446
13447 template <EnumType kElement,
13448 std::memory_order order = std::memory_order_relaxed>
13449 typename std::tuple_element<kElement, TupleT>::type::ObjectPtrType Get()
13450 const {
13451 using object_type = typename std::tuple_element<kElement, TupleT>::type;
13452 return object_type::RawCast(array_.At<order>(index_ + kElement));
13453 }
13454
13455 template <EnumType kElement,
13456 std::memory_order order = std::memory_order_relaxed>
13457 void Set(const typename std::tuple_element<kElement, TupleT>::type& value)
13458 const {
13459 array_.SetAt<order>(index_ + kElement, value);
13460 }
13461
13462 intptr_t index() const { return (index_ - kStartOffset) / EntrySize; }
13463
13464 private:
13465 const Array& array_;
13466 intptr_t index_;
13467
13468 friend class Iterator;
13469 };
13470
13471 class Iterator {
13472 public:
13473 Iterator(const Array& array, intptr_t index) : entry_(array, index) {}
13474
13475 bool operator==(const Iterator& other) {
13476 return entry_.index_ == other.entry_.index_;
13477 }
13478 bool operator!=(const Iterator& other) {
13479 return entry_.index_ != other.entry_.index_;
13480 }
13481
13482 const TupleView& operator*() const { return entry_; }
13483
13485 entry_.index_ += EntrySize;
13486 return *this;
13487 }
13488
13489 private:
13490 TupleView entry_;
13491 };
13492
13493 explicit ArrayOfTuplesView(const Array& array) : array_(array) {
13494 ASSERT(!array.IsNull());
13495 ASSERT(array.Length() >= kStartOffset);
13496 ASSERT(array.Length() % EntrySize == kStartOffset);
13497 }
13498
13499 intptr_t Length() const {
13500 return (array_.Length() - kStartOffset) / EntrySize;
13501 }
13502
13503 TupleView At(intptr_t i) const {
13504 return TupleView(array_, kStartOffset + i * EntrySize);
13505 }
13506
13507 TupleView operator[](intptr_t i) const { return At(i); }
13508
13509 Iterator begin() const { return Iterator(array_, kStartOffset); }
13510
13511 Iterator end() const {
13512 return Iterator(array_, kStartOffset + Length() * EntrySize);
13513 }
13514
13515 private:
13516 const Array& array_;
13517};
13518
13521
13523
13525 std::tuple<Object,
13532 Bool>>;
13533
13536
13539 std::tuple<Object, TypeArguments, TypeArguments>,
13541
13542void DumpTypeTable(Isolate* isolate);
13543void DumpTypeParameterTable(Isolate* isolate);
13544void DumpTypeArgumentsTable(Isolate* isolate);
13545
13547 const Object& metadata_obj,
13548 const String& pragma_name,
13549 bool multiple = false,
13550 Object* options = nullptr);
13551
13553 const Array& metadata,
13554 Field* reusable_field_handle,
13555 Object* reusable_object_handle);
13556
13558ErrorPtr EntryPointFieldInvocationError(const String& getter_name);
13559
13561ErrorPtr EntryPointMemberInvocationError(const Object& member);
13562
13563#undef PRECOMPILER_WSR_FIELD_DECLARATION
13564
13565} // namespace dart
13566
13567#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:55
static struct Initializer initializer
int count
static constexpr size_t kHeaderSize
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.
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
#define COMPILE_ASSERT(expr)
Definition assert.h:339
bool Equals(const SkPath &a, const SkPath &b)
#define CLASS_LIST(V)
Definition class_id.h:208
bool IsNullableObjectType() const
Definition object.h:9184
bool IsNonNullable() const
Definition object.h:9048
UntaggedAbstractType::TypeState type_state() const
Definition object.h:9331
bool IsMintType() const
Definition object.h:9229
bool IsFinalized() const
Definition object.h:9030
static intptr_t flags_offset()
Definition object.h:9023
virtual bool HasTypeClass() const
Definition object.h:9063
void SetHash(intptr_t value) const
Definition object.h:13360
static intptr_t type_test_stub_entry_point_offset()
Definition object.h:9277
bool IsSmiType() const
Definition object.h:9226
bool IsVoidType() const
Definition object.h:9169
static intptr_t NextFieldOffset()
Definition object.h:9313
uword type_test_stub_entry_point() const
Definition object.h:9281
Nullability nullability() const
Definition object.h:9037
virtual bool Equals(const Instance &other) const
Definition object.h:9074
static intptr_t InstanceSize()
Definition object.h:9309
bool IsObjectType() const
Definition object.h:9181
bool IsNumberType() const
Definition object.h:9223
virtual uint32_t CanonicalizeHash() const
Definition object.h:9073
bool IsCatchAllType() const
Definition object.h:9256
bool IsFutureOrType() const
Definition object.h:9247
CodePtr type_test_stub() const
Definition object.h:9284
uword Hash() const
Definition object.h:13351
HEAP_OBJECT_IMPLEMENTATION(AbstractType, Instance)
void UpdateTypeTestingStubEntryPoint() const
Definition object.h:9302
bool IsNullable() const
Definition object.h:9043
bool IsBoolType() const
Definition object.h:9202
static intptr_t hash_offset()
Definition object.h:9026
bool IsDynamicType() const
Definition object.h:9166
virtual InstancePtr CanonicalizeLocked(Thread *thread) const
Definition object.h:9118
virtual bool CanonicalizeEquals(const Instance &other) const
Definition object.h:9070
bool IsLegacy() const
Definition object.h:9053
StringPtr message() const
Definition object.h:8030
static intptr_t InstanceSize()
Definition object.h:8032
Iterator(const Array &array, intptr_t index)
Definition object.h:13473
const TupleView & operator*() const
Definition object.h:13482
bool operator==(const Iterator &other)
Definition object.h:13475
bool operator!=(const Iterator &other)
Definition object.h:13478
std::tuple_element< kElement, TupleT >::type::ObjectPtrType Get() const
Definition object.h:13449
void Set(const typename std::tuple_element< kElement, TupleT >::type &value) const
Definition object.h:13457
TupleView(const Array &array, intptr_t index)
Definition object.h:13444
ArrayOfTuplesView(const Array &array)
Definition object.h:13493
Iterator end() const
Definition object.h:13511
intptr_t Length() const
Definition object.h:13499
TupleView operator[](intptr_t i) const
Definition object.h:13507
TupleView At(intptr_t i) const
Definition object.h:13503
Iterator begin() const
Definition object.h:13509
static intptr_t type_arguments_offset()
Definition object.h:10902
static intptr_t InstanceSize()
Definition object.h:10910
void SetAt(intptr_t index, const Object &value, Thread *thread) const
Definition object.h:10862
static intptr_t index_at_offset(intptr_t offset_in_bytes)
Definition object.h:10821
static CompressedObjectPtr * DataOf(ArrayPtr array)
Definition object.h:10849
static bool Equals(ArrayPtr a, ArrayPtr b)
Definition object.h:10833
ObjectPtr AtAcquire(intptr_t index) const
Definition object.h:10867
static intptr_t element_offset(intptr_t index)
Definition object.h:10817
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
Definition object.h:10933
static constexpr intptr_t InstanceSize(intptr_t len)
Definition object.h:10923
void SetAtRelease(intptr_t index, const Object &value) const
Definition object.h:10870
virtual TypeArgumentsPtr GetTypeArguments() const
Definition object.h:10879
static constexpr bool UseCardMarkingForAllocation(const intptr_t array_length)
Definition object.h:10797
static constexpr bool IsValidLength(intptr_t len)
Definition object.h:10906
bool IsImmutable() const
Definition object.h:10874
virtual void SetTypeArguments(const TypeArguments &value) const
Definition object.h:10882
static intptr_t LengthOf(const ArrayPtr array)
Definition object.h:10809
ObjectPtr At(intptr_t index) const
Definition object.h:10854
intptr_t Length() const
Definition object.h:10808
static ArrayPtr NewUninitialized(intptr_t len, Heap::Space space=Heap::kNew)
Definition object.h:10938
ArrayPtr Copy() const
Definition object.h:10971
static constexpr intptr_t UnroundedSize(intptr_t len)
Definition object.h:10916
static intptr_t data_offset()
Definition object.h:10814
void SetAt(intptr_t index, const Object &value) const
Definition object.h:10858
static intptr_t length_offset()
Definition object.h:10813
bool Equals(const Array &other) const
Definition object.h:10844
static constexpr bool decode(uint8_t value)
Definition bitfield.h:173
static intptr_t InstanceSize()
Definition object.h:10772
virtual uint32_t CanonicalizeHash() const
Definition object.h:10784
static const Bool & False()
Definition object.h:10778
static const Bool & Get(bool value)
Definition object.h:10780
static const Bool & True()
Definition object.h:10776
bool value() const
Definition object.h:10770
static InstancePtr Data(const Instance &view_obj)
Definition object.h:11837
static constexpr bool ContainsCompressedPointers()
Definition object.h:11833
static intptr_t NumberOfFields()
Definition object.h:11844
static intptr_t data_offset()
Definition object.h:11846
intptr_t CountWithTypeArgs() const
Definition object.cc:16532
intptr_t CountWithoutTypeArgs() const
Definition object.cc:16537
static intptr_t target_name_offset()
Definition object.h:2365
intptr_t SizeWithoutTypeArgs() const
Definition object.cc:16542
StringPtr target_name() const
Definition object.h:2352
friend class ICData
Definition object.h:2379
intptr_t SizeWithTypeArgs() const
Definition object.cc:16547
static intptr_t arguments_descriptor_offset()
Definition object.h:2369
intptr_t TypeArgsLen() const
Definition object.cc:16527
ArrayPtr arguments_descriptor() const
Definition object.h:2353
static intptr_t InstanceSize()
Definition object.h:12393
uint64_t Id() const
Definition object.h:12391
void Register(const Class &cls)
ClassPtr At(intptr_t cid) const
static intptr_t target_instance_size(ClassPtr clazz)
Definition object.h:1161
void PatchFieldsAndFunctions() const
void CopyDeclarationType(const Class &old_cls) const
void AddFields(const GrowableArray< const Field * > &fields) const
Definition object.cc:5068
static intptr_t id_offset()
Definition object.h:1240
TypeArgumentsPtr DefaultTypeArguments(Zone *zone) const
Definition object.cc:3708
void AddFunction(const Function &function) const
Definition object.cc:3346
void set_is_implemented_unsafe() const
Definition object.cc:5673
bool is_sealed() const
Definition object.h:1761
void set_num_type_arguments(intptr_t value) const
Definition object.cc:3170
void set_is_transformed_mixin_application() const
Definition object.cc:5720
bool is_base_class() const
Definition object.h:1767
static intptr_t host_instance_size(ClassPtr clazz)
Definition object.h:1158
void set_is_implemented() const
Definition object.cc:5668
FieldPtr LookupInstanceField(const String &name) const
Definition object.cc:6399
intptr_t kernel_offset() const
Definition object.h:1806
void set_has_pragma(bool value) const
Definition object.cc:3190
const char * NameCString(NameVisibility name_visibility) const
Definition object.cc:3067
void set_is_finalized_unsafe() const
Definition object.cc:5775
intptr_t FindImplicitClosureFunctionIndex(const Function &needle) const
Definition object.cc:3414
intptr_t NumTypeParameters() const
Definition object.h:1346
const char * ScrubbedNameCString() const
Definition object.cc:3046
FunctionPtr LookupFunctionAllowPrivate(const String &name) const
Definition object.cc:6222
ObjectPtr InvokeSetter(const String &selector, const Instance &argument, bool respect_reflectable=true, bool check_is_entrypoint=false) const
Definition object.cc:4632
CodePtr allocation_stub() const
Definition object.h:1802
void set_is_deeply_immutable(bool value) const
Definition object.cc:3205
FunctionPtr LookupDynamicFunctionAllowPrivate(const String &name) const
Definition object.cc:6188
void set_instance_size(intptr_t host_value_in_bytes, intptr_t target_value_in_bytes) const
Definition object.h:1169
LibraryPtr library() const
Definition object.h:1335
void set_is_isolate_unsendable_due_to_pragma(bool value) const
Definition object.cc:3199
void set_super_type(const Type &value) const
Definition object.cc:3734
bool TraceAllocation(IsolateGroup *isolate_group) const
Definition object.cc:4489
FunctionPtr InvocationDispatcherFunctionFromIndex(intptr_t idx) const
Definition object.cc:3469
void set_is_allocate_finalized() const
Definition object.cc:5780
FunctionPtr LookupConstructorAllowPrivate(const String &name) const
Definition object.cc:6208
static ClassPtr NewTypedDataViewClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition object.cc:5333
void set_is_enum_class() const
Definition object.cc:5710
void set_is_synthesized_class() const
Definition object.cc:5701
FunctionPtr LookupGetterFunction(const String &name) const
Definition object.cc:6363
void CopyCanonicalConstants(const Class &old_cls) const
void Finalize() const
Definition object.cc:4362
static uint16_t NumNativeFieldsOf(ClassPtr clazz)
Definition object.h:1794
static int32_t target_next_field_offset_in_words(const ClassPtr cls)
Definition object.h:1961
static int32_t host_next_field_offset_in_words(const ClassPtr cls)
Definition object.h:1957
bool IsRecordClass() const
Definition object.h:1585
bool IsInFullSnapshot() const
Definition object.cc:3091
ObjectPtr InvokeGetter(const String &selector, bool throw_nsm_if_absent, bool respect_reflectable=true, bool check_is_entrypoint=false) const
Definition object.cc:4572
FieldPtr LookupInstanceFieldAllowPrivate(const String &name) const
Definition object.cc:6489
void set_is_allocated_unsafe(bool value) const
Definition object.cc:5760
bool can_be_future() const
Definition object.h:2178
void AddDirectImplementor(const Class &subclass, bool is_mixin) const
Definition object.cc:5801
TypePtr GetInstantiationOf(Zone *zone, const Class &cls) const
Definition object.cc:12776
bool is_declaration_loaded() const
Definition object.h:1705
intptr_t target_type_arguments_field_offset() const
Definition object.h:1386
uint32_t Hash() const
Definition object.cc:5652
static intptr_t super_type_offset()
Definition object.h:1438
void SetFields(const Array &value) const
Definition object.cc:5039
void set_is_prefinalized() const
Definition object.cc:5787
bool is_const() const
Definition object.h:1747
void set_is_interface_class() const
Definition object.cc:5740
bool IsDartFunctionClass() const
Definition object.cc:5958
void set_next_field_offset_in_words(intptr_t host_value, intptr_t target_value) const
Definition object.h:1209
StringPtr ScrubbedName() const
Definition object.cc:3042
static intptr_t InstanceSize()
Definition object.h:1687
GrowableObjectArrayPtr direct_subclasses() const
Definition object.h:1539
GrowableObjectArrayPtr direct_implementors_unsafe() const
Definition object.h:1527
bool is_mixin_class() const
Definition object.h:1764
TypeArgumentsPtr GetDeclarationInstanceTypeArguments() const
Definition object.cc:3526
TypePtr super_type() const
Definition object.h:1433
FunctionPtr GetInvocationDispatcher(const String &target_name, const Array &args_desc, UntaggedFunction::Kind kind, bool create_if_absent) const
Definition object.cc:3897
intptr_t host_next_field_offset() const
Definition object.h:1192
FunctionPtr LookupStaticFunction(const String &name) const
Definition object.cc:6192
intptr_t id() const
Definition object.h:1235
static intptr_t UnboxedFieldSizeInBytesByCid(intptr_t cid)
Definition object.cc:3752
void set_is_declaration_loaded() const
Definition object.cc:5682
bool is_final() const
Definition object.h:1775
static ClassPtr NewExternalTypedDataClass(intptr_t class_id, IsolateGroup *isolate)
Definition object.cc:5373
void set_num_type_arguments_unsafe(intptr_t value) const
Definition object.cc:3186
intptr_t target_instance_size() const
Definition object.h:1149
void set_is_fields_marked_nullable() const
Definition object.cc:5750
intptr_t NumTypeArguments() const
Definition object.cc:3690
void set_is_abstract() const
Definition object.cc:5677
static intptr_t host_type_arguments_field_offset_in_words_offset()
Definition object.h:1428
void set_is_mixin_class() const
Definition object.cc:5730
FunctionPtr LookupConstructor(const String &name) const
Definition object.cc:6202
void set_type_arguments_field_offset_in_words(intptr_t host_value, intptr_t target_value) const
Definition object.h:1416
void set_num_native_fields(uint16_t value) const
Definition object.h:1791
static ClassPtr NewTypedDataClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition object.cc:5314
void set_type_arguments_field_offset(intptr_t host_value_in_bytes, intptr_t target_value_in_bytes) const
Definition object.h:1399
WeakArrayPtr dependent_code() const
Definition object.cc:4475
static bool is_valid_id(intptr_t value)
Definition object.h:1232
void set_dependent_code(const WeakArray &array) const
Definition object.cc:4481
intptr_t target_next_field_offset() const
Definition object.h:1195
static int32_t host_type_arguments_field_offset_in_words(const ClassPtr cls)
Definition object.h:1969
bool is_isolate_unsendable() const
Definition object.h:2153
ObjectPtr EvaluateCompiledExpression(const ExternalTypedData &kernel_buffer, const Array &type_definitions, const Array &param_values, const TypeArguments &type_param_values) const
Definition object.cc:4876
FunctionPtr LookupSetterFunction(const String &name) const
Definition object.cc:6367
bool is_loaded() const
Definition object.h:1787
bool IsPrivate() const
Definition object.cc:6180
FunctionPtr GetRecordFieldGetter(const String &getter_name) const
Definition object.cc:4128
void set_is_sealed() const
Definition object.cc:5725
TypePtr RareType() const
Definition object.cc:3097
void set_direct_subclasses(const GrowableObjectArray &subclasses) const
Definition object.cc:5854
static intptr_t declaration_type_offset()
Definition object.h:1317
intptr_t host_type_arguments_field_offset() const
Definition object.h:1377
static bool IsIsolateUnsendable(ClassPtr clazz)
Definition object.h:1797
ArrayPtr interfaces() const
Definition object.h:1449
bool IsObjectClass() const
Definition object.h:1567
bool InjectCIDFields() const
Definition object.cc:5114
void set_interfaces(const Array &value) const
Definition object.cc:5794
bool is_type_finalized() const
Definition object.h:1711
void SetUserVisibleNameInClassTable()
Definition object.cc:5438
static int32_t target_type_arguments_field_offset_in_words(const ClassPtr cls)
Definition object.h:1973
InstancePtr InsertCanonicalConstant(Zone *zone, const Instance &constant) const
Definition object.cc:6540
void set_script(const Script &value) const
Definition object.cc:5610
ArrayPtr fields() const
Definition object.h:1617
bool is_deeply_immutable() const
Definition object.h:2164
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:5975
void DisableAllocationStub() const
Definition object.cc:5934
void SetTraceAllocation(bool trace_allocation) const
Definition object.cc:4498
ArrayPtr constants() const
Definition object.cc:5861
bool HasInstanceFields() const
Definition object.cc:3261
void set_is_future_subtype(bool value) const
Definition object.cc:3210
void set_is_declaration_loaded_unsafe() const
Definition object.cc:5687
InstancePtr LookupCanonicalInstance(Zone *zone, const Instance &value) const
Definition object.cc:6527
uint16_t num_native_fields() const
Definition object.h:1790
void MigrateImplicitStaticClosures(ProgramReloadContext *context, const Class &new_cls) const
intptr_t implementor_cid() const
Definition object.h:1247
void set_is_finalized() const
Definition object.cc:5769
ArrayPtr OffsetToFieldMap(ClassTable *class_table=nullptr) const
Definition object.cc:3233
intptr_t host_instance_size() const
Definition object.h:1145
static bool IsDeeplyImmutable(ClassPtr clazz)
Definition object.h:2167
void DisableAllCHAOptimizedCode()
Definition object.cc:4471
FunctionPtr LookupFunctionReadLocked(const String &name) const
Definition object.cc:6226
void AddField(const Field &field) const
Definition object.cc:5057
void DisableCHAOptimizedCode(const Class &subclass)
Definition object.cc:4457
bool HasCompressedPointers() const
Definition object.cc:3007
static intptr_t num_type_arguments_offset()
Definition object.h:1254
void set_is_allocated(bool value) const
Definition object.cc:5755
void set_allocation_stub(const Code &value) const
Definition object.cc:5925
int32_t SourceFingerprint() const
Definition object.cc:5659
static int32_t host_instance_size_in_words(const ClassPtr cls)
Definition object.h:1945
FunctionPtr LookupDynamicFunctionUnsafe(const String &name) const
Definition object.cc:6184
bool is_abstract() const
Definition object.h:1698
bool IsDynamicClass() const
Definition object.h:1558
bool IsGeneric() const
Definition object.h:1360
bool IsClosureClass() const
Definition object.h:1579
StringPtr Name() const
Definition object.cc:3038
InvocationDispatcherEntry
Definition object.h:1137
@ kInvocationDispatcherArgsDesc
Definition object.h:1139
@ kInvocationDispatcherName
Definition object.h:1138
@ kInvocationDispatcherFunction
Definition object.h:1140
@ kInvocationDispatcherEntrySize
Definition object.h:1141
static bool IsInFullSnapshot(ClassPtr cls)
Definition object.h:1587
static constexpr intptr_t kNoTypeArguments
Definition object.h:1376
FunctionPtr LookupStaticFunctionAllowPrivate(const String &name) const
Definition object.cc:6198
void set_token_pos(TokenPosition value) const
Definition object.cc:5620
TypePtr DeclarationType() const
Definition object.cc:5882
FieldPtr LookupStaticFieldAllowPrivate(const String &name) const
Definition object.cc:6497
FunctionPtr LookupFactory(const String &name) const
Definition object.cc:6212
TokenPosition token_pos() const
Definition object.h:1281
void set_instance_size_in_words(intptr_t host_value, intptr_t target_value) const
Definition object.h:1176
ErrorPtr EnsureIsFinalized(Thread *thread) const
Definition object.cc:4979
bool IsVoidClass() const
Definition object.h:1561
void set_is_synthesized_class_unsafe() const
Definition object.cc:5706
bool FindInstantiationOf(Zone *zone, const Class &cls, GrowableArray< const Type * > *path, bool consider_only_super_classes=false) const
Definition object.cc:12723
void set_is_base_class() const
Definition object.cc:5735
static ClassPtr New(IsolateGroup *isolate_group, bool register_class=true)
Definition object.cc:3114
bool is_prefinalized() const
Definition object.h:1740
void RegisterCHACode(const Code &code)
Definition object.cc:4445
bool IsFutureClass() const
Definition object.cc:5962
GrowableObjectArrayPtr direct_subclasses_unsafe() const
Definition object.h:1544
KernelProgramInfoPtr KernelProgramInfo() const
Definition object.cc:5615
TokenPosition end_token_pos() const
Definition object.h:1293
bool is_future_subtype() const
Definition object.h:2172
FieldPtr LookupField(const String &name) const
Definition object.cc:6407
friend class Intrinsifier
Definition object.h:2221
void CopyStaticFieldValues(ProgramReloadContext *reload_context, const Class &old_cls) const
void set_kernel_offset(intptr_t value) const
Definition object.h:1814
void set_library(const Library &value) const
Definition object.cc:3488
void set_end_token_pos(TokenPosition value) const
Definition object.cc:5625
ErrorPtr EnsureIsAllocateFinalized(Thread *thread) const
Definition object.cc:5009
void DisableCHAImplementorUsers()
Definition object.h:1919
bool is_fields_marked_nullable() const
Definition object.h:1778
FunctionPtr LookupFactoryAllowPrivate(const String &name) const
Definition object.cc:6218
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
Definition object.cc:3715
void set_is_loaded(bool value) const
Definition object.cc:5764
static ClassPtr NewStringClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition object.cc:5287
void set_constants(const Array &value) const
Definition object.cc:5865
intptr_t FindFieldIndex(const Field &needle) const
Definition object.cc:5085
StringPtr UserVisibleName() const
Definition object.cc:3050
void AddInvocationDispatcher(const String &target_name, const Array &args_desc, const Function &dispatcher) const
Definition object.cc:3881
bool FindInstantiationOf(Zone *zone, const Class &cls, bool consider_only_super_classes=false) const
Definition object.h:1470
void AddDirectSubclass(const Class &subclass) const
Definition object.cc:5833
void set_id(intptr_t value) const
Definition object.h:1236
bool FindInstantiationOf(Zone *zone, const Type &type, bool consider_only_super_classes=false) const
Definition object.h:1493
bool IsTopLevel() const
Definition object.cc:6176
static intptr_t GetClassId(ClassPtr cls)
Definition object.h:1593
FieldPtr FieldFromIndex(intptr_t idx) const
Definition object.cc:5106
static int32_t target_instance_size_in_words(const ClassPtr cls)
Definition object.h:1949
bool is_enum_class() const
Definition object.h:1722
bool IsNeverClass() const
Definition object.h:1564
bool NoteImplementor(const Class &implementor) const
Definition object.cc:5635
TypeParametersPtr type_parameters() const
Definition object.h:1340
bool IsNullClass() const
Definition object.h:1555
void set_is_type_finalized() const
Definition object.cc:5693
const char * UserVisibleNameCString() const
Definition object.cc:3059
void MarkFieldBoxedDuringReload(ClassTable *class_table, const Field &field) const
void set_is_final() const
Definition object.cc:5745
GrowableObjectArrayPtr direct_implementors() const
Definition object.h:1522
intptr_t FindFunctionIndex(const Function &needle) const
Definition object.cc:3371
bool is_implemented() const
Definition object.h:1694
TypeParameterPtr TypeParameterAt(intptr_t index, Nullability nullability=Nullability::kNonNullable) const
Definition object.cc:3739
static ClassPtr NewPointerClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition object.cc:5393
void set_next_field_offset(intptr_t host_value_in_bytes, intptr_t target_value_in_bytes) const
Definition object.h:1203
bool has_pragma() const
Definition object.h:2149
void set_is_const() const
Definition object.cc:5715
bool is_allocate_finalized() const
Definition object.h:1734
bool is_transformed_mixin_application() const
Definition object.h:1756
FunctionPtr ImplicitClosureFunctionFromIndex(intptr_t idx) const
Definition object.cc:3404
FunctionPtr FunctionFromIndex(intptr_t idx) const
Definition object.cc:3393
bool IsFutureOrClass() const
Definition object.h:1576
UntaggedClass::ClassLoadingState class_loading_state() const
Definition object.h:1701
bool is_allocated() const
Definition object.h:1783
static ClassPtr NewNativeWrapper(const Library &library, const String &name, int num_fields)
Definition object.cc:5244
void SetFunctions(const Array &value) const
Definition object.cc:3314
void set_type_parameters(const TypeParameters &value) const
Definition object.cc:3492
bool is_synthesized_class() const
Definition object.h:1716
static ClassPtr NewUnmodifiableTypedDataViewClass(intptr_t class_id, IsolateGroup *isolate_group)
Definition object.cc:5353
DART_WARN_UNUSED_RESULT ErrorPtr VerifyEntryPoint() const
Definition object.cc:27446
void CheckReload(const Class &replacement, ProgramReloadContext *context) const
FieldPtr LookupFieldAllowPrivate(const String &name, bool instance_only=false) const
Definition object.cc:6458
ClassPtr Mixin() const
Definition object.cc:3081
bool is_isolate_unsendable_due_to_pragma() const
Definition object.h:2159
bool is_interface_class() const
Definition object.h:1770
void set_direct_implementors(const GrowableObjectArray &implementors) const
Definition object.cc:5827
intptr_t FindInvocationDispatcherFunctionIndex(const Function &needle) const
Definition object.cc:3442
static bool IsClosureClass(ClassPtr cls)
Definition object.h:1580
bool is_finalized() const
Definition object.h:1725
ArrayPtr current_functions() const
Definition object.h:1643
ArrayPtr functions() const
Definition object.h:1648
FieldPtr LookupStaticField(const String &name) const
Definition object.cc:6403
ScriptPtr script() const
Definition object.h:1274
void EnsureDeclarationLoaded() const
Definition object.cc:4968
virtual StringPtr DictionaryName() const
Definition object.h:1272
TypeArgumentsPtr GetInstanceTypeArguments(Thread *thread, const TypeArguments &type_arguments, bool canonicalize=true) const
Definition object.cc:3574
void set_is_isolate_unsendable(bool value) const
Definition object.cc:3194
void set_can_be_future(bool value) const
Definition object.cc:3215
static intptr_t packed_fields_offset()
Definition object.h:4298
static intptr_t InstanceSize()
Definition object.h:4294
ObjectPtr RawContext() const
Definition object.h:12332
ContextPtr GetContext() const
Definition object.h:12334
static intptr_t delayed_type_arguments_offset()
Definition object.h:12320
static intptr_t function_offset()
Definition object.h:12325
virtual uint32_t CanonicalizeHash() const
Definition object.h:12363
void set_delayed_type_arguments(const TypeArguments &args) const
Definition object.h:12317
SmiPtr hash() const
Definition object.h:12354
static intptr_t instantiator_type_arguments_offset()
Definition object.h:12300
bool IsGeneric() const
Definition object.h:12350
static intptr_t function_type_arguments_offset()
Definition object.h:12310
TypeArgumentsPtr instantiator_type_arguments() const
Definition object.h:12294
TypeArgumentsPtr delayed_type_arguments() const
Definition object.h:12314
TypeArgumentsPtr function_type_arguments() const
Definition object.h:12304
static intptr_t hash_offset()
Definition object.h:12355
void set_function_type_arguments(const TypeArguments &args) const
Definition object.h:12307
static intptr_t InstanceSize()
Definition object.h:12357
InstancePtr GetImplicitClosureReceiver() const
Definition object.h:12339
static FunctionPtr FunctionOf(ClosurePtr closure)
Definition object.h:12328
FunctionPtr function() const
Definition object.h:12324
void set_instantiator_type_arguments(const TypeArguments &args) const
Definition object.h:12297
static intptr_t context_offset()
Definition object.h:12344
static intptr_t InstanceSize()
Definition object.h:6202
static intptr_t HeaderSize()
Definition object.h:6197
void PrintToJSONObject(JSONObject *jsobj, bool ref) const
uint8_t * Data() const
Definition object.h:6215
uint32_t Hash() const
Definition object.h:6225
intptr_t Length() const
Definition object.h:6214
static intptr_t InstanceSize(intptr_t len)
Definition object.h:6207
static intptr_t UnroundedSize(CodeSourceMapPtr map)
Definition object.h:6198
static intptr_t UnroundedSize(intptr_t len)
Definition object.h:6201
bool Equals(const CodeSourceMap &other) const
Definition object.h:6217
static intptr_t instructions_offset()
Definition object.h:6752
void set_exception_handlers(const ExceptionHandlers &handlers) const
Definition object.h:7090
FunctionPtr function() const
Definition object.h:7101
uword EntryPoint() const
Definition object.h:6837
void GetInlinedFunctionsAtReturnAddress(intptr_t pc_offset, GrowableArray< const Function * > *functions, GrowableArray< TokenPosition > *token_positions) const
Definition object.h:7056
LocalVarDescriptorsPtr var_descriptors() const
Definition object.h:7067
void Enable() const
Definition object.h:7223
uword UncheckedEntryPoint() const
Definition object.h:6851
ArrayPtr deopt_info_array() const
Definition object.h:6916
void set_code_source_map(const CodeSourceMap &code_source_map) const
Definition object.h:6910
uword Size() const
Definition object.h:6876
static uword PayloadSizeOf(const CodePtr code)
Definition object.h:6877
static bool IsDisabled(CodePtr code)
Definition object.h:7229
static intptr_t owner_offset()
Definition object.h:7120
NOT_IN_PRODUCT(void PrintJSONInlineIntervals(JSONObject *object) const)
void set_pc_descriptors(const PcDescriptors &descriptors) const
Definition object.h:6901
int32_t GetPointerOffsetAt(int index) const
Definition object.h:7186
bool is_alive() const
Definition object.h:6803
PcDescriptorsPtr pc_descriptors() const
Definition object.h:6900
bool is_optimized() const
Definition object.h:6790
classid_t OwnerClassId() const
Definition object.h:7111
CodeSourceMapPtr code_source_map() const
Definition object.h:6906
static uword EntryPointOf(const CodePtr code)
Definition object.h:6838
bool is_force_optimized() const
Definition object.h:6798
static bool ContainsInstructionAt(const CodePtr code, uword pc)
Definition object.h:6893
ObjectPoolPtr object_pool() const
Definition object.h:6781
static intptr_t InstanceSize()
Definition object.h:7134
static uword UncheckedEntryPointOf(const CodePtr code)
Definition object.h:6846
void set_var_descriptors(const LocalVarDescriptors &value) const
Definition object.h:7075
static intptr_t active_instructions_offset()
Definition object.h:6756
static InstructionsPtr InstructionsOf(const CodePtr code)
Definition object.h:6748
bool ContainsInstructionAt(uword addr) const
Definition object.h:6888
bool IsDisabled() const
Definition object.h:7228
static uword PayloadStartOf(const CodePtr code)
Definition object.h:6824
uword MonomorphicUncheckedEntryPoint() const
Definition object.h:6867
bool HasMonomorphicEntry() const
Definition object.h:6812
ObjectPtr owner() const
Definition object.h:7106
ArrayPtr static_calls_target_table() const
Definition object.h:6972
static bool IsDiscarded(const CodePtr code)
Definition object.h:6807
uword MonomorphicEntryPoint() const
Definition object.h:6859
void set_object_pool(ObjectPoolPtr object_pool) const
Definition object.h:7239
static intptr_t entry_point_offset(EntryKind kind=EntryKind::kNormal)
Definition object.h:6766
static intptr_t object_pool_offset()
Definition object.h:6782
static bool IsOptimized(CodePtr code)
Definition object.h:6794
static intptr_t InstanceSize(intptr_t len)
Definition object.h:7139
intptr_t pointer_offsets_length() const
Definition object.h:6786
static classid_t OwnerClassIdOf(CodePtr raw)
Definition object.h:7112
InstructionsPtr active_instructions() const
Definition object.h:6737
ObjectPtr return_address_metadata() const
Definition object.h:7026
CompressedStackMapsPtr compressed_stackmaps() const
Definition object.h:6936
bool IsUnknownDartCode() const
Definition object.h:7216
bool is_discarded() const
Definition object.h:6806
@ kDefaultEntry
Definition object.h:6949
@ kUncheckedEntry
Definition object.h:6950
InstructionsPtr instructions() const
Definition object.h:6747
uword PayloadStart() const
Definition object.h:6823
ExceptionHandlersPtr exception_handlers() const
Definition object.h:7087
static bool HasMonomorphicEntry(const CodePtr code)
Definition object.h:6813
int64_t compile_timestamp() const
Definition object.h:7201
Iterator(const Iterator &it)
Definition object.h:6366
bool Find(uint32_t pc_offset)
Definition object.h:6430
Iterator(const PayloadHandle &maps, const PayloadHandle &global_table)
Definition object.h:6357
bool IsObject(intptr_t bit_index) const
Definition object.h:6461
intptr_t SpillSlotBitCount() const
Definition object.h:6455
RawPayloadHandle(const RawPayloadHandle &)=default
RawPayloadHandle & operator=(const CompressedStackMaps &maps)
Definition object.h:6322
RawPayloadHandle & operator=(CompressedStackMapsPtr maps)
Definition object.h:6328
const UntaggedCompressedStackMaps::Payload * payload() const
Definition object.h:6311
RawPayloadHandle & operator=(const RawPayloadHandle &)=default
RawPayloadHandle & operator=(const UntaggedCompressedStackMaps::Payload *payload)
Definition object.h:6316
bool IsGlobalTable() const
Definition object.h:6283
const uint8_t * data() const
Definition object.h:6248
static intptr_t UnroundedSize(intptr_t length)
Definition object.h:6269
bool Equals(const CompressedStackMaps &other) const
Definition object.h:6251
static bool IsGlobalTable(const CompressedStackMapsPtr raw)
Definition object.h:6284
static CompressedStackMapsPtr NewUsingTable(const void *payload, intptr_t size)
Definition object.h:6293
static CompressedStackMapsPtr NewInlined(const void *payload, intptr_t size)
Definition object.h:6289
static CompressedStackMapsPtr NewGlobalTable(const void *payload, intptr_t size)
Definition object.h:6299
static intptr_t HeaderSize()
Definition object.h:6262
static intptr_t InstanceSize()
Definition object.h:6272
uintptr_t payload_size() const
Definition object.h:6242
bool UsesGlobalTable() const
Definition object.h:6277
static intptr_t UnroundedSize(CompressedStackMapsPtr maps)
Definition object.h:6266
static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw)
Definition object.h:6243
static intptr_t InstanceSize(intptr_t length)
Definition object.h:6273
static bool UsesGlobalTable(const CompressedStackMapsPtr raw)
Definition object.h:6278
static intptr_t InstanceSize()
Definition object.h:12166
static constexpr bool ContainsCompressedPointers()
Definition object.h:12156
static intptr_t InstanceSize()
Definition object.h:12267
static constexpr bool ContainsCompressedPointers()
Definition object.h:12257
static intptr_t InstanceSize()
Definition object.h:7506
static intptr_t InstanceSize(intptr_t len)
Definition object.h:7512
intptr_t num_variables() const
Definition object.h:7455
static intptr_t NumVariables(const ContextPtr context)
Definition object.h:7389
static intptr_t num_variables_offset()
Definition object.h:7386
static bool IsValidLength(intptr_t len)
Definition object.h:7415
static intptr_t variable_offset(intptr_t context_index)
Definition object.h:7410
static intptr_t parent_offset()
Definition object.h:7381
void set_parent(const Context &parent) const
Definition object.h:7378
void SetAt(intptr_t context_index, const Object &value) const
Definition object.h:13277
static intptr_t InstanceSize()
Definition object.h:7419
static intptr_t InstanceSize(intptr_t len)
Definition object.h:7425
ObjectPtr At(intptr_t context_index) const
Definition object.h:7393
intptr_t num_variables() const
Definition object.h:7385
ContextPtr parent() const
Definition object.h:7377
static uword AllocateReadOnlyHandle()
Definition dart.cc:1123
bool HasNext() const
Definition object.h:5020
static intptr_t value_offset()
Definition object.h:10118
static intptr_t InstanceSize()
Definition object.h:10114
double value() const
Definition object.h:10094
static double Value(DoublePtr dbl)
Definition object.h:10095
bool IsClosed() const
Definition object.h:11929
void SetClosed(bool value) const
Definition object.h:11934
static bool IsDynamicLibrary(const Instance &obj)
Definition object.h:11904
void * GetHandle() const
Definition object.h:11910
bool CanBeClosed() const
Definition object.h:11919
static intptr_t InstanceSize()
Definition object.h:11900
void SetCanBeClosed(bool value) const
Definition object.h:11924
void SetHandle(void *value) const
Definition object.h:11915
static intptr_t InstanceSize(intptr_t len)
Definition object.h:6584
static intptr_t InstanceSize()
Definition object.h:6579
static intptr_t InstanceSize()
Definition object.h:11714
virtual uint8_t * Validate(uint8_t *data) const
Definition object.h:11739
void SetData(uint8_t *data) const
Definition object.h:11746
void SetLength(intptr_t value) const
Definition object.h:11741
static bool IsExternalTypedData(const Instance &obj)
Definition object.h:11732
static intptr_t MaxElements(intptr_t class_id)
Definition object.h:11718
static intptr_t InstanceSize()
Definition object.h:4354
ObjectPtr At(intptr_t index, bool concurrent_use=false) const
Definition field_table.h:61
bool is_final() const
Definition object.h:4420
uint16_t kind_bits() const
Definition object.h:4413
FunctionPtr InitializerFunction() const
Definition object.h:4777
bool has_initializer() const
Definition object.h:4586
intptr_t kernel_offset() const
Definition object.h:4468
void set_has_nontrivial_initializer_unsafe(bool has_nontrivial_initializer) const
Definition object.h:4573
bool is_unboxed() const
Definition object.h:4685
void set_is_reflectable(bool value) const
Definition object.h:4433
static intptr_t guarded_cid_offset()
Definition object.h:4642
static intptr_t static_type_exactness_state_offset()
Definition object.h:4624
void set_is_nullable_unsafe(bool val) const
Definition object.h:4735
void set_is_late(bool value) const
Definition object.h:4704
bool IsOriginal() const
Definition object.h:4396
bool NeedsInitializationCheckOnLoad() const
Definition object.h:4679
bool has_pragma() const
Definition object.h:4448
static intptr_t kind_bits_offset()
Definition object.h:4558
void set_is_unboxed(bool b) const
Definition object.h:4693
bool is_reflectable() const
Definition object.h:4432
void set_is_extension_type_member(bool value) const
Definition object.h:4712
void set_has_initializer(bool has_initializer) const
Definition object.h:4596
bool needs_length_check() const
Definition object.h:4670
intptr_t TargetOffset() const
Definition object.h:13220
bool is_late() const
Definition object.h:4422
void set_static_type_exactness_state(StaticTypeExactnessState state) const
Definition object.h:4612
static intptr_t guarded_list_length_in_object_offset_offset()
Definition object.h:4666
void set_is_generic_covariant_impl(bool value) const
Definition object.h:4463
bool is_static() const
Definition object.h:4418
StaticTypeExactnessState static_type_exactness_state() const
Definition object.h:4606
bool is_extension_member() const
Definition object.h:4423
static intptr_t host_offset_or_field_id_offset()
Definition object.h:4496
static intptr_t InstanceSize()
Definition object.h:4531
void SetOffset(intptr_t host_offset_in_bytes, intptr_t target_offset_in_bytes) const
Definition object.h:13237
void set_initializer_changed_after_initialization(bool value) const
Definition object.h:4442
void set_is_extension_member(bool value) const
Definition object.h:4708
StringPtr name() const
Definition object.h:4408
void set_has_pragma(bool value) const
Definition object.h:4449
void set_guarded_cid(intptr_t cid) const
Definition object.h:4633
void set_guarded_list_length_in_object_offset(intptr_t offset) const
Definition object.h:4661
ObjectPtr StaticValue() const
Definition object.h:13253
bool needs_load_guard() const
Definition object.h:4429
bool has_trivial_initializer() const
Definition object.h:4602
bool is_covariant() const
Definition object.h:4454
void set_needs_load_guard(bool value) const
Definition object.h:4716
void set_has_initializer_unsafe(bool has_initializer) const
Definition object.h:4590
void set_is_covariant(bool value) const
Definition object.h:4455
bool is_generic_covariant_impl() const
Definition object.h:4460
void set_has_nontrivial_initializer(bool has_nontrivial_initializer) const
Definition object.h:4580
bool is_nullable_unsafe() const
Definition object.h:4731
intptr_t field_id() const
Definition object.h:13258
void set_guarded_cid_unsafe(intptr_t cid) const
Definition object.h:4638
intptr_t HostOffset() const
Definition object.h:13215
void set_is_nullable(bool val) const
Definition object.h:4726
void set_field_id(intptr_t field_id) const
Definition object.h:13262
static intptr_t initializer_function_offset()
Definition object.h:4782
AbstractTypePtr type() const
Definition object.h:4523
void set_kernel_offset(intptr_t value) const
Definition object.h:4476
static intptr_t TargetOffsetOf(FieldPtr field)
Definition object.h:13229
bool is_instance() const
Definition object.h:4419
virtual StringPtr DictionaryName() const
Definition object.h:4411
bool is_extension_type_member() const
Definition object.h:4426
void set_is_unboxed_unsafe(bool b) const
Definition object.h:4689
bool is_const() const
Definition object.h:4421
void set_field_id_unsafe(intptr_t field_id) const
Definition object.h:13268
void set_guarded_list_length(intptr_t list_length) const
Definition object.h:4651
TokenPosition end_token_pos() const
Definition object.h:4563
TokenPosition token_pos() const
Definition object.h:4562
static intptr_t is_nullable_offset()
Definition object.h:4739
bool has_nontrivial_initializer() const
Definition object.h:4569
void set_static_type_exactness_state_unsafe(StaticTypeExactnessState state) const
Definition object.h:4618
static intptr_t guarded_list_length_offset()
Definition object.h:4656
bool initializer_changed_after_initialization() const
Definition object.h:4439
FinalizerEntryPtr entries_collected() const
Definition object.h:13029
void set_isolate(Isolate *value) const
Definition object.h:13015
SetPtr all_entries() const
Definition object.h:13021
static intptr_t entries_collected_offset()
Definition object.h:13035
static intptr_t all_entries_offset()
Definition object.h:13025
Isolate * isolate() const
Definition object.h:13014
void set_all_entries(const Set &value) const
Definition object.h:13022
static intptr_t detachments_offset()
Definition object.h:13017
static intptr_t isolate_offset()
Definition object.h:13011
void set_entries_collected(const FinalizerEntry &value) const
Definition object.h:13032
void set_value(const Object &value) const
Definition object.h:12945
FinalizerBasePtr finalizer() const
Definition object.h:12964
static intptr_t external_size_offset()
Definition object.h:12982
void set_next(const FinalizerEntry &value) const
Definition object.h:12971
ObjectPtr token() const
Definition object.h:12958
void set_token(const Object &value) const
Definition object.h:12959
void set_detach(const Object &value) const
Definition object.h:12951
ObjectPtr detach() const
Definition object.h:12950
static intptr_t InstanceSize()
Definition object.h:12986
static intptr_t token_offset()
Definition object.h:12960
static intptr_t next_offset()
Definition object.h:12974
static intptr_t value_offset()
Definition object.h:12946
static intptr_t detach_offset()
Definition object.h:12954
ObjectPtr value() const
Definition object.h:12944
FinalizerEntryPtr next() const
Definition object.h:12970
void set_external_size(intptr_t value) const
Definition object.h:12979
static intptr_t finalizer_offset()
Definition object.h:12966
intptr_t external_size() const
Definition object.h:12978
static intptr_t callback_offset()
Definition object.h:13051
static intptr_t type_arguments_offset()
Definition object.h:13046
static intptr_t InstanceSize()
Definition object.h:13055
ObjectPtr callback() const
Definition object.h:13050
static intptr_t value_offset()
Definition object.h:11171
static intptr_t InstanceSize()
Definition object.h:11167
static intptr_t InstanceSize()
Definition object.h:11236
static intptr_t value_offset()
Definition object.h:11240
static intptr_t NumOptionalParametersOf(FunctionTypePtr ptr)
Definition object.h:9601
TypeParametersPtr type_parameters() const
Definition object.h:9707
intptr_t NumOptionalNamedParameters() const
Definition object.h:9621
intptr_t num_implicit_parameters() const
Definition object.h:9565
static intptr_t parameter_types_offset()
Definition object.h:9660
static bool HasOptionalPositionalParameters(FunctionTypePtr ptr)
Definition object.h:9594
AbstractTypePtr result_type() const
Definition object.h:9650
intptr_t NumOptionalPositionalParameters() const
Definition object.h:9614
static bool HasOptionalParameters(FunctionTypePtr ptr)
Definition object.h:9578
static intptr_t packed_parameter_counts_offset()
Definition object.h:9634
ArrayPtr named_parameter_names() const
Definition object.h:9669
static intptr_t NumFixedParametersOf(FunctionTypePtr ptr)
Definition object.h:9571
intptr_t NumParentTypeArguments() const
Definition object.h:9550
static intptr_t NumParentTypeArgumentsOf(FunctionTypePtr ptr)
Definition object.h:9545
intptr_t NumTypeArguments() const
Definition object.h:9563
static intptr_t NumTypeArgumentsOf(FunctionTypePtr ptr)
Definition object.h:9560
bool HasOptionalNamedParameters() const
Definition object.h:9589
static intptr_t named_parameter_names_offset()
Definition object.h:9673
bool HasOptionalParameters() const
Definition object.h:9583
bool HasOptionalPositionalParameters() const
Definition object.h:9597
bool HasGenericParent() const
Definition object.h:9730
static intptr_t NameArrayLengthIncludingFlags(intptr_t num_parameters)
static intptr_t NumParametersOf(FunctionTypePtr ptr)
Definition object.h:9625
intptr_t NumParameters() const
Definition object.h:9628
static intptr_t NumOptionalNamedParametersOf(FunctionTypePtr ptr)
Definition object.h:9618
static bool HasOptionalNamedParameters(FunctionTypePtr ptr)
Definition object.h:9585
static bool IsGeneric(FunctionTypePtr ptr)
Definition object.h:9724
intptr_t num_fixed_parameters() const
Definition object.h:9575
bool IsGeneric() const
Definition object.h:9727
static intptr_t NumTypeParametersOf(FunctionTypePtr ptr)
Definition object.h:9554
intptr_t NumTypeParameters() const
Definition object.h:9558
virtual classid_t type_class_id() const
Definition object.h:9510
static intptr_t InstanceSize()
Definition object.h:9756
virtual bool HasTypeClass() const
Definition object.h:9508
static intptr_t type_parameters_offset()
Definition object.h:9711
uint16_t packed_type_parameter_counts() const
Definition object.h:9637
intptr_t NumOptionalParameters() const
Definition object.h:9605
ArrayPtr parameter_types() const
Definition object.h:9658
uint32_t packed_parameter_counts() const
Definition object.h:9630
static intptr_t NumOptionalPositionalParametersOf(FunctionTypePtr ptr)
Definition object.h:9611
static intptr_t packed_type_parameter_counts_offset()
Definition object.h:9641
bool IsSyncGenerator() const
Definition object.h:3947
bool is_unboxed_integer_parameter_at(intptr_t index) const
Definition object.h:3763
bool IsRecognized() const
Definition object.h:3604
bool has_unboxed_return() const
Definition object.h:3783
bool HasUnboxedParameters() const
Definition object.h:3816
COMPILE_ASSERT(MethodRecognizer::kNumRecognizedMethods<(1<< kRecognizedTagSize))
CodePtr CurrentCode() const
Definition object.h:3157
virtual StringPtr DictionaryName() const
Definition object.h:2985
static uword EntryPointOf(const FunctionPtr function)
Definition object.h:3179
bool IsDispatcherOrImplicitAccessor() const
Definition object.h:3822
bool HasParent() const
Definition object.h:3910
bool IsIrregexpFunction() const
Definition object.h:3878
COMPILE_ASSERT(kNumTagBits<=(kBitsPerByte *sizeof(decltype(UntaggedFunction::kind_tag_))))
bool WasExecuted() const
Definition object.h:4100
void set_unboxed_integer_return() const
Definition object.h:3721
bool has_unboxed_double_return() const
Definition object.h:3799
bool IsImplicitInstanceClosureFunction() const
Definition object.h:3904
void SetOptimizedInstructionCountClamped(uintptr_t value) const
Definition object.h:3552
bool IsImplicitClosureFunction() const
Definition object.h:3883
void set_kernel_offset(intptr_t value) const
Definition object.h:3538
bool IsNoSuchMethodDispatcher() const
Definition object.h:3268
static bool IsFfiCallbackTrampoline(FunctionPtr function)
Definition object.h:3921
bool IsRegularFunction() const
Definition object.h:3260
bool IsImplicitGetterOrSetter() const
Definition object.h:3298
static bool is_visible(FunctionPtr f)
Definition object.h:4163
bool has_unboxed_integer_return() const
Definition object.h:3791
void set_end_token_pos(TokenPosition value) const
Definition object.h:3442
static intptr_t code_offset()
Definition object.h:3176
bool IsDynamicClosureCallDispatcher() const
Definition object.h:3288
ArrayPtr parameter_types() const
Definition object.h:3087
bool MakesCopyOfParameters() const
Definition object.h:3494
bool IsFieldInitializer() const
Definition object.h:3865
bool NeedsTypeArgumentTypeChecks() const
Definition object.h:3412
bool has_unboxed_record_return() const
Definition object.h:3807
bool IsStaticFunction() const
Definition object.h:3382
bool IsDynamicFunction(bool allow_abstract=false) const
Definition object.h:3354
ObjectPtr RawOwner() const
Definition object.h:3063
void set_unboxed_double_parameter_at(intptr_t index) const
Definition object.h:3708
bool IsSuspendableFunction() const
Definition object.h:3937
static intptr_t InstanceSize()
Definition object.h:3965
void SetUsageCounter(intptr_t value) const
Definition object.h:4093
bool IsImplicitGetterFunction() const
Definition object.h:3842
void set_unboxed_integer_parameter_at(intptr_t index) const
Definition object.h:3696
static constexpr intptr_t maximum_unboxed_parameter_count()
Definition object.h:3684
bool IsGetterFunction() const
Definition object.h:3837
bool HasAwaiterLink() const
Definition object.h:3219
StringPtr name() const
Definition object.h:2972
TokenPosition token_pos() const
Definition object.h:3426
static intptr_t kind_tag_offset()
Definition object.h:4106
uword entry_point() const
Definition object.h:3178
PRECOMPILER_WSR_FIELD_DECLARATION(FunctionType, signature)
uint32_t packed_fields() const
Definition object.h:3462
bool IsClosureFunction() const
Definition object.h:3871
bool IsFfiCallbackTrampoline() const
Definition object.h:3918
bool IsImplicitStaticGetterFunction() const
Definition object.h:3848
static bool IsImplicitClosureFunction(FunctionPtr func)
Definition object.h:3886
void set_unboxed_record_return() const
Definition object.h:3742
intptr_t kernel_offset() const
Definition object.h:3530
static CodePtr CurrentCodeOf(const FunctionPtr function)
Definition object.h:3161
static intptr_t signature_offset()
Definition object.h:3029
bool is_unboxed_parameter_at(intptr_t index) const
Definition object.h:3753
void SetOptimizedCallSiteCountClamped(uintptr_t value) const
Definition object.h:3557
bool IsRecordFieldGetter() const
Definition object.h:3272
bool IsAsyncFunction() const
Definition object.h:3942
bool IsInvokeFieldDispatcher() const
Definition object.h:3276
void reset_unboxed_parameters_and_return() const
Definition object.h:3689
bool IsAsyncGenerator() const
Definition object.h:3952
bool IsNonImplicitClosureFunction() const
Definition object.h:3891
bool HasSavedArgumentsDescriptor() const
Definition object.h:3253
bool IsImplicitStaticClosureFunction() const
Definition object.h:3897
bool IsMethodExtractor() const
Definition object.h:3264
CodePtr unoptimized_code() const
Definition object.h:3165
static intptr_t entry_point_offset(CodeEntryKind entry_kind=CodeEntryKind::kNormal)
Definition object.h:3183
bool HasThisParameter() const
Definition object.h:3349
bool is_unboxed_double_parameter_at(intptr_t index) const
Definition object.h:3773
bool is_optimizable() const
Definition object.h:4178
bool IsFactory() const
Definition object.h:3347
bool HasGenericParent() const
Definition object.h:3123
void SetWasExecuted(bool value) const
Definition object.h:4102
bool HasUnboxedReturnValue() const
Definition object.h:3819
static UntaggedFunction::Kind KindOf(FunctionPtr func)
Definition object.h:3330
UntaggedFunction::AsyncModifier modifier() const
Definition object.h:3334
TypeParametersPtr type_parameters() const
Definition object.h:3109
bool NeedsArgumentTypeChecks() const
Definition object.h:3416
bool IsLocalFunction() const
Definition object.h:3913
bool IsGenerativeConstructor() const
Definition object.h:3343
bool IsDynamicInvocationForwarder() const
Definition object.h:3294
UntaggedFunction::Kind kind() const
Definition object.h:3329
TokenPosition end_token_pos() const
Definition object.h:3435
static intptr_t unchecked_entry_point_offset()
Definition object.h:3195
bool IsImplicitSetterFunction() const
Definition object.h:3858
static intptr_t data_offset()
Definition object.h:4104
bool IsDynamicInvokeFieldDispatcher() const
Definition object.h:3280
void set_is_optimizable(bool value) const
Definition object.h:4185
void set_unboxed_double_return() const
Definition object.h:3731
MethodRecognizer::Kind recognized_kind() const
Definition object.h:3599
bool IsConstructor() const
Definition object.h:3340
bool HasImplicitClosureFunction() const
Definition object.h:3306
bool IsSetterFunction() const
Definition object.h:3853
AbstractTypePtr result_type() const
Definition object.h:3079
static intptr_t InstanceSize()
Definition object.h:13174
static intptr_t type_arguments_offset()
Definition object.h:13181
virtual TypeArgumentsPtr GetTypeArguments() const
Definition object.h:13178
virtual InstancePtr CanonicalizeLocked(Thread *thread) const
Definition object.h:11098
void SetData(const Array &value) const
Definition object.h:11057
void SetLength(intptr_t value) const
Definition object.h:11050
static SmiPtr NoSafepointLength(const GrowableObjectArrayPtr array)
Definition object.h:11126
virtual void SetTypeArguments(const TypeArguments &value) const
Definition object.h:11081
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition object.h:11118
static ArrayPtr NoSafepointData(const GrowableObjectArrayPtr array)
Definition object.h:11130
static intptr_t type_arguments_offset()
Definition object.h:11103
virtual TypeArgumentsPtr GetTypeArguments() const
Definition object.h:11078
static intptr_t InstanceSize()
Definition object.h:11114
static intptr_t data_offset()
Definition object.h:11110
intptr_t Length() const
Definition object.h:11046
ObjectPtr At(intptr_t index) const
Definition object.h:11059
virtual bool CanonicalizeEquals(const Instance &other) const
Definition object.h:11092
ArrayPtr data() const
Definition object.h:11056
void SetAt(intptr_t index, const Object &value) const
Definition object.h:11065
intptr_t Capacity() const
Definition object.h:11041
static intptr_t length_offset()
Definition object.h:11107
@ kNew
Definition heap.h:38
static intptr_t ExactnessIndexFor(intptr_t num_args)
Definition object.h:2735
static intptr_t owner_offset()
Definition object.h:2574
static intptr_t CodeIndexFor(intptr_t num_args)
Definition object.h:2733
static intptr_t TargetIndexFor(intptr_t num_args)
Definition object.h:2732
bool receiver_cannot_be_smi() const
Definition object.h:2767
static intptr_t NumArgsTestedMask()
Definition object.h:2566
intptr_t deopt_id() const
Definition object.h:2448
ICDataPtr AsUnaryClassChecks() const
Definition object.h:2671
static intptr_t entries_offset()
Definition object.h:2570
static intptr_t state_bits_offset()
Definition object.h:2560
static intptr_t CountIndexFor(intptr_t num_args)
Definition object.h:2729
static intptr_t NumArgsTestedShift()
Definition object.h:2564
bool IsOriginal() const
Definition object.h:2444
ArrayPtr entries() const
Definition object.h:2763
bool IsValidEntryIndex(intptr_t index) const
Definition object.h:2552
@ kNumRebindRules
Definition object.h:2529
static intptr_t InstanceSize()
Definition object.h:2556
void Clear(const CallSiteResetter &proof_of_reload) const
Definition object.h:2583
bool is_tracking_exactness() const
Definition object.h:2463
AbstractTypePtr receivers_static_type() const
Definition object.h:2460
void set_receiver_cannot_be_smi(bool value) const
Definition object.h:2771
static intptr_t receivers_static_type_offset()
Definition object.h:2577
void set_is_megamorphic(bool value) const
Definition object.h:2535
bool HasDeoptReasons() const
Definition object.h:2508
static intptr_t EntryPointIndexFor(intptr_t num_args)
Definition object.h:2730
static intptr_t InstanceSize()
Definition object.h:11020
static intptr_t InstanceSize(intptr_t len)
Definition object.h:11022
static constexpr bool ContainsCompressedPointers()
Definition object.h:11012
static constexpr bool ContainsCompressedPointers()
Definition object.h:12071
static intptr_t data_offset()
Definition object.h:12075
intptr_t GetNativeField(int index) const
Definition object.h:13281
static intptr_t NextFieldOffset()
Definition object.h:8326
uint16_t NumNativeFields() const
Definition object.h:8251
static intptr_t InstanceSize()
Definition object.h:8308
static intptr_t NativeFieldsOffset()
Definition object.h:8328
void GetNativeFields(uint16_t num_fields, intptr_t *field_values) const
Definition object.h:13292
static intptr_t UnroundedSize()
Definition object.h:8307
intptr_t SizeFromClass() const
Definition object.h:8187
bool IsValidNativeIndex(int index) const
Definition object.h:8241
static intptr_t InstanceSize(intptr_t size)
Definition object.h:5912
static intptr_t HeaderSize()
Definition object.h:5920
static intptr_t InstanceSize()
Definition object.h:5906
static intptr_t Size(const InstructionsSectionPtr instr)
Definition object.h:5903
static intptr_t InstanceSize()
Definition object.h:5942
bool ContainsPc(uword pc) const
Definition object.h:5951
static uword PayloadStartAt(InstructionsTablePtr table, intptr_t index)
uword PayloadStartAt(intptr_t index) const
Definition object.h:5967
const UntaggedInstructionsTable::Data * rodata() const
Definition object.h:5962
static uword MonomorphicEntryPoint(const InstructionsPtr instr)
Definition object.h:5759
uint32_t Hash() const
Definition object.h:5845
static intptr_t InstanceSize()
Definition object.h:5804
static InstructionsPtr FromPayloadStart(uword payload_start)
Definition object.h:5817
static intptr_t InstanceSize(intptr_t size)
Definition object.h:5810
uword MonomorphicEntryPoint() const
Definition object.h:5717
uword EntryPoint() const
Definition object.h:5718
uword PayloadStart() const
Definition object.h:5716
static uword PayloadStart(const InstructionsPtr instr)
Definition object.h:5719
static uint32_t Hash(const InstructionsPtr instr)
Definition object.h:5847
static intptr_t HeaderSize()
Definition object.h:5796
bool Equals(const Instructions &other) const
Definition object.h:5825
static uword EntryPoint(const InstructionsPtr instr)
Definition object.h:5768
static intptr_t Size(const InstructionsPtr instr)
Definition object.h:5712
intptr_t Size() const
Definition object.h:5711
static bool Equals(InstructionsPtr a, InstructionsPtr b)
Definition object.h:5829
static intptr_t InstanceSize()
Definition object.h:11205
static intptr_t value_offset()
Definition object.h:11209
static int64_t GetInt64Value(const IntegerPtr obj)
Definition object.h:9949
virtual ObjectPtr HashCode() const
Definition object.h:9917
virtual bool OperatorEquals(const Instance &other) const
Definition object.h:9908
virtual int64_t AsTruncatedInt64Value() const
Definition object.h:9924
virtual bool CanonicalizeEquals(const Instance &other) const
Definition object.h:9911
static IsolateGroup * Current()
Definition isolate.h:534
ClassTable * class_table() const
Definition isolate.h:491
FieldTable * field_table() const
Definition isolate.h:953
static Isolate * Current()
Definition isolate.h:939
static intptr_t InstanceSize()
Definition object.h:5458
ArrayPtr libraries_cache() const
Definition object.h:5497
ArrayPtr constants() const
Definition object.h:5492
ArrayPtr scripts() const
Definition object.h:5489
TypedDataViewPtr constants_table() const
Definition object.h:5483
TypedDataPtr string_offsets() const
Definition object.h:5462
TypedDataViewPtr string_data() const
Definition object.h:5467
ArrayPtr classes_cache() const
Definition object.h:5504
TypedDataViewPtr metadata_mappings() const
Definition object.h:5475
TypedDataPtr canonical_names() const
Definition object.h:5469
TypedDataBasePtr kernel_component() const
Definition object.h:5464
TypedDataViewPtr metadata_payloads() const
Definition object.h:5471
static intptr_t InstanceSize()
Definition object.h:8058
Report::Kind kind() const
Definition object.h:8051
virtual StringPtr DictionaryName() const
Definition object.h:8423
static intptr_t InstanceSize()
Definition object.h:8434
bool is_deferred_load() const
Definition object.h:8432
intptr_t num_imports() const
Definition object.h:8426
StringPtr name() const
Definition object.h:8422
ArrayPtr imports() const
Definition object.h:8425
LibraryPtr importer() const
Definition object.h:8427
intptr_t num_imports() const
Definition object.h:5190
void set_native_entry_symbol_resolver(Dart_NativeEntrySymbol native_symbol_resolver) const
Definition object.h:5213
void set_is_dart_scheme(bool value) const
Definition object.h:5262
bool Loaded() const
Definition object.h:5082
bool LoadRequested() const
Definition object.h:5074
GrowableObjectArrayPtr used_scripts() const
Definition object.h:5182
ArrayPtr dependencies() const
Definition object.h:5194
void set_native_entry_resolver(Dart_NativeEntryResolver value) const
Definition object.h:5204
bool LoadNotStarted() const
Definition object.h:5071
void set_ffi_native_resolver(Dart_FfiNativeResolver value) const
Definition object.h:5225
bool is_in_fullsnapshot() const
Definition object.h:5231
ClassPtr toplevel_class() const
Definition object.h:5179
StringPtr name() const
Definition object.h:5065
intptr_t index() const
Definition object.h:5241
intptr_t UrlHash() const
Definition object.h:13327
static intptr_t InstanceSize()
Definition object.h:5090
Dart_NativeEntrySymbol native_entry_symbol_resolver() const
Definition object.h:5209
void set_debuggable(bool value) const
Definition object.h:5255
void set_is_in_fullsnapshot(bool value) const
Definition object.h:5234
bool is_dart_scheme() const
Definition object.h:5259
ArrayPtr exports() const
Definition object.h:5188
LoadingUnitPtr loading_unit() const
Definition object.h:5087
Dart_NativeEntryResolver native_entry_resolver() const
Definition object.h:5200
void set_index(intptr_t value) const
Definition object.h:5242
bool IsDebuggable() const
Definition object.h:5252
void set_kernel_library_index(intptr_t value) const
Definition object.h:5288
StringPtr private_key() const
Definition object.h:5070
StringPtr url() const
Definition object.h:5068
bool LoadInProgress() const
Definition object.h:5077
intptr_t kernel_library_index() const
Definition object.h:5280
Dart_FfiNativeResolver ffi_native_resolver() const
Definition object.h:5221
KernelProgramInfoPtr kernel_program_info() const
Definition object.h:5272
ArrayPtr imports() const
Definition object.h:5187
static StringPtr UrlOf(LibraryPtr lib)
Definition object.h:5069
void set_hash_mask(intptr_t value) const
Definition object.h:12016
bool IsImmutable() const
Definition object.h:11989
void set_data(const Array &value) const
Definition object.h:12013
static intptr_t IndexSizeToHashMask(intptr_t index_size)
Definition object.h:11947
static intptr_t deleted_keys_offset()
Definition object.h:11980
TypedDataPtr index() const
Definition object.h:12006
SmiPtr deleted_keys() const
Definition object.h:12025
ArrayPtr data() const
Definition object.h:12012
static intptr_t data_offset()
Definition object.h:11968
SmiPtr hash_mask() const
Definition object.h:12015
virtual void SetTypeArguments(const TypeArguments &value) const
Definition object.h:11996
void set_deleted_keys(intptr_t value) const
Definition object.h:12026
static intptr_t InstanceSize()
Definition object.h:11956
static const LinkedHashBase & Cast(const Object &obj)
Definition object.h:11984
static intptr_t type_arguments_offset()
Definition object.h:11960
static intptr_t index_offset()
Definition object.h:11964
void set_used_data(intptr_t value) const
Definition object.h:12021
static intptr_t used_data_offset()
Definition object.h:11976
SmiPtr used_data() const
Definition object.h:12020
void set_index(const TypedData &value) const
Definition object.h:12007
intptr_t Length() const
Definition object.h:12030
static intptr_t hash_mask_offset()
Definition object.h:11972
virtual TypeArgumentsPtr GetTypeArguments() const
Definition object.h:11993
bool loaded() const
Definition object.h:7961
const uint8_t * instructions_image() const
Definition object.h:7998
intptr_t id() const
Definition object.h:7956
LoadingUnitPtr parent() const
Definition object.h:7951
COMPILE_ASSERT(kIllegalId==WeakTable::kNoValue)
static intptr_t InstanceSize()
Definition object.h:7944
void set_loaded(bool value) const
Definition object.h:7966
bool load_outstanding() const
Definition object.h:7980
void set_instructions_image(const uint8_t *value) const
Definition object.h:8003
bool has_instructions_image() const
Definition object.h:8007
ArrayPtr base_objects() const
Definition object.h:7953
void set_load_outstanding() const
Definition object.h:7984
static intptr_t InstanceSize(intptr_t len)
Definition object.h:6031
static intptr_t InstanceSize()
Definition object.h:6026
Iterator(const Map &map)
Definition object.h:12107
ObjectPtr CurrentValue() const
Definition object.h:12129
ObjectPtr CurrentKey() const
Definition object.h:12127
static intptr_t InstanceSize()
Definition object.h:12085
static intptr_t InstanceSize()
Definition object.h:7605
static intptr_t buckets_offset()
Definition object.h:7589
static intptr_t arguments_descriptor_offset()
Definition object.h:7595
static intptr_t mask_offset()
Definition object.h:7592
static intptr_t InstanceSize()
Definition object.h:10069
virtual bool IsZero() const
Definition object.h:10056
virtual bool IsNegative() const
Definition object.h:10057
static int64_t Value(MintPtr mint)
Definition object.h:10054
static intptr_t value_offset()
Definition object.h:10053
int64_t value() const
Definition object.h:10052
ObjectPtr referent() const
Definition object.h:13094
static intptr_t InstanceSize()
Definition object.h:13117
void set_referent(const Object &referent) const
Definition object.h:13096
static intptr_t entrypoint_offset()
Definition object.h:2341
static intptr_t expected_cid_offset()
Definition object.h:2337
static MonomorphicSmiableCallPtr New(classid_t expected_cid, const Code &target)
Definition object.cc:16397
static intptr_t InstanceSize()
Definition object.h:2330
classid_t expected_cid() const
Definition object.h:2328
ArrayPtr hide_names() const
Definition object.h:5421
static intptr_t InstanceSize()
Definition object.h:5424
ArrayPtr show_names() const
Definition object.h:5420
LibraryPtr target() const
Definition object.h:5419
LibraryPtr owner() const
Definition object.h:5422
static intptr_t callback_offset()
Definition object.h:13074
void set_callback(const Pointer &value) const
Definition object.h:13071
static intptr_t InstanceSize()
Definition object.h:13078
PointerPtr callback() const
Definition object.h:13070
EntryType TypeAt(intptr_t index) const
Definition object.h:5567
ObjectPtr ObjectAt(intptr_t index) const
Definition object.h:5599
intptr_t Length() const
Definition object.h:5543
uword RawValueAt(intptr_t index) const
Definition object.h:5611
void SetObjectAt(intptr_t index, const Object &obj) const
Definition object.h:5605
static uint8_t EncodeBits(EntryType type, Patchability patchable, SnapshotBehavior snapshot_behavior)
Definition object.h:5582
SnapshotBehavior SnapshotBehaviorAt(intptr_t index) const
Definition object.h:5577
static intptr_t InstanceSize()
Definition object.h:5620
void SetRawValueAt(intptr_t index, uword raw_value) const
Definition object.h:5615
static intptr_t length_offset()
Definition object.h:5548
static intptr_t OffsetFromIndex(intptr_t index)
Definition object.h:5659
void SetLength(intptr_t value) const
Definition object.h:5544
static intptr_t element_offset(intptr_t index)
Definition object.h:5554
Patchability PatchableAt(intptr_t index) const
Definition object.h:5572
static intptr_t data_offset()
Definition object.h:5551
static intptr_t IndexFromOffset(intptr_t offset)
Definition object.h:5647
static intptr_t InstanceSize(intptr_t len)
Definition object.h:5630
void SetTypeAt(intptr_t index, EntryType type, Patchability patchable, SnapshotBehavior snapshot_behavior) const
Definition object.h:5589
ObjectPtr Decompress(uword heap_base) const
UntaggedObject * untag() const
intptr_t GetClassId() const
Definition raw_object.h:864
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:2960
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:2820
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:13201
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:2808
bool InVMIsolateHeap() const
Definition object.h:395
static ClassPtr megamorphic_cache_class()
Definition object.h:564
virtual StringPtr DictionaryName() const
Definition object.cc:2685
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:2681
static bool ShouldHaveImmutabilityBitSet(classid_t class_id)
Definition object.cc:2689
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
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
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 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:1677
ClassPtr clazz() const
Definition object.h:13192
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:10515
static intptr_t UnroundedSize(OneByteStringPtr str)
Definition object.h:10537
static intptr_t data_offset()
Definition object.h:10533
static intptr_t InstanceSize(intptr_t len)
Definition object.h:10548
static OneByteStringPtr New(const char *c_string, Heap::Space space=Heap::kNew)
Definition object.h:10555
static intptr_t InstanceSize()
Definition object.h:10543
static OneByteStringPtr null()
Definition object.h:10603
static intptr_t UnroundedSize(intptr_t len)
Definition object.h:10540
static uint16_t CharAt(OneByteStringPtr str, intptr_t index)
Definition object.h:10510
static uint16_t CharAt(const String &str, intptr_t index)
Definition object.h:10504
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:2250
KernelProgramInfoPtr kernel_program_info() const
Definition object.h:2265
void set_kernel_program_info(const KernelProgramInfo &info) const
Definition object.cc:7928
static bool IsInFullSnapshot(PatchClassPtr cls)
Definition object.h:2274
ScriptPtr script() const
Definition object.h:2251
void set_kernel_library_index(intptr_t index) const
Definition object.h:2260
intptr_t kernel_library_index() const
Definition object.h:2253
static intptr_t InstanceSize()
Definition object.h:2271
Iterator(const PcDescriptors &descriptors, intptr_t kind_mask)
Definition object.h:6085
intptr_t YieldIndex() const
Definition object.h:6133
TokenPosition TokenPos() const
Definition object.h:6129
intptr_t DeoptId() const
Definition object.h:6128
intptr_t TryIndex() const
Definition object.h:6132
UntaggedPcDescriptors::Kind Kind() const
Definition object.h:6134
static intptr_t UnroundedSize(PcDescriptorsPtr desc)
Definition object.h:6056
static intptr_t HeaderSize()
Definition object.h:6055
intptr_t Length() const
Definition object.cc:15826
bool Equals(const PcDescriptors &other) const
Definition object.h:6167
static void PrintHeaderString()
static intptr_t InstanceSize(intptr_t len)
Definition object.h:6065
static intptr_t InstanceSize()
Definition object.h:6060
static intptr_t UnroundedSize(intptr_t len)
Definition object.h:6059
static intptr_t data_offset()
Definition object.h:11479
static intptr_t type_arguments_offset()
Definition object.h:11876
size_t NativeAddress() const
Definition object.h:11867
void SetNativeAddress(size_t address) const
Definition object.h:11871
static intptr_t InstanceSize()
Definition object.h:11861
AbstractTypePtr type_argument() const
Definition object.h:11883
StringPtr debug_name() const
Definition object.h:12442
StackTracePtr allocation_location() const
Definition object.h:12438
InstancePtr handler() const
Definition object.h:12412
static intptr_t InstanceSize()
Definition object.h:12445
void set_handler(const Instance &value) const
Definition object.h:12413
void set_keep_isolate_alive(bool value) const
Definition object.h:12431
void set_is_open(bool value) const
Definition object.h:12423
static intptr_t handler_offset()
Definition object.h:12416
static intptr_t send_port_offset()
Definition object.h:12407
SendPortPtr send_port() const
Definition object.h:12406
bool is_open() const
Definition object.h:12420
Dart_Port Id() const
Definition object.h:12410
bool keep_isolate_alive() const
Definition object.h:12428
static RecordShape ForUnnamed(intptr_t num_fields)
Definition object.h:11282
bool operator!=(const RecordShape &other) const
Definition object.h:11301
RecordShape(SmiPtr smi_value)
Definition object.h:11274
RecordShape(intptr_t num_fields, intptr_t field_names_index)
Definition object.h:11277
intptr_t field_names_index() const
Definition object.h:11290
intptr_t AsInt() const
Definition object.h:11296
intptr_t num_fields() const
Definition object.h:11288
bool operator==(const RecordShape &other) const
Definition object.h:11298
bool HasNamedFields() const
Definition object.h:11286
RecordShape(intptr_t value)
Definition object.h:11273
SmiPtr AsSmi() const
Definition object.h:11294
RecordShape shape() const
Definition object.h:11362
virtual classid_t type_class_id() const
Definition object.h:11327
intptr_t NumFields() const
Definition object.h:13366
static intptr_t InstanceSize()
Definition object.h:11376
ArrayPtr field_types() const
Definition object.h:11364
virtual bool HasTypeClass() const
Definition object.h:11325
ArrayPtr GetFieldNames(Thread *thread) const
Definition object.h:11467
static intptr_t InstanceSize(intptr_t num_fields)
Definition object.h:11440
static intptr_t shape_offset()
Definition object.h:11405
RecordShape shape() const
Definition object.h:11404
static intptr_t InstanceSize()
Definition object.h:11434
static intptr_t NumFields(RecordPtr ptr)
Definition object.h:11400
intptr_t num_fields() const
Definition object.h:11399
static intptr_t field_index_at_offset(intptr_t offset_in_bytes)
Definition object.h:11426
void SetFieldAt(intptr_t field_index, const Object &value) const
Definition object.h:11410
static intptr_t field_offset(intptr_t index)
Definition object.h:11422
ObjectPtr FieldAt(intptr_t field_index) const
Definition object.h:11407
bool NeedsUnicodeCaseEquivalents()
Definition object.h:12702
bool operator!=(const RegExpFlags &other) const
Definition object.h:12721
bool IsGlobal() const
Definition object.h:12696
void SetMultiLine()
Definition object.h:12710
bool IsMultiLine() const
Definition object.h:12698
int value() const
Definition object.h:12716
bool IsUnicode() const
Definition object.h:12699
bool IsDotAll() const
Definition object.h:12700
RegExpFlags(int value)
Definition object.h:12694
bool operator==(const RegExpFlags &other) const
Definition object.h:12718
bool IgnoreCase() const
Definition object.h:12697
void SetIgnoreCase()
Definition object.h:12709
TypedDataPtr bytecode(bool is_one_byte, bool sticky) const
Definition object.h:12777
void set_is_simple() const
Definition object.h:12856
bool is_complex() const
Definition object.h:12763
void set_is_multi_line() const
Definition object.h:12847
void set_is_unicode() const
Definition object.h:12850
StringPtr pattern() const
Definition object.h:12771
void set_num_bracket_expressions(const Smi &value) const
bool is_initialized() const
Definition object.h:12761
ArrayPtr capture_name_map() const
Definition object.h:12775
void set_is_complex() const
Definition object.h:12857
void set_is_dot_all() const
Definition object.h:12853
static intptr_t function_offset(intptr_t cid, bool sticky)
Definition object.h:12789
void set_num_bracket_expressions(SmiPtr value) const
static intptr_t InstanceSize()
Definition object.h:12875
intptr_t num_bracket_expressions() const
Definition object.h:12772
void set_is_ignore_case() const
Definition object.h:12844
void set_flags(RegExpFlags flags) const
Definition object.h:12868
RegExpFlags flags() const
Definition object.h:12865
FunctionPtr function(intptr_t cid, bool sticky) const
Definition object.h:12810
intptr_t num_registers(bool is_one_byte) const
Definition object.h:12765
void set_num_registers(bool is_one_byte, intptr_t value) const
Definition object.h:12858
void set_is_global() const
Definition object.h:12841
bool is_simple() const
Definition object.h:12762
static intptr_t line_starts_offset()
Definition object.h:4935
intptr_t kernel_script_index() const
Definition object.h:4933
intptr_t col_offset() const
Definition object.h:4915
int64_t load_timestamp() const
Definition object.h:4921
static intptr_t InstanceSize()
Definition object.h:4974
StringPtr url() const
Definition object.h:4903
intptr_t line_offset() const
Definition object.h:4914
Dart_Port Id() const
Definition object.h:12464
static intptr_t InstanceSize()
Definition object.h:12472
Dart_Port origin_id() const
Definition object.h:12466
void set_origin_id(Dart_Port id) const
Definition object.h:12467
static intptr_t InstanceSize()
Definition object.h:7556
ObjectPtr CurrentKey() const
Definition object.h:12230
Iterator(const Set &set)
Definition object.h:12210
static intptr_t InstanceSize()
Definition object.h:12188
static SingleTargetCachePtr New()
Definition object.cc:16368
void set_target(const Code &target) const
Definition object.cc:16360
static intptr_t InstanceSize()
Definition object.h:2315
DEFINE_NON_POINTER_FIELD_ACCESSORS(intptr_t, lower_limit)
CodePtr target() const
Definition object.h:2295
DEFINE_NON_POINTER_FIELD_ACCESSORS(intptr_t, upper_limit)
static intptr_t target_offset()
Definition object.h:2297
DEFINE_NON_POINTER_FIELD_ACCESSORS(uword, entry_point)
static bool IsMatch(const Object &a, const Object &b)
Definition object.h:10037
static uword Hash(const Object &obj)
Definition object.h:10041
static bool ReportStats()
Definition object.h:10035
static const char * Name()
Definition object.h:10034
static SmiPtr New(intptr_t value)
Definition object.h:9985
static intptr_t InstanceSize()
Definition object.h:9983
intptr_t Value() const
Definition object.h:9969
static intptr_t RawValue(intptr_t value)
Definition object.h:10001
friend class Class
Definition object.h:10026
static bool IsValid(int64_t value)
Definition object.h:10005
virtual bool IsZero() const
Definition object.h:9972
static ClassPtr Class()
virtual bool IsNegative() const
Definition object.h:9973
static intptr_t Value(const SmiPtr raw_smi)
Definition object.h:9994
void operator^=(ObjectPtr value)
Definition object.h:10011
virtual bool FitsIntoSmi() const
Definition object.h:9979
void operator=(SmiPtr value)
Definition object.h:10007
TypedDataPtr pc_offset_array() const
Definition object.h:12544
static intptr_t InstanceSize()
Definition object.h:12565
ArrayPtr code_array() const
Definition object.h:12540
StackTracePtr async_link() const
Definition object.h:12536
static StaticTypeExactnessState NotTracking()
void Add(const uint8_t *code_units, intptr_t len)
Definition object.h:10481
void Add(uint16_t code_unit)
Definition object.h:10480
intptr_t Finalize()
Definition object.h:10496
void Add(const uint16_t *code_units, intptr_t len)
Definition object.h:10488
CodePointIterator(const String &str)
Definition object.h:10162
CodePointIterator(const String &str, intptr_t start, intptr_t length)
Definition object.h:10167
virtual bool OperatorEquals(const Instance &other) const
Definition object.h:10266
static constexpr intptr_t kSizeofRawString
Definition object.h:10149
static constexpr intptr_t kMaxElements
Definition object.h:10152
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:10290
static uword Hash(const int32_t *characters, intptr_t len)
static uint32_t SetCachedHashIfNotSet(StringPtr obj, uint32_t hash)
Definition object.h:10428
intptr_t Length() const
Definition object.h:10189
virtual ObjectPtr HashCode() const
Definition object.h:10236
static uword HashRawSymbol(const StringPtr symbol)
Definition object.h:10226
bool HasHash() const
Definition object.h:10208
void SetHash(intptr_t value) const
Definition object.h:10456
static intptr_t HeaderSize()
Definition object.h:10154
virtual uint32_t CanonicalizeHash() const
Definition object.h:10272
void SetLength(intptr_t value) const
Definition object.h:10450
bool Equals(const String &str) const
Definition object.h:13311
static intptr_t length_offset()
Definition object.h:10193
static intptr_t InstanceSize()
Definition object.h:10156
static intptr_t hash_offset()
Definition object.h:10213
bool IsTwoByteString() const
Definition object.h:10294
static uint32_t SetCachedHash(StringPtr obj, uint32_t hash)
Definition object.h:10433
static StringPtr SubString(const String &str, intptr_t begin_index, intptr_t length, Heap::Space space=Heap::kNew)
Definition object.h:10382
uint16_t CharAt(intptr_t index) const
Definition object.h:10238
bool StartsWith(const String &other) const
Definition object.h:10277
bool IsSymbol() const
Definition object.h:10288
uword Hash() const
Definition object.h:10195
virtual bool CanonicalizeEquals(const Instance &other) const
Definition object.h:10269
bool EqualsLatin1(const uint8_t *characters, intptr_t len) const
Definition object.h:10253
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:10424
static intptr_t LengthOf(StringPtr obj)
Definition object.h:10190
FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance)
intptr_t num_occupied() const
Definition object.h:7792
static intptr_t num_inputs_offset()
Definition object.h:7787
static intptr_t cache_offset()
Definition object.h:7782
static constexpr intptr_t MaxEntriesForCacheAllocatedFor(intptr_t count)
Definition object.h:7814
intptr_t num_inputs() const
Definition object.h:7790
static intptr_t InstanceSize()
Definition object.h:7778
static intptr_t frame_size_offset()
Definition object.h:12620
static intptr_t error_callback_offset()
Definition object.h:12630
static intptr_t function_data_offset()
Definition object.h:12624
ClosurePtr error_callback() const
Definition object.h:12655
static intptr_t then_callback_offset()
Definition object.h:12627
static intptr_t InstanceSize(intptr_t frame_capacity)
Definition object.h:12605
static intptr_t FrameSizeGrowthGap()
Definition object.h:12611
static intptr_t HeaderSize()
Definition object.h:12593
static intptr_t payload_offset()
Definition object.h:12633
static intptr_t UnroundedSize(SuspendStatePtr ptr)
Definition object.h:12594
ClosurePtr then_callback() const
Definition object.h:12653
static intptr_t InstanceSize()
Definition object.h:12600
uword pc() const
Definition object.h:12647
static intptr_t pc_offset()
Definition object.h:12623
InstancePtr function_data() const
Definition object.h:12651
static intptr_t frame_capacity_offset()
Definition object.h:12616
intptr_t frame_size() const
Definition object.h:12649
static intptr_t UnroundedSize(intptr_t frame_capacity)
Definition object.h:12597
static Thread * Current()
Definition thread.h:361
void set_handle(FinalizablePersistentHandle *handle)
Definition object.h:12498
FinalizablePersistentHandle * handle() const
Definition object.h:12497
TransferableTypedDataPeer(uint8_t *data, intptr_t length)
Definition object.h:12490
static intptr_t InstanceSize()
Definition object.h:12518
static uint16_t CharAt(const String &str, intptr_t index)
Definition object.h:10643
static intptr_t UnroundedSize(TwoByteStringPtr str)
Definition object.h:10677
static uint16_t CharAt(TwoByteStringPtr str, intptr_t index)
Definition object.h:10649
static intptr_t InstanceSize(intptr_t len)
Definition object.h:10688
static intptr_t InstanceSize()
Definition object.h:10683
static intptr_t data_offset()
Definition object.h:10674
static TwoByteStringPtr null()
Definition object.h:10722
static intptr_t UnroundedSize(intptr_t len)
Definition object.h:10680
static void SetCharAt(const String &str, intptr_t index, uint16_t ch)
Definition object.h:10654
KeyLocation FindKeyOrUnused(const TypeArguments &instantiator_tav, const TypeArguments &function_tav) const
Definition object.h:8839
static const Array & EmptyStorage()
Definition object.h:8865
intptr_t NumOccupied() const
Definition object.h:8827
intptr_t NumEntries() const
Definition object.h:8899
bool IsEquivalent(const TypeArguments &other, TypeEquality kind, FunctionTypeMapping *function_type_equivalence=nullptr) const
Definition object.h:8665
static intptr_t instantiations_offset()
Definition object.h:8955
bool IsInstantiated(Genericity genericity=kAny, intptr_t num_free_fun_type_params=kAllFree) const
Definition object.h:8681
uword Hash() const
Definition object.h:13370
virtual uint32_t CanonicalizeHash() const
Definition object.h:8978
intptr_t Length() const
Definition object.cc:7352
static intptr_t types_offset()
Definition object.h:8560
bool Equals(const TypeArguments &other) const
Definition object.h:8660
static intptr_t InstanceSize()
Definition object.h:8962
static intptr_t InstanceSize(intptr_t len)
Definition object.h:8968
static intptr_t hash_offset()
Definition object.h:8984
AbstractTypePtr TypeAtNullSafe(intptr_t index) const
Definition object.cc:7372
virtual InstancePtr CanonicalizeLocked(Thread *thread) const
Definition object.h:8711
static intptr_t type_at_offset(intptr_t index)
Definition object.h:8563
bool IsRaw(intptr_t from_index, intptr_t len) const
Definition object.h:8620
bool IsRawWhenInstantiatedFromRaw(intptr_t len) const
Definition object.h:8630
static intptr_t nullability_offset()
Definition object.h:8599
static intptr_t length_offset()
Definition object.h:8554
virtual classid_t type_class_id() const
Definition object.h:9790
bool IsClassTypeParameter() const
Definition object.h:9796
static intptr_t index_offset()
Definition object.h:9802
intptr_t index() const
Definition object.h:9800
virtual bool HasTypeClass() const
Definition object.h:9789
virtual void EnumerateURIs(URIs *uris) const
Definition object.h:9835
static intptr_t InstanceSize()
Definition object.h:9856
intptr_t base() const
Definition object.h:9798
const char * CanonicalNameCString() const
Definition object.h:9848
bool IsFunctionTypeParameter() const
Definition object.h:9792
static intptr_t defaults_offset()
Definition object.h:8481
static intptr_t flags_offset()
Definition object.h:8470
static intptr_t names_offset()
Definition object.h:8464
static intptr_t InstanceSize()
Definition object.h:8511
COMPILE_ASSERT(kFlagsPerSmi< kSmiBits)
static intptr_t bounds_offset()
Definition object.h:8474
static intptr_t arguments_offset()
Definition object.h:9350
static intptr_t InstanceSize()
Definition object.h:9402
virtual TypeArgumentsPtr arguments() const
Definition object.h:9361
virtual bool HasTypeClass() const
Definition object.h:9353
SmiPtr length() const
Definition object.h:11490
TypedDataElementType ElementType() const
Definition object.h:11501
intptr_t Length() const
Definition object.h:11492
virtual uint8_t * Validate(uint8_t *data) const
Definition object.h:11587
intptr_t ElementSizeInBytes() const
Definition object.h:11505
static TypedDataElementType ElementType(classid_t cid)
Definition object.h:11513
static intptr_t length_offset()
Definition object.h:11486
intptr_t LengthInBytes() const
Definition object.h:11497
static intptr_t ElementSizeInBytes(classid_t cid)
Definition object.h:11509
void SetLength(intptr_t value) const
Definition object.h:11582
void * DataAddr(intptr_t byte_offset) const
Definition object.h:11545
TypedDataBasePtr typed_data() const
Definition object.h:11794
static intptr_t typed_data_offset()
Definition object.h:11786
static intptr_t offset_in_bytes_offset()
Definition object.h:11790
static SmiPtr OffsetInBytes(const TypedDataView &view)
Definition object.h:11775
static intptr_t InstanceSize()
Definition object.h:11767
virtual uint8_t * Validate(uint8_t *data) const
Definition object.h:11812
static InstancePtr Data(const TypedDataView &view)
Definition object.h:11771
void InitializeWith(const TypedDataBase &typed_data, intptr_t offset_in_bytes, intptr_t length)
Definition object.h:11796
SmiPtr offset_in_bytes() const
Definition object.h:11809
static bool IsExternalTypedDataView(const TypedDataView &view_obj)
Definition object.h:11779
static intptr_t payload_offset()
Definition object.h:11643
static bool IsTypedData(const Instance &obj)
Definition object.h:11677
static intptr_t InstanceSize(intptr_t lengthInBytes)
Definition object.h:11653
static intptr_t MaxNewSpaceElements(intptr_t class_id)
Definition object.h:11663
static intptr_t MaxElements(intptr_t class_id)
Definition object.h:11658
void RecomputeDataField()
Definition object.h:11684
static intptr_t InstanceSize()
Definition object.h:11647
static intptr_t stacktrace_offset()
Definition object.h:8123
InstancePtr exception() const
Definition object.h:8117
static intptr_t exception_offset()
Definition object.h:8118
static intptr_t InstanceSize()
Definition object.h:8127
InstancePtr stacktrace() const
Definition object.h:8122
static intptr_t InstanceSize()
Definition object.h:2389
bool can_patch_to_monomorphic() const
Definition object.h:2385
void StoreSmi(type const *addr, type value)
Definition raw_object.h:702
void StorePointer(type const *addr, type value)
Definition raw_object.h:574
bool IsImmutable() const
Definition raw_object.h:333
void Validate(IsolateGroup *isolate_group) const
Definition raw_object.cc:42
static uword ToAddr(const UntaggedObject *raw_obj)
Definition raw_object.h:501
bool InVMIsolateHeap() const
Definition raw_object.cc:20
type LoadPointer(type const *addr) const
Definition raw_object.h:555
bool Contains(uword addr) const
Definition raw_object.h:415
void StoreCompressedPointer(compressed_type const *addr, type value)
Definition raw_object.h:585
intptr_t GetClassId() const
Definition raw_object.h:371
void StorePointerUnaligned(type const *addr, type value, Thread *thread)
Definition raw_object.h:613
bool IsCanonical() const
Definition raw_object.h:329
static constexpr bool kContainsCompressedPointers
Definition raw_object.h:527
static intptr_t InstanceSize()
Definition object.h:8155
bool is_user_initiated() const
Definition object.h:8150
StringPtr message() const
Definition object.h:8153
static intptr_t tag_offset()
Definition object.h:13140
void set_streamable(bool streamable)
Definition object.h:13136
void set_tag(uword t) const
Definition object.h:13129
uword tag() const
Definition object.h:13128
bool streamable() const
Definition object.h:13135
static intptr_t InstanceSize()
Definition object.h:13146
StringPtr label() const
Definition object.h:13142
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition utils.h:105
static constexpr bool IsAligned(T x, uintptr_t alignment, uintptr_t offset=0)
Definition utils.h:77
static uword AllocateZoneHandle(Zone *zone)
Definition handles.cc:42
static uword AllocateHandle(Zone *zone)
Definition handles.cc:32
void SetAt(intptr_t index, const Object &value) const
Definition object.h:6696
static intptr_t InstanceSize()
Definition object.h:6715
static intptr_t LengthOf(const WeakArrayPtr array)
Definition object.h:13273
static constexpr intptr_t InstanceSize(intptr_t len)
Definition object.h:6721
ObjectPtr AtAcquire(intptr_t index) const
Definition object.h:6701
static intptr_t element_offset(intptr_t index)
Definition object.h:6679
static intptr_t length_offset()
Definition object.h:6673
intptr_t Length() const
Definition object.h:6670
ObjectPtr At(intptr_t index) const
Definition object.h:6695
static constexpr bool IsValidLength(intptr_t length)
Definition object.h:6711
static intptr_t index_at_offset(intptr_t offset_in_bytes)
Definition object.h:6683
static intptr_t data_offset()
Definition object.h:6676
void SetAtRelease(intptr_t index, const Object &value) const
Definition object.h:6704
ObjectPtr value() const
Definition object.h:12898
static intptr_t key_offset()
Definition object.h:12896
void set_key(const Object &key) const
Definition object.h:12895
static intptr_t value_offset()
Definition object.h:12900
static intptr_t InstanceSize()
Definition object.h:12906
ObjectPtr key() const
Definition object.h:12894
void set_value(const Object &value) const
Definition object.h:12899
static intptr_t InstanceSize()
Definition object.h:12932
ObjectPtr target() const
Definition object.h:12918
static intptr_t type_arguments_offset()
Definition object.h:12926
static intptr_t target_offset()
Definition object.h:12922
void set_target(const Object &target) const
Definition object.h:12919
static ObjectPtr UnwrapIfTarget(const Object &obj)
Definition object.h:6650
static ObjectPtr Unwrap(ObjectPtr obj)
Definition object.h:6640
static ObjectPtr UnwrapIfTarget(ObjectPtr obj)
Definition object.h:6649
static ObjectPtr TargetOf(const WeakSerializationReferencePtr obj)
Definition object.h:6636
static intptr_t InstanceSize()
Definition object.h:6652
static ObjectPtr Unwrap(const Object &obj)
Definition object.h:6648
int64_t Dart_Port
Definition dart_api.h:1524
#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:3225
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:3246
void *(* Dart_FfiNativeResolver)(const char *name, uintptr_t args_n)
Definition dart_api.h:3253
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
glong glong end
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static const uint8_t buffer[]
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
const char * name
Definition fuchsia.cc:50
void Init()
#define DECLARE_BIT(Name)
Definition isolate.h:766
#define REUSABLE_FRIEND_DECLARATION(name)
Definition isolate.h:1687
size_t length
Win32Message message
#define DEFINE_ENUM_LIST(class_name, function_name, enum_name, fp)
double y
double x
Optional< SkRect > bounds
Definition SkRecords.h:189
static constexpr intptr_t kNullIdentityHash
Definition object.h:10763
const intptr_t kOffsetOfPtr
Definition globals.h:136
const int kNumTypedDataCidRemainders
Definition class_id.h:265
void DumpStackFrame(intptr_t frame_index, uword pc, uword fp)
Definition profiler.cc:77
static bool Equals(const Object &expected, const Object &actual)
bool IsTypedDataViewClassId(intptr_t index)
Definition class_id.h:439
bool IsTypedDataClassId(intptr_t index)
Definition class_id.h:433
static constexpr intptr_t kFalseIdentityHash
Definition object.h:10765
constexpr intptr_t kBitsPerWordLog2
Definition globals.h:513
constexpr intptr_t kBitsPerByteLog2
Definition globals.h:462
bool IsFfiDynamicLibraryClassId(intptr_t index)
Definition class_id.h:545
InstantiationMode
ZoneGrowableHandlePtrArray< const String > URIs
Definition object.h:1110
const char *const name
const int kTypedDataCidRemainderUnmodifiable
Definition class_id.h:264
constexpr intptr_t kBitsPerWord
Definition globals.h:514
uword cpp_vtable
Definition globals.h:163
Nullability
Definition object.h:1112
DART_WARN_UNUSED_RESULT ErrorPtr EntryPointFieldInvocationError(const String &getter_name)
Definition object.cc:27272
DART_EXPORT bool IsNull(Dart_Handle object)
intptr_t RawSmiValue(const SmiPtr raw_value)
uint32_t CombineHashes(uint32_t hash, uint32_t other_hash)
Definition hash.h:12
const int kTypedDataCidRemainderInternal
Definition class_id.h:261
FfiCallbackKind
Definition object.h:2964
int32_t classid_t
Definition globals.h:524
DART_WARN_UNUSED_RESULT ErrorPtr EntryPointMemberInvocationError(const Object &member)
Definition object.cc:27288
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
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:27193
ObjectPtr Invoke(const Library &lib, const char *name)
TypedDataElementType
Definition raw_object.h:123
FunctionPtr GetFunction(const Library &lib, const char *name)
constexpr uword kUwordMax
Definition globals.h:519
@ kHeapObjectTag
DART_WARN_UNUSED_RESULT ErrorPtr VerifyEntryPoint(const Library &lib, const Object &member, const Object &annotated, std::initializer_list< EntryPointPragma > allowed_kinds)
Definition object.cc:27227
uintptr_t uword
Definition globals.h:501
TypeEquality
Definition object.h:1120
EntryPointPragma
Definition object.h:4344
const int kTypedDataCidRemainderExternal
Definition class_id.h:263
static const char * Concat(const char *a, const char *b)
Definition file_test.cc:86
const int kTypedDataCidRemainderView
Definition class_id.h:262
bool IsZero(char *begin, char *end)
uint32_t HashBytes(const uint8_t *bytes, intptr_t size)
Definition hash.h:31
@ kCurrentAndEnclosingFree
Definition object.h:2917
@ kAllFree
Definition object.h:2920
@ kNoneFree
Definition object.h:2906
bool FindPragmaInMetadata(Thread *T, const Object &metadata_obj, const String &pragma_name, bool multiple, Object *options)
Definition object.cc:4142
void Validate(const Table &table)
NNBDCompiledMode
Definition object.h:1128
constexpr intptr_t kBitsPerInt32
Definition globals.h:466
const intptr_t cid
static constexpr intptr_t kTrueIdentityHash
Definition object.h:10764
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)
uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits=kBitsPerInt32)
Definition hash.h:20
static uint32_t Hash(uint32_t key)
void DumpTypeTable(Isolate *isolate)
Definition object.cc:27154
constexpr int32_t kMaxInt32
Definition globals.h:483
constexpr intptr_t kWordSize
Definition globals.h:509
static constexpr intptr_t kObjectAlignment
void DFLRT_ExitSafepoint(NativeArguments __unusable_)
Genericity
Definition object.h:2228
@ kFunctions
Definition object.h:2231
@ kCurrentClass
Definition object.h:2230
@ kAny
Definition object.h:2229
const intptr_t kPreferredLoopAlignment
void DumpTypeParameterTable(Isolate *isolate)
Definition object.cc:27177
static int8_t data[kExtLength]
void DumpTypeArgumentsTable(Isolate *isolate)
Definition object.cc:27185
static constexpr intptr_t kNewAllocatableSize
Definition spaces.h:54
bool IsExternalTypedDataClassId(intptr_t index)
Definition class_id.h:447
ObjectPtr CompressedObjectPtr
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
#define SHARED_READONLY_HANDLES_LIST(V)
Definition object.h:457
#define DEFINE_INSTRUCTIONS_FLAG_HANDLING(Name)
Definition object.h:5698
#define BASE_OBJECT_IMPLEMENTATION(object, super)
Definition object.h:106
#define ASSERT_FUNCTION_KIND_IN_RANGE(Name)
Definition object.h:4216
#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:4235
#define DECLARE_FLAG_POS(Name)
Definition object.h:4076
#define HEAP_OBJECT_IMPLEMENTATION(object, super)
Definition object.h:260
#define DEFINE_ACCESSORS(name, accessor_name)
Definition object.h:4155
#define DECLARE_SHARED_READONLY_HANDLE(Type, name)
Definition object.h:1013
#define DEOPT_REASONS(V)
Definition object.h:2473
#define PRECOMPILER_WSR_FIELD_DECLARATION(Type, Name)
Definition object.h:1055
#define FOR_EACH_FUNCTION_KIND_BIT(V)
Definition object.h:4135
#define FOR_EACH_REBIND_RULE(V)
Definition object.h:2517
#define DECLARE_FLAG_ACCESSORS(Name)
Definition object.h:7473
#define FINAL_HEAP_OBJECT_IMPLEMENTATION(object, super)
Definition object.h:300
#define TYPED_GETTER_SETTER(name, type)
Definition object.h:11551
#define STORE_NON_POINTER_ILLEGAL_TYPE(type)
Definition object.h:849
#define REBIND_ENUM_DEF(name)
Definition object.h:2526
#define DEFINE_GETTERS_AND_SETTERS(return_type, type, name)
Definition object.h:3512
#define OBJECT_IMPLEMENTATION(object, super)
Definition object.h:242
#define DEFINE_FLAG_BIT(Name)
Definition object.h:4080
#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:4153
#define DEFINE_INSTRUCTIONS_FLAG(Name)
Definition object.h:5691
#define INSTRUCTIONS_FLAGS_LIST(V)
Definition object.h:5686
#define DEFINE_SHARED_READONLY_HANDLE_GETTER(Type, name)
Definition object.h:503
#define STATE_BITS_LIST(V)
Definition object.h:4069
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_
#define T
#define FOR_EACH_RAW_FUNCTION_KIND(V)
#define JIT_FUNCTION_COUNTERS(F)
#define CONTEXT_SCOPE_VARIABLE_DESC_FLAG_LIST(V)
Point offset
static intptr_t elements_start_offset()
Definition object.h:10828
static intptr_t elements_start_offset()
Definition object.h:7130
static intptr_t elements_start_offset()
Definition object.h:7500
static intptr_t elements_start_offset()
Definition object.h:7406
static intptr_t elements_start_offset()
Definition object.h:6573
static NameFormattingParams DisambiguatedUnqualified(Object::NameVisibility visibility)
Definition object.h:2955
static NameFormattingParams DisambiguatedWithoutClassName(Object::NameVisibility visibility)
Definition object.h:2948
Object::NameVisibility name_visibility
Definition object.h:2925
NameFormattingParams(Object::NameVisibility visibility, Object::NameDisambiguation name_disambiguation=Object::NameDisambiguation::kNo)
Definition object.h:2941
static intptr_t elements_start_offset()
Definition object.h:5560
Entry(uword value, EntryType info)
Definition object.h:5535
const Object * obj_
Definition object.h:5537
Entry(const Object *obj)
Definition object.h:5533
static intptr_t elements_start_offset()
Definition object.h:10527
static intptr_t elements_start_offset()
Definition object.h:11418
static intptr_t elements_start_offset()
Definition object.h:10668
static intptr_t elements_start_offset()
Definition object.h:8569
static intptr_t elements_start_offset()
Definition object.h:6690
#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
#define DEFINE_FLAG_ACCESSORS(Name)
Definition object.cc:18694