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_RAW_OBJECT_H_
6#define RUNTIME_VM_RAW_OBJECT_H_
7
8#if defined(SHOULD_NOT_INCLUDE_RUNTIME)
9#error "Should not include runtime"
10#endif
11
12#include "platform/assert.h"
13#include "platform/atomic.h"
14#include "platform/thread_sanitizer.h"
15#include "vm/class_id.h"
16#include "vm/compiler/method_recognizer.h"
17#include "vm/compiler/runtime_api.h"
18#include "vm/exceptions.h"
19#include "vm/globals.h"
20#include "vm/pointer_tagging.h"
21#include "vm/snapshot.h"
22#include "vm/tagged_pointer.h"
23#include "vm/token.h"
24#include "vm/token_position.h"
25
26namespace dart {
27
28// For now there are no compressed pointers.
29typedef ObjectPtr RawCompressed;
30
31// Forward declarations.
32class Isolate;
33class IsolateGroup;
34#define DEFINE_FORWARD_DECLARATION(clazz) class clazz##Layout;
35CLASS_LIST(DEFINE_FORWARD_DECLARATION)
36#undef DEFINE_FORWARD_DECLARATION
37class CodeStatistics;
38
39#define VISIT_FROM(type, first) \
40 type* from() { return reinterpret_cast<type*>(&first); }
41
42#define VISIT_TO(type, last) \
43 type* to() { return reinterpret_cast<type*>(&last); }
44
45#define VISIT_TO_LENGTH(type, last) \
46 type* to(intptr_t length) { return reinterpret_cast<type*>(last); }
47
48#define VISIT_NOTHING() int NothingToVisit();
49
50#define ASSERT_UNCOMPRESSED(Type) \
51 ASSERT(SIZE_OF_DEREFERENCED_RETURNED_VALUE(Type##Layout, from) == kWordSize)
52
53// For now there are no compressed pointers, so this assert is the same as
54// the above.
55#define ASSERT_COMPRESSED(Type) \
56 ASSERT(SIZE_OF_DEREFERENCED_RETURNED_VALUE(Type##Layout, from) == kWordSize)
57
58#define ASSERT_NOTHING_TO_VISIT(Type) \
59 ASSERT(SIZE_OF_RETURNED_VALUE(Type##Layout, NothingToVisit) == sizeof(int))
60
61enum TypedDataElementType {
62#define V(name) k##name##Element,
63 CLASS_LIST_TYPED_DATA(V)
64#undef V
65};
66
67#define SNAPSHOT_WRITER_SUPPORT() \
68 void WriteTo(SnapshotWriter* writer, intptr_t object_id, \
69 Snapshot::Kind kind, bool as_reference); \
70 friend class SnapshotWriter;
71
72#define VISITOR_SUPPORT(object) \
73 static intptr_t Visit##object##Pointers(object##Ptr raw_obj, \
74 ObjectPointerVisitor* visitor);
75
76#define HEAP_PROFILER_SUPPORT() friend class HeapProfiler;
77
78#define RAW_OBJECT_IMPLEMENTATION(object) \
79 private: /* NOLINT */ \
80 VISITOR_SUPPORT(object) \
81 friend class object; \
82 friend class ObjectLayout; \
83 friend class Heap; \
84 friend class Interpreter; \
85 friend class InterpreterHelpers; \
86 friend class Simulator; \
87 friend class SimulatorHelpers; \
88 friend class OffsetsTable; \
89 DISALLOW_ALLOCATION(); \
90 DISALLOW_IMPLICIT_CONSTRUCTORS(object##Layout)
91
92#define RAW_HEAP_OBJECT_IMPLEMENTATION(object) \
93 private: \
94 RAW_OBJECT_IMPLEMENTATION(object); \
95 SNAPSHOT_WRITER_SUPPORT() \
96 HEAP_PROFILER_SUPPORT() \
97 friend class object##SerializationCluster; \
98 friend class object##DeserializationCluster; \
99 friend class Serializer; \
100 friend class Deserializer; \
101 friend class Pass2Visitor;
102
103// RawObject is the base class of all raw objects; even though it carries the
104// tags_ field not all raw objects are allocated in the heap and thus cannot
105// be dereferenced (e.g. RawSmi).
106class ObjectLayout {
107 public:
108 // The tags field which is a part of the object header uses the following
109 // bit fields for storing tags.
110 enum TagBits {
111 kCardRememberedBit = 0,
112 kOldAndNotMarkedBit = 1, // Incremental barrier target.
113 kNewBit = 2, // Generational barrier target.
114 kOldBit = 3, // Incremental barrier source.
115 kOldAndNotRememberedBit = 4, // Generational barrier source.
116 kCanonicalBit = 5,
117 kReservedTagPos = 6,
118 kReservedTagSize = 2,
119
120 kSizeTagPos = kReservedTagPos + kReservedTagSize, // = 8
121 kSizeTagSize = 8,
122 kClassIdTagPos = kSizeTagPos + kSizeTagSize, // = 16
123 kClassIdTagSize = 16,
124#if defined(HASH_IN_OBJECT_HEADER)
125 kHashTagPos = kClassIdTagPos + kClassIdTagSize, // = 32
126 kHashTagSize = 16,
127#endif
128 };
129
130 static const intptr_t kGenerationalBarrierMask = 1 << kNewBit;
131 static const intptr_t kIncrementalBarrierMask = 1 << kOldAndNotMarkedBit;
132 static const intptr_t kBarrierOverlapShift = 2;
133 COMPILE_ASSERT(kOldAndNotMarkedBit + kBarrierOverlapShift == kOldBit);
134 COMPILE_ASSERT(kNewBit + kBarrierOverlapShift == kOldAndNotRememberedBit);
135
136 // The bit in the Smi tag position must be something that can be set to 0
137 // for a dead filler object of either generation.
138 // See Object::MakeUnusedSpaceTraversable.
139 COMPILE_ASSERT(kCardRememberedBit == 0);
140
141 // Encodes the object size in the tag in units of object alignment.
142 class SizeTag {
143 public:
144 typedef intptr_t Type;
145
146 static constexpr intptr_t kMaxSizeTagInUnitsOfAlignment =
147 ((1 << ObjectLayout::kSizeTagSize) - 1);
148 static constexpr intptr_t kMaxSizeTag =
149 kMaxSizeTagInUnitsOfAlignment * kObjectAlignment;
150
151 static UNLESS_DEBUG(constexpr) uword encode(intptr_t size) {
152 return SizeBits::encode(SizeToTagValue(size));
153 }
154
155 static constexpr uword decode(uword tag) {
156 return TagValueToSize(SizeBits::decode(tag));
157 }
158
159 static UNLESS_DEBUG(constexpr) uword update(intptr_t size, uword tag) {
160 return SizeBits::update(SizeToTagValue(size), tag);
161 }
162
163 static UNLESS_DEBUG(constexpr) bool SizeFits(intptr_t size) {
164 DEBUG_ASSERT(Utils::IsAligned(size, kObjectAlignment));
165 return (size <= kMaxSizeTag);
166 }
167
168 private:
169 // The actual unscaled bit field used within the tag field.
170 class SizeBits
171 : public BitField<uint32_t, intptr_t, kSizeTagPos, kSizeTagSize> {};
172
173 static UNLESS_DEBUG(constexpr) intptr_t SizeToTagValue(intptr_t size) {
174 DEBUG_ASSERT(Utils::IsAligned(size, kObjectAlignment));
175 return !SizeFits(size) ? 0 : (size >> kObjectAlignmentLog2);
176 }
177 static constexpr intptr_t TagValueToSize(intptr_t value) {
178 return value << kObjectAlignmentLog2;
179 }
180 };
181
182 class ClassIdTag : public BitField<uint32_t,
183 ClassIdTagType,
184 kClassIdTagPos,
185 kClassIdTagSize> {};
186 COMPILE_ASSERT(kBitsPerByte * sizeof(ClassIdTagType) == kClassIdTagSize);
187
188 class CardRememberedBit
189 : public BitField<uint32_t, bool, kCardRememberedBit, 1> {};
190
191 class OldAndNotMarkedBit
192 : public BitField<uint32_t, bool, kOldAndNotMarkedBit, 1> {};
193
194 class NewBit : public BitField<uint32_t, bool, kNewBit, 1> {};
195
196 class CanonicalBit : public BitField<uint32_t, bool, kCanonicalBit, 1> {};
197
198 class OldBit : public BitField<uint32_t, bool, kOldBit, 1> {};
199
200 class OldAndNotRememberedBit
201 : public BitField<uint32_t, bool, kOldAndNotRememberedBit, 1> {};
202
203 class ReservedBits
204 : public BitField<uint32_t, intptr_t, kReservedTagPos, kReservedTagSize> {
205 };
206
207 class Tags {
208 public:
209 Tags() : tags_(0) {}
210
211 NO_SANITIZE_THREAD
212 operator uint32_t() const {
213 return *reinterpret_cast<const uint32_t*>(&tags_);
214 }
215
216 NO_SANITIZE_THREAD
217 uint32_t operator=(uint32_t tags) {
218 return *reinterpret_cast<uint32_t*>(&tags_) = tags;
219 }
220
221 NO_SANITIZE_THREAD
222 bool StrongCAS(uint32_t old_tags, uint32_t new_tags) {
223 return tags_.compare_exchange_strong(old_tags, new_tags,
224 std::memory_order_relaxed);
225 }
226
227 NO_SANITIZE_THREAD
228 bool WeakCAS(uint32_t old_tags, uint32_t new_tags) {
229 return tags_.compare_exchange_weak(old_tags, new_tags,
230 std::memory_order_relaxed);
231 }
232
233 template <class TagBitField>
234 NO_SANITIZE_THREAD typename TagBitField::Type Read() const {
235 return TagBitField::decode(*reinterpret_cast<const uint32_t*>(&tags_));
236 }
237
238 template <class TagBitField>
239 NO_SANITIZE_THREAD void UpdateBool(bool value) {
240 if (value) {
241 tags_.fetch_or(TagBitField::encode(true), std::memory_order_relaxed);
242 } else {
243 tags_.fetch_and(~TagBitField::encode(true), std::memory_order_relaxed);
244 }
245 }
246
247 template <class TagBitField>
248 NO_SANITIZE_THREAD void UpdateUnsynchronized(
249 typename TagBitField::Type value) {
250 *reinterpret_cast<uint32_t*>(&tags_) =
251 TagBitField::update(value, *reinterpret_cast<uint32_t*>(&tags_));
252 }
253
254 template <class TagBitField>
255 NO_SANITIZE_THREAD bool TryAcquire() {
256 uint32_t mask = TagBitField::encode(true);
257 uint32_t old_tags = tags_.fetch_or(mask, std::memory_order_relaxed);
258 return !TagBitField::decode(old_tags);
259 }
260
261 template <class TagBitField>
262 NO_SANITIZE_THREAD bool TryClear() {
263 uint32_t mask = ~TagBitField::encode(true);
264 uint32_t old_tags = tags_.fetch_and(mask, std::memory_order_relaxed);
265 return TagBitField::decode(old_tags);
266 }
267
268 private:
269 std::atomic<uint32_t> tags_;
270 COMPILE_ASSERT(sizeof(std::atomic<uint32_t>) == sizeof(uint32_t));
271 };
272
273 // Assumes this is a heap object.
274 bool IsNewObject() const {
275 uword addr = reinterpret_cast<uword>(this);
276 return (addr & kObjectAlignmentMask) == kNewObjectAlignmentOffset;
277 }
278 // Assumes this is a heap object.
279 bool IsOldObject() const {
280 uword addr = reinterpret_cast<uword>(this);
281 return (addr & kObjectAlignmentMask) == kOldObjectAlignmentOffset;
282 }
283
284 // Support for GC marking bit. Marked objects are either grey (not yet
285 // visited) or black (already visited).
286 bool IsMarked() const {
287 ASSERT(IsOldObject());
288 return !tags_.Read<OldAndNotMarkedBit>();
289 }
290 void SetMarkBit() {
291 ASSERT(IsOldObject());
292 ASSERT(!IsMarked());
293 tags_.UpdateBool<OldAndNotMarkedBit>(false);
294 }
295 void SetMarkBitUnsynchronized() {
296 ASSERT(IsOldObject());
297 ASSERT(!IsMarked());
298 tags_.UpdateUnsynchronized<OldAndNotMarkedBit>(false);
299 }
300 void ClearMarkBit() {
301 ASSERT(IsOldObject());
302 ASSERT(IsMarked());
303 tags_.UpdateBool<OldAndNotMarkedBit>(true);
304 }
305 // Returns false if the bit was already set.
306 DART_WARN_UNUSED_RESULT
307 bool TryAcquireMarkBit() {
308 ASSERT(IsOldObject());
309 return tags_.TryClear<OldAndNotMarkedBit>();
310 }
311
312 // Canonical objects have the property that two canonical objects are
313 // logically equal iff they are the same object (pointer equal).
314 bool IsCanonical() const { return tags_.Read<CanonicalBit>(); }
315 void SetCanonical() { tags_.UpdateBool<CanonicalBit>(true); }
316 void ClearCanonical() { tags_.UpdateBool<CanonicalBit>(false); }
317
318 bool InVMIsolateHeap() const;
319
320 // Support for GC remembered bit.
321 bool IsRemembered() const {
322 ASSERT(IsOldObject());
323 return !tags_.Read<OldAndNotRememberedBit>();
324 }
325 void SetRememberedBit() {
326 ASSERT(!IsRemembered());
327 ASSERT(!IsCardRemembered());
328 tags_.UpdateBool<OldAndNotRememberedBit>(false);
329 }
330 void ClearRememberedBit() {
331 ASSERT(IsOldObject());
332 tags_.UpdateBool<OldAndNotRememberedBit>(true);
333 }
334
335 DART_FORCE_INLINE
336 void AddToRememberedSet(Thread* thread) {
337 ASSERT(!this->IsRemembered());
338 this->SetRememberedBit();
339 thread->StoreBufferAddObject(ObjectPtr(this));
340 }
341
342 bool IsCardRemembered() const { return tags_.Read<CardRememberedBit>(); }
343 void SetCardRememberedBitUnsynchronized() {
344 ASSERT(!IsRemembered());
345 ASSERT(!IsCardRemembered());
346 tags_.UpdateUnsynchronized<CardRememberedBit>(true);
347 }
348
349 intptr_t GetClassId() const { return tags_.Read<ClassIdTag>(); }
350
351 intptr_t HeapSize() const {
352 uint32_t tags = tags_;
353 intptr_t result = SizeTag::decode(tags);
354 if (result != 0) {
355#if defined(DEBUG)
356 // TODO(22501) Array::MakeFixedLength has a race with this code: we might
357 // have loaded tags field and then MakeFixedLength could have updated it
358 // leading to inconsistency between HeapSizeFromClass() and
359 // SizeTag::decode(tags). We are working around it by reloading tags_ and
360 // recomputing size from tags.
361 const intptr_t size_from_class = HeapSizeFromClass(tags);
362 if ((result > size_from_class) && (GetClassId() == kArrayCid) &&
363 (tags_ != tags)) {
364 result = SizeTag::decode(tags_);
365 }
366 ASSERT(result == size_from_class);
367#endif
368 return result;
369 }
370 result = HeapSizeFromClass(tags);
371 ASSERT(result > SizeTag::kMaxSizeTag);
372 return result;
373 }
374
375 // This variant must not deference this->tags_.
376 intptr_t HeapSize(uint32_t tags) const {
377 intptr_t result = SizeTag::decode(tags);
378 if (result != 0) {
379 return result;
380 }
381 result = HeapSizeFromClass(tags);
382 ASSERT(result > SizeTag::kMaxSizeTag);
383 return result;
384 }
385
386 bool Contains(uword addr) const {
387 intptr_t this_size = HeapSize();
388 uword this_addr = ObjectLayout::ToAddr(this);
389 return (addr >= this_addr) && (addr < (this_addr + this_size));
390 }
391
392 void Validate(IsolateGroup* isolate_group) const;
393 bool FindObject(FindObjectVisitor* visitor);
394
395 // This function may access the class-ID in the header, but it cannot access
396 // the actual class object, because the sliding compactor uses this function
397 // while the class objects are being moved.
398 intptr_t VisitPointers(ObjectPointerVisitor* visitor) {
399 // Fall back to virtual variant for predefined classes
400 intptr_t class_id = GetClassId();
401 if (class_id < kNumPredefinedCids) {
402 return VisitPointersPredefined(visitor, class_id);
403 }
404
405 // Calculate the first and last raw object pointer fields.
406 intptr_t instance_size = HeapSize();
407 uword obj_addr = ToAddr(this);
408 uword from = obj_addr + sizeof(ObjectLayout);
409 uword to = obj_addr + instance_size - kWordSize;
410 const auto first = reinterpret_cast<ObjectPtr*>(from);
411 const auto last = reinterpret_cast<ObjectPtr*>(to);
412
413#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
414 const auto unboxed_fields_bitmap =
415 visitor->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
416
417 if (!unboxed_fields_bitmap.IsEmpty()) {
418 intptr_t bit = sizeof(ObjectLayout) / kWordSize;
419 for (ObjectPtr* current = first; current <= last; current++) {
420 if (!unboxed_fields_bitmap.Get(bit++)) {
421 visitor->VisitPointer(current);
422 }
423 }
424 } else {
425 visitor->VisitPointers(first, last);
426 }
427#else
428 // Call visitor function virtually
429 visitor->VisitPointers(first, last);
430#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
431
432 return instance_size;
433 }
434
435 template <class V>
436 intptr_t VisitPointersNonvirtual(V* visitor) {
437 // Fall back to virtual variant for predefined classes
438 intptr_t class_id = GetClassId();
439 if (class_id < kNumPredefinedCids) {
440 return VisitPointersPredefined(visitor, class_id);
441 }
442
443 // Calculate the first and last raw object pointer fields.
444 intptr_t instance_size = HeapSize();
445 uword obj_addr = ToAddr(this);
446 uword from = obj_addr + sizeof(ObjectLayout);
447 uword to = obj_addr + instance_size - kWordSize;
448 const auto first = reinterpret_cast<ObjectPtr*>(from);
449 const auto last = reinterpret_cast<ObjectPtr*>(to);
450
451#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
452 const auto unboxed_fields_bitmap =
453 visitor->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
454
455 if (!unboxed_fields_bitmap.IsEmpty()) {
456 intptr_t bit = sizeof(ObjectLayout) / kWordSize;
457 for (ObjectPtr* current = first; current <= last; current++) {
458 if (!unboxed_fields_bitmap.Get(bit++)) {
459 visitor->V::VisitPointers(current, current);
460 }
461 }
462 } else {
463 visitor->V::VisitPointers(first, last);
464 }
465#else
466 // Call visitor function non-virtually
467 visitor->V::VisitPointers(first, last);
468#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
469
470 return instance_size;
471 }
472
473 // This variant ensures that we do not visit the extra slot created from
474 // rounding up instance sizes up to the allocation unit.
475 void VisitPointersPrecise(Isolate* isolate, ObjectPointerVisitor* visitor);
476
477 static ObjectPtr FromAddr(uword addr) {
478 // We expect the untagged address here.
479 ASSERT((addr & kSmiTagMask) != kHeapObjectTag);
480 return static_cast<ObjectPtr>(addr + kHeapObjectTag);
481 }
482
483 static uword ToAddr(const ObjectLayout* raw_obj) {
484 return reinterpret_cast<uword>(raw_obj);
485 }
486 static uword ToAddr(const ObjectPtr raw_obj) {
487 return static_cast<uword>(raw_obj) - kHeapObjectTag;
488 }
489
490 static bool IsCanonical(intptr_t value) {
491 return CanonicalBit::decode(value);
492 }
493
494 private:
495 Tags tags_; // Various object tags (bits).
496#if defined(HASH_IN_OBJECT_HEADER)
497 // On 64 bit there is a hash field in the header for the identity hash.
498 uint32_t hash_;
499#elif defined(IS_SIMARM_X64)
500 // On simarm_x64 the hash isn't used, but we need the padding anyway so that
501 // the object layout fits assumptions made about X64.
502 uint32_t padding_;
503#endif
504
505 intptr_t VisitPointersPredefined(ObjectPointerVisitor* visitor,
506 intptr_t class_id);
507
508 intptr_t HeapSizeFromClass(uint32_t tags) const;
509
510 void SetClassId(intptr_t new_cid) {
511 tags_.UpdateUnsynchronized<ClassIdTag>(new_cid);
512 }
513
514 // All writes to heap objects should ultimately pass through one of the
515 // methods below or their counterparts in Object, to ensure that the
516 // write barrier is correctly applied.
517
518 template <typename type, std::memory_order order = std::memory_order_relaxed>
519 type LoadPointer(type const* addr) {
520 return reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
521 ->load(order);
522 }
523
524 template <typename type, std::memory_order order = std::memory_order_relaxed>
525 void StorePointer(type const* addr, type value) {
526 reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
527 ->store(value, order);
528 if (value->IsHeapObject()) {
529 CheckHeapPointerStore(value, Thread::Current());
530 }
531 }
532
533 template <typename type>
534 void StorePointer(type const* addr, type value, Thread* thread) {
535 *const_cast<type*>(addr) = value;
536 if (value->IsHeapObject()) {
537 CheckHeapPointerStore(value, thread);
538 }
539 }
540
541 template <typename type>
542 void StorePointerUnaligned(type const* addr, type value, Thread* thread) {
543 StoreUnaligned(const_cast<type*>(addr), value);
544 if (value->IsHeapObject()) {
545 CheckHeapPointerStore(value, thread);
546 }
547 }
548
549 DART_FORCE_INLINE
550 void CheckHeapPointerStore(ObjectPtr value, Thread* thread) {
551 uint32_t source_tags = this->tags_;
552 uint32_t target_tags = value->ptr()->tags_;
553 if (((source_tags >> kBarrierOverlapShift) & target_tags &
554 thread->write_barrier_mask()) != 0) {
555 if (value->IsNewObject()) {
556 // Generational barrier: record when a store creates an
557 // old-and-not-remembered -> new reference.
558 AddToRememberedSet(thread);
559 } else {
560 // Incremental barrier: record when a store creates an
561 // old -> old-and-not-marked reference.
562 ASSERT(value->IsOldObject());
563#if !defined(TARGET_ARCH_IA32)
564 if (ClassIdTag::decode(target_tags) == kInstructionsCid) {
565 // Instruction pages may be non-writable. Defer marking.
566 thread->DeferredMarkingStackAddObject(value);
567 return;
568 }
569#endif
570 if (value->ptr()->TryAcquireMarkBit()) {
571 thread->MarkingStackAddObject(value);
572 }
573 }
574 }
575 }
576
577 template <typename type, std::memory_order order = std::memory_order_relaxed>
578 void StoreArrayPointer(type const* addr, type value) {
579 reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
580 ->store(value, order);
581 if (value->IsHeapObject()) {
582 CheckArrayPointerStore(addr, value, Thread::Current());
583 }
584 }
585
586 template <typename type>
587 void StoreArrayPointer(type const* addr, type value, Thread* thread) {
588 *const_cast<type*>(addr) = value;
589 if (value->IsHeapObject()) {
590 CheckArrayPointerStore(addr, value, thread);
591 }
592 }
593
594 template <typename type>
595 DART_FORCE_INLINE void CheckArrayPointerStore(type const* addr,
596 ObjectPtr value,
597 Thread* thread) {
598 uint32_t source_tags = this->tags_;
599 uint32_t target_tags = value->ptr()->tags_;
600 if (((source_tags >> kBarrierOverlapShift) & target_tags &
601 thread->write_barrier_mask()) != 0) {
602 if (value->IsNewObject()) {
603 // Generational barrier: record when a store creates an
604 // old-and-not-remembered -> new reference.
605 ASSERT(!this->IsRemembered());
606 if (this->IsCardRemembered()) {
607 RememberCard(reinterpret_cast<ObjectPtr const*>(addr));
608 } else {
609 this->SetRememberedBit();
610 thread->StoreBufferAddObject(static_cast<ObjectPtr>(this));
611 }
612 } else {
613 // Incremental barrier: record when a store creates an
614 // old -> old-and-not-marked reference.
615 ASSERT(value->IsOldObject());
616#if !defined(TARGET_ARCH_IA32)
617 if (ClassIdTag::decode(target_tags) == kInstructionsCid) {
618 // Instruction pages may be non-writable. Defer marking.
619 thread->DeferredMarkingStackAddObject(value);
620 return;
621 }
622#endif
623 if (value->ptr()->TryAcquireMarkBit()) {
624 thread->MarkingStackAddObject(value);
625 }
626 }
627 }
628 }
629
630 // Use for storing into an explicitly Smi-typed field of an object
631 // (i.e., both the previous and new value are Smis).
632 void StoreSmi(SmiPtr const* addr, SmiPtr value) {
633 // Can't use Contains, as array length is initialized through this method.
634 ASSERT(reinterpret_cast<uword>(addr) >= ObjectLayout::ToAddr(this));
635 *const_cast<SmiPtr*>(addr) = value;
636 }
637 NO_SANITIZE_THREAD
638 void StoreSmiIgnoreRace(SmiPtr const* addr, SmiPtr value) {
639 // Can't use Contains, as array length is initialized through this method.
640 ASSERT(reinterpret_cast<uword>(addr) >= ObjectLayout::ToAddr(this));
641 *const_cast<SmiPtr*>(addr) = value;
642 }
643
644 protected:
645 friend class StoreBufferUpdateVisitor; // RememberCard
646 void RememberCard(ObjectPtr const* slot);
647
648 friend class Array;
649 friend class ByteBuffer;
650 friend class CidRewriteVisitor;
651 friend class Closure;
652 friend class Code;
653 friend class Pointer;
654 friend class Double;
655 friend class DynamicLibrary;
656 friend class ForwardPointersVisitor; // StorePointer
657 friend class FreeListElement;
658 friend class Function;
659 friend class GCMarker;
660 friend class ExternalTypedData;
661 friend class ForwardList;
662 friend class GrowableObjectArray; // StorePointer
663 friend class Heap;
664 friend class ClassStatsVisitor;
665 template <bool>
666 friend class MarkingVisitorBase;
667 friend class Mint;
668 friend class Object;
669 friend class OneByteString; // StoreSmi
670 friend class InstanceLayout;
671 friend class Scavenger;
672 template <bool>
673 friend class ScavengerVisitorBase;
674 friend class ImageReader; // tags_ check
675 friend class ImageWriter;
676 friend class AssemblyImageWriter;
677 friend class BlobImageWriter;
678 friend class SnapshotReader;
679 friend class Deserializer;
680 friend class SnapshotWriter;
681 friend class String;
682 friend class WeakProperty; // StorePointer
683 friend class Instance; // StorePointer
684 friend class StackFrame; // GetCodeObject assertion.
685 friend class CodeLookupTableBuilder; // profiler
686 friend class Interpreter;
687 friend class InterpreterHelpers;
688 friend class Simulator;
689 friend class SimulatorHelpers;
690 friend class ObjectLocator;
691 friend class WriteBarrierUpdateVisitor; // CheckHeapPointerStore
692 friend class OffsetsTable;
693 friend class Object;
694
695 DISALLOW_ALLOCATION();
696 DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectLayout);
697};
698
699inline intptr_t ObjectPtr::GetClassId() const {
700 return ptr()->GetClassId();
701}
702
703class ClassLayout : public ObjectLayout {
704 public:
705 enum ClassFinalizedState {
706 kAllocated = 0, // Initial state.
707 kPreFinalized, // VM classes: size precomputed, but no checks done.
708 kFinalized, // Class parsed, code compiled, not ready for allocation.
709 kAllocateFinalized, // CHA invalidated, class is ready for allocation.
710 };
711 enum ClassLoadingState {
712 // Class object is created, but it is not filled up.
713 // At this state class can only be used as a forward reference during
714 // class loading.
715 kNameOnly = 0,
716 // Class declaration information such as type parameters, supertype and
717 // implemented interfaces are loaded. However, types in the class are
718 // not finalized yet.
719 kDeclarationLoaded,
720 // Types in the class are finalized. At this point, members can be loaded
721 // and class can be finalized.
722 kTypeFinalized,
723 };
724
725 private:
726 RAW_HEAP_OBJECT_IMPLEMENTATION(Class);
727
728 VISIT_FROM(ObjectPtr, name_);
729 StringPtr name_;
730 StringPtr user_name_;
731 ArrayPtr functions_;
732 ArrayPtr functions_hash_table_;
733 ArrayPtr fields_;
734 ArrayPtr offset_in_words_to_field_;
735 ArrayPtr interfaces_; // Array of AbstractType.
736 ScriptPtr script_;
737 LibraryPtr library_;
738 TypeArgumentsPtr type_parameters_; // Array of TypeParameter.
739 AbstractTypePtr super_type_;
740 FunctionPtr signature_function_; // Associated function for typedef class.
741 ArrayPtr constants_; // Canonicalized const instances of this class.
742 TypePtr declaration_type_; // Declaration type for this class.
743 ArrayPtr invocation_dispatcher_cache_; // Cache for dispatcher functions.
744 CodePtr allocation_stub_; // Stub code for allocation of instances.
745 GrowableObjectArrayPtr direct_implementors_; // Array of Class.
746 GrowableObjectArrayPtr direct_subclasses_; // Array of Class.
747 ArrayPtr dependent_code_; // CHA optimized codes.
748 VISIT_TO(ObjectPtr, dependent_code_);
749 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
750 switch (kind) {
751 case Snapshot::kFullAOT:
752 return reinterpret_cast<ObjectPtr*>(&allocation_stub_);
753 case Snapshot::kFull:
754 return reinterpret_cast<ObjectPtr*>(&direct_subclasses_);
755 case Snapshot::kFullJIT:
756 return reinterpret_cast<ObjectPtr*>(&dependent_code_);
757 case Snapshot::kMessage:
758 case Snapshot::kNone:
759 case Snapshot::kInvalid:
760 break;
761 }
762 UNREACHABLE();
763 return NULL;
764 }
765
766 TokenPosition token_pos_;
767 TokenPosition end_token_pos_;
768
769 classid_t id_; // Class Id, also index in the class table.
770 int16_t num_type_arguments_; // Number of type arguments in flattened vector.
771 uint16_t num_native_fields_;
772 uint32_t state_bits_;
773
774 // Size if fixed len or 0 if variable len.
775 int32_t host_instance_size_in_words_;
776
777 // Offset of type args fld.
778 int32_t host_type_arguments_field_offset_in_words_;
779
780 // Offset of the next instance field.
781 int32_t host_next_field_offset_in_words_;
782
783#if !defined(DART_PRECOMPILED_RUNTIME)
784 // Size if fixed len or 0 if variable len (target).
785 int32_t target_instance_size_in_words_;
786
787 // Offset of type args fld.
788 int32_t target_type_arguments_field_offset_in_words_;
789
790 // Offset of the next instance field (target).
791 int32_t target_next_field_offset_in_words_;
792#endif // !defined(DART_PRECOMPILED_RUNTIME)
793
794#if !defined(DART_PRECOMPILED_RUNTIME)
795 typedef BitField<uint32_t, bool, 0, 1> IsDeclaredInBytecode;
796 typedef BitField<uint32_t, uint32_t, 1, 31> BinaryDeclarationOffset;
797 uint32_t binary_declaration_;
798#endif // !defined(DART_PRECOMPILED_RUNTIME)
799
800 friend class Instance;
801 friend class Isolate;
802 friend class Object;
803 friend class InstanceLayout;
804 friend class InstructionsLayout;
805 friend class TypeArgumentsLayout;
806 friend class SnapshotReader;
807 friend class InstanceSerializationCluster;
808 friend class CidRewriteVisitor;
809};
810
811class PatchClassLayout : public ObjectLayout {
812 private:
813 RAW_HEAP_OBJECT_IMPLEMENTATION(PatchClass);
814
815 VISIT_FROM(ObjectPtr, patched_class_);
816 ClassPtr patched_class_;
817 ClassPtr origin_class_;
818 ScriptPtr script_;
819 ExternalTypedDataPtr library_kernel_data_;
820 VISIT_TO(ObjectPtr, library_kernel_data_);
821
822 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
823 switch (kind) {
824 case Snapshot::kFullAOT:
825 return reinterpret_cast<ObjectPtr*>(&script_);
826 case Snapshot::kFull:
827 case Snapshot::kFullJIT:
828 return reinterpret_cast<ObjectPtr*>(&library_kernel_data_);
829 case Snapshot::kMessage:
830 case Snapshot::kNone:
831 case Snapshot::kInvalid:
832 break;
833 }
834 UNREACHABLE();
835 return NULL;
836 }
837
838 NOT_IN_PRECOMPILED(intptr_t library_kernel_offset_);
839
840 friend class Function;
841};
842
843class FunctionLayout : public ObjectLayout {
844 public:
845 // When you add a new kind, please also update the observatory to account
846 // for the new string returned by KindToCString().
847 // - runtime/observatory/lib/src/models/objects/function.dart (FunctionKind)
848 // - runtime/observatory/lib/src/elements/function_view.dart
849 // (_functionKindToString)
850 // - runtime/observatory/lib/src/service/object.dart (stringToFunctionKind)
851#define FOR_EACH_RAW_FUNCTION_KIND(V) \
852 /* an ordinary or operator method */ \
853 V(RegularFunction) \
854 /* a user-declared closure function */ \
855 V(ClosureFunction) \
856 /* an implicit closure (i.e., tear-off) */ \
857 V(ImplicitClosureFunction) \
858 /* a signature only without actual code */ \
859 V(SignatureFunction) \
860 /* getter functions e.g: get foo() { .. } */ \
861 V(GetterFunction) \
862 /* setter functions e.g: set foo(..) { .. } */ \
863 V(SetterFunction) \
864 /* a generative (is_static=false) or factory (is_static=true) constructor */ \
865 V(Constructor) \
866 /* an implicit getter for instance fields */ \
867 V(ImplicitGetter) \
868 /* an implicit setter for instance fields */ \
869 V(ImplicitSetter) \
870 /* represents an implicit getter for static fields with initializers */ \
871 V(ImplicitStaticGetter) \
872 /* the initialization expression for a static or instance field */ \
873 V(FieldInitializer) \
874 /* return a closure on the receiver for tear-offs */ \
875 V(MethodExtractor) \
876 /* builds an Invocation and invokes noSuchMethod */ \
877 V(NoSuchMethodDispatcher) \
878 /* invokes a field as a closure (i.e., call-through-getter) */ \
879 V(InvokeFieldDispatcher) \
880 /* a generated irregexp matcher function. */ \
881 V(IrregexpFunction) \
882 /* a forwarder which performs type checks for arguments of a dynamic call */ \
883 /* (i.e., those checks omitted by the caller for interface calls). */ \
884 V(DynamicInvocationForwarder) \
885 V(FfiTrampoline)
886
887 enum Kind {
888#define KIND_DEFN(Name) k##Name,
889 FOR_EACH_RAW_FUNCTION_KIND(KIND_DEFN)
890#undef KIND_DEFN
891 };
892
893 static const char* KindToCString(Kind k) {
894 switch (k) {
895#define KIND_CASE(Name) \
896 case Kind::k##Name: \
897 return #Name;
898 FOR_EACH_RAW_FUNCTION_KIND(KIND_CASE)
899#undef KIND_CASE
900 default:
901 UNREACHABLE();
902 return nullptr;
903 }
904 }
905
906 static bool ParseKind(const char* str, Kind* out) {
907#define KIND_CASE(Name) \
908 if (strcmp(str, #Name) == 0) { \
909 *out = Kind::k##Name; \
910 return true; \
911 }
912 FOR_EACH_RAW_FUNCTION_KIND(KIND_CASE)
913#undef KIND_CASE
914 return false;
915 }
916
917 enum AsyncModifier {
918 kNoModifier = 0x0,
919 kAsyncBit = 0x1,
920 kGeneratorBit = 0x2,
921 kAsync = kAsyncBit,
922 kSyncGen = kGeneratorBit,
923 kAsyncGen = kAsyncBit | kGeneratorBit,
924 };
925
926 // Wraps a 64-bit integer to represent the bitmap for unboxed parameters and
927 // return value. Two bits are used for each of them - the first one indicates
928 // whether this value is unboxed or not, and the second one says whether it is
929 // an integer or a double. It includes the two bits for the receiver, even
930 // though currently we do not have information from TFA that allows the
931 // receiver to be unboxed.
932 class UnboxedParameterBitmap {
933 public:
934 static constexpr intptr_t kBitsPerParameter = 2;
935 static constexpr intptr_t kParameterBitmask = (1 << kBitsPerParameter) - 1;
936 static constexpr intptr_t kCapacity =
937 (kBitsPerByte * sizeof(uint64_t)) / kBitsPerParameter;
938
939 UnboxedParameterBitmap() : bitmap_(0) {}
940 explicit UnboxedParameterBitmap(uint64_t bitmap) : bitmap_(bitmap) {}
941 UnboxedParameterBitmap(const UnboxedParameterBitmap&) = default;
942 UnboxedParameterBitmap& operator=(const UnboxedParameterBitmap&) = default;
943
944 DART_FORCE_INLINE bool IsUnboxed(intptr_t position) const {
945 if (position >= kCapacity) {
946 return false;
947 }
948 ASSERT(Utils::TestBit(bitmap_, kBitsPerParameter * position) ||
949 !Utils::TestBit(bitmap_, kBitsPerParameter * position + 1));
950 return Utils::TestBit(bitmap_, kBitsPerParameter * position);
951 }
952 DART_FORCE_INLINE bool IsUnboxedInteger(intptr_t position) const {
953 if (position >= kCapacity) {
954 return false;
955 }
956 return Utils::TestBit(bitmap_, kBitsPerParameter * position) &&
957 !Utils::TestBit(bitmap_, kBitsPerParameter * position + 1);
958 }
959 DART_FORCE_INLINE bool IsUnboxedDouble(intptr_t position) const {
960 if (position >= kCapacity) {
961 return false;
962 }
963 return Utils::TestBit(bitmap_, kBitsPerParameter * position) &&
964 Utils::TestBit(bitmap_, kBitsPerParameter * position + 1);
965 }
966 DART_FORCE_INLINE void SetUnboxedInteger(intptr_t position) {
967 ASSERT(position < kCapacity);
968 bitmap_ |= Utils::Bit<decltype(bitmap_)>(kBitsPerParameter * position);
969 ASSERT(!Utils::TestBit(bitmap_, kBitsPerParameter * position + 1));
970 }
971 DART_FORCE_INLINE void SetUnboxedDouble(intptr_t position) {
972 ASSERT(position < kCapacity);
973 bitmap_ |= Utils::Bit<decltype(bitmap_)>(kBitsPerParameter * position);
974 bitmap_ |=
975 Utils::Bit<decltype(bitmap_)>(kBitsPerParameter * position + 1);
976 }
977 DART_FORCE_INLINE uint64_t Value() const { return bitmap_; }
978 DART_FORCE_INLINE bool IsEmpty() const { return bitmap_ == 0; }
979 DART_FORCE_INLINE void Reset() { bitmap_ = 0; }
980 DART_FORCE_INLINE bool HasUnboxedParameters() const {
981 return (bitmap_ >> kBitsPerParameter) != 0;
982 }
983 DART_FORCE_INLINE bool HasUnboxedReturnValue() const {
984 return (bitmap_ & kParameterBitmask) != 0;
985 }
986
987 private:
988 uint64_t bitmap_;
989 };
990
991 static constexpr intptr_t kMaxFixedParametersBits = 15;
992 static constexpr intptr_t kMaxOptionalParametersBits = 14;
993
994 private:
995 friend class Class;
996
997 RAW_HEAP_OBJECT_IMPLEMENTATION(Function);
998
999 uword entry_point_; // Accessed from generated code.
1000 uword unchecked_entry_point_; // Accessed from generated code.
1001
1002 VISIT_FROM(ObjectPtr, name_);
1003 StringPtr name_;
1004 ObjectPtr owner_; // Class or patch class or mixin class
1005 // where this function is defined.
1006 AbstractTypePtr result_type_;
1007 ArrayPtr parameter_types_;
1008 ArrayPtr parameter_names_;
1009 TypeArgumentsPtr type_parameters_; // Array of TypeParameter.
1010 ObjectPtr data_; // Additional data specific to the function kind. See
1011 // Function::set_data() for details.
1012 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
1013 switch (kind) {
1014 case Snapshot::kFullAOT:
1015 case Snapshot::kFull:
1016 case Snapshot::kFullJIT:
1017 return reinterpret_cast<ObjectPtr*>(&data_);
1018 case Snapshot::kMessage:
1019 case Snapshot::kNone:
1020 case Snapshot::kInvalid:
1021 break;
1022 }
1023 UNREACHABLE();
1024 return NULL;
1025 }
1026 ArrayPtr ic_data_array_; // ICData of unoptimized code.
1027 ObjectPtr* to_no_code() {
1028 return reinterpret_cast<ObjectPtr*>(&ic_data_array_);
1029 }
1030 CodePtr code_; // Currently active code. Accessed from generated code.
1031 NOT_IN_PRECOMPILED(BytecodePtr bytecode_);
1032 NOT_IN_PRECOMPILED(CodePtr unoptimized_code_); // Unoptimized code, keep it
1033 // after optimization.
1034#if defined(DART_PRECOMPILED_RUNTIME)
1035 VISIT_TO(ObjectPtr, code_);
1036#else
1037 VISIT_TO(ObjectPtr, unoptimized_code_);
1038#endif
1039
1040 NOT_IN_PRECOMPILED(TokenPosition token_pos_);
1041 NOT_IN_PRECOMPILED(TokenPosition end_token_pos_);
1042 uint32_t kind_tag_; // See Function::KindTagBits.
1043 uint32_t packed_fields_;
1044
1045 typedef BitField<uint32_t, bool, 0, 1> PackedHasNamedOptionalParameters;
1046 typedef BitField<uint32_t,
1047 bool,
1048 PackedHasNamedOptionalParameters::kNextBit,
1049 1>
1050 OptimizableBit;
1051 typedef BitField<uint32_t, bool, OptimizableBit::kNextBit, 1>
1052 BackgroundOptimizableBit;
1053 typedef BitField<uint32_t,
1054 uint16_t,
1055 BackgroundOptimizableBit::kNextBit,
1056 kMaxFixedParametersBits>
1057 PackedNumFixedParameters;
1058 typedef BitField<uint32_t,
1059 uint16_t,
1060 PackedNumFixedParameters::kNextBit,
1061 kMaxOptionalParametersBits>
1062 PackedNumOptionalParameters;
1063 static_assert(PackedNumOptionalParameters::kNextBit <=
1064 kBitsPerWord * sizeof(decltype(packed_fields_)),
1065 "FunctionLayout::packed_fields_ bitfields don't align.");
1066
1067#define JIT_FUNCTION_COUNTERS(F) \
1068 F(intptr_t, int32_t, usage_counter) \
1069 F(intptr_t, uint16_t, optimized_instruction_count) \
1070 F(intptr_t, uint16_t, optimized_call_site_count) \
1071 F(int8_t, int8_t, deoptimization_counter) \
1072 F(intptr_t, int8_t, state_bits) \
1073 F(int, int8_t, inlining_depth)
1074
1075#if !defined(DART_PRECOMPILED_RUNTIME)
1076 typedef BitField<uint32_t, bool, 0, 1> IsDeclaredInBytecode;
1077 typedef BitField<uint32_t, uint32_t, 1, 31> BinaryDeclarationOffset;
1078 uint32_t binary_declaration_;
1079
1080#define DECLARE(return_type, type, name) type name##_;
1081 JIT_FUNCTION_COUNTERS(DECLARE)
1082#undef DECLARE
1083
1084#endif // !defined(DART_PRECOMPILED_RUNTIME)
1085
1086 NOT_IN_PRECOMPILED(UnboxedParameterBitmap unboxed_parameters_info_);
1087};
1088
1089class ClosureDataLayout : public ObjectLayout {
1090 private:
1091 RAW_HEAP_OBJECT_IMPLEMENTATION(ClosureData);
1092
1093 VISIT_FROM(ObjectPtr, context_scope_);
1094 ContextScopePtr context_scope_;
1095 FunctionPtr parent_function_; // Enclosing function of this local function.
1096 TypePtr signature_type_;
1097 InstancePtr closure_; // Closure object for static implicit closures.
1098 VISIT_TO(ObjectPtr, closure_);
1099
1100 friend class Function;
1101};
1102
1103class SignatureDataLayout : public ObjectLayout {
1104 private:
1105 RAW_HEAP_OBJECT_IMPLEMENTATION(SignatureData);
1106
1107 VISIT_FROM(ObjectPtr, parent_function_);
1108 FunctionPtr parent_function_; // Enclosing function of this sig. function.
1109 TypePtr signature_type_;
1110 VISIT_TO(ObjectPtr, signature_type_);
1111 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
1112
1113 friend class Function;
1114};
1115
1116class RedirectionDataLayout : public ObjectLayout {
1117 private:
1118 RAW_HEAP_OBJECT_IMPLEMENTATION(RedirectionData);
1119
1120 VISIT_FROM(ObjectPtr, type_);
1121 TypePtr type_;
1122 StringPtr identifier_;
1123 FunctionPtr target_;
1124 VISIT_TO(ObjectPtr, target_);
1125 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
1126};
1127
1128class FfiTrampolineDataLayout : public ObjectLayout {
1129 private:
1130 RAW_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData);
1131
1132 VISIT_FROM(ObjectPtr, signature_type_);
1133 TypePtr signature_type_;
1134 FunctionPtr c_signature_;
1135
1136 // Target Dart method for callbacks, otherwise null.
1137 FunctionPtr callback_target_;
1138
1139 // For callbacks, value to return if Dart target throws an exception.
1140 InstancePtr callback_exceptional_return_;
1141
1142 VISIT_TO(ObjectPtr, callback_exceptional_return_);
1143 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
1144
1145 // Callback id for callbacks.
1146 //
1147 // The callbacks ids are used so that native callbacks can lookup their own
1148 // code objects, since native code doesn't pass code objects into function
1149 // calls. The callback id is also used to for verifying that callbacks are
1150 // called on the correct isolate. See DLRT_VerifyCallbackIsolate for details.
1151 //
1152 // Will be 0 for non-callbacks. Check 'callback_target_' to determine if this
1153 // is a callback or not.
1154 uint32_t callback_id_;
1155};
1156
1157class FieldLayout : public ObjectLayout {
1158 RAW_HEAP_OBJECT_IMPLEMENTATION(Field);
1159
1160 VISIT_FROM(ObjectPtr, name_);
1161 StringPtr name_;
1162 ObjectPtr owner_; // Class or patch class or mixin class
1163 // where this field is defined or original field.
1164 AbstractTypePtr type_;
1165 FunctionPtr initializer_function_; // Static initializer function.
1166
1167 // - for instance fields: offset in words to the value in the class instance.
1168 // - for static fields: index into field_table.
1169 SmiPtr host_offset_or_field_id_;
1170
1171 // When generating APPJIT snapshots after running the application it is
1172 // necessary to save the initial value of static fields so that we can
1173 // restore the value back to the original initial value.
1174 NOT_IN_PRECOMPILED(InstancePtr saved_initial_value_); // Saved initial value
1175 SmiPtr guarded_list_length_;
1176 ArrayPtr dependent_code_;
1177 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
1178 switch (kind) {
1179 case Snapshot::kFull:
1180 case Snapshot::kFullJIT:
1181 case Snapshot::kFullAOT:
1182 return reinterpret_cast<ObjectPtr*>(&initializer_function_);
1183 case Snapshot::kMessage:
1184 case Snapshot::kNone:
1185 case Snapshot::kInvalid:
1186 break;
1187 }
1188 UNREACHABLE();
1189 return NULL;
1190 }
1191#if defined(DART_PRECOMPILED_RUNTIME)
1192 VISIT_TO(ObjectPtr, dependent_code_);
1193#else
1194 SubtypeTestCachePtr type_test_cache_; // For type test in implicit setter.
1195 VISIT_TO(ObjectPtr, type_test_cache_);
1196#endif
1197 TokenPosition token_pos_;
1198 TokenPosition end_token_pos_;
1199 ClassIdTagType guarded_cid_;
1200 ClassIdTagType is_nullable_; // kNullCid if field can contain null value and
1201 // kInvalidCid otherwise.
1202
1203#if !defined(DART_PRECOMPILED_RUNTIME)
1204 typedef BitField<uint32_t, bool, 0, 1> IsDeclaredInBytecode;
1205 typedef BitField<uint32_t, uint32_t, 1, 31> BinaryDeclarationOffset;
1206 uint32_t binary_declaration_;
1207#endif // !defined(DART_PRECOMPILED_RUNTIME)
1208
1209 // Offset to the guarded length field inside an instance of class matching
1210 // guarded_cid_. Stored corrected by -kHeapObjectTag to simplify code
1211 // generated on platforms with weak addressing modes (ARM).
1212 int8_t guarded_list_length_in_object_offset_;
1213
1214 // Runtime tracking state of exactness of type annotation of this field.
1215 // See StaticTypeExactnessState for the meaning and possible values in this
1216 // field.
1217 int8_t static_type_exactness_state_;
1218
1219 uint16_t kind_bits_; // static, final, const, has initializer....
1220
1221#if !defined(DART_PRECOMPILED_RUNTIME)
1222 // for instance fields, the offset in words in the target architecture
1223 int32_t target_offset_;
1224#endif // !defined(DART_PRECOMPILED_RUNTIME)
1225
1226 friend class CidRewriteVisitor;
1227 friend class GuardFieldClassInstr; // For sizeof(guarded_cid_/...)
1228 friend class LoadFieldInstr; // For sizeof(guarded_cid_/...)
1229 friend class StoreInstanceFieldInstr; // For sizeof(guarded_cid_/...)
1230};
1231
1232class ScriptLayout : public ObjectLayout {
1233 public:
1234 enum {
1235 kLazyLookupSourceAndLineStartsPos = 0,
1236 kLazyLookupSourceAndLineStartsSize = 1,
1237 };
1238
1239 private:
1240 RAW_HEAP_OBJECT_IMPLEMENTATION(Script);
1241
1242 VISIT_FROM(ObjectPtr, url_);
1243 StringPtr url_;
1244 StringPtr resolved_url_;
1245 ArrayPtr compile_time_constants_;
1246 TypedDataPtr line_starts_;
1247 ArrayPtr debug_positions_;
1248 KernelProgramInfoPtr kernel_program_info_;
1249 StringPtr source_;
1250 VISIT_TO(ObjectPtr, source_);
1251 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
1252 switch (kind) {
1253 case Snapshot::kFullAOT:
1254 return reinterpret_cast<ObjectPtr*>(&url_);
1255 case Snapshot::kFull:
1256 case Snapshot::kFullJIT:
1257 return reinterpret_cast<ObjectPtr*>(&kernel_program_info_);
1258 case Snapshot::kMessage:
1259 case Snapshot::kNone:
1260 case Snapshot::kInvalid:
1261 break;
1262 }
1263 UNREACHABLE();
1264 return NULL;
1265 }
1266
1267 int32_t line_offset_;
1268 int32_t col_offset_;
1269
1270 using LazyLookupSourceAndLineStartsBit =
1271 BitField<uint8_t,
1272 bool,
1273 kLazyLookupSourceAndLineStartsPos,
1274 kLazyLookupSourceAndLineStartsSize>;
1275 uint8_t flags_;
1276
1277 intptr_t kernel_script_index_;
1278 int64_t load_timestamp_;
1279};
1280
1281class LibraryLayout : public ObjectLayout {
1282 enum LibraryState {
1283 kAllocated, // Initial state.
1284 kLoadRequested, // Compiler or script requested load of library.
1285 kLoadInProgress, // Library is in the process of being loaded.
1286 kLoaded, // Library is loaded.
1287 };
1288
1289 enum LibraryFlags {
1290 kDartSchemeBit = 0,
1291 kDebuggableBit, // True if debugger can stop in library.
1292 kInFullSnapshotBit, // True if library is in a full snapshot.
1293 kNnbdBit, // True if library is non nullable by default.
1294 kNnbdCompiledModePos, // Encodes nnbd compiled mode of constants in lib.
1295 kNnbdCompiledModeSize = 2,
1296 kNumFlagBits = kNnbdCompiledModePos + kNnbdCompiledModeSize,
1297 };
1298 COMPILE_ASSERT(kNumFlagBits <= (sizeof(uint8_t) * kBitsPerByte));
1299 class DartSchemeBit : public BitField<uint8_t, bool, kDartSchemeBit, 1> {};
1300 class DebuggableBit : public BitField<uint8_t, bool, kDebuggableBit, 1> {};
1301 class InFullSnapshotBit
1302 : public BitField<uint8_t, bool, kInFullSnapshotBit, 1> {};
1303 class NnbdBit : public BitField<uint8_t, bool, kNnbdBit, 1> {};
1304 class NnbdCompiledModeBits : public BitField<uint8_t,
1305 uint8_t,
1306 kNnbdCompiledModePos,
1307 kNnbdCompiledModeSize> {};
1308
1309 RAW_HEAP_OBJECT_IMPLEMENTATION(Library);
1310
1311 VISIT_FROM(ObjectPtr, name_);
1312 StringPtr name_;
1313 StringPtr url_;
1314 StringPtr private_key_;
1315 ArrayPtr dictionary_; // Top-level names in this library.
1316 GrowableObjectArrayPtr metadata_; // Metadata on classes, methods etc.
1317 ClassPtr toplevel_class_; // Class containing top-level elements.
1318 GrowableObjectArrayPtr used_scripts_;
1319 LoadingUnitPtr loading_unit_;
1320 ArrayPtr imports_; // List of Namespaces imported without prefix.
1321 ArrayPtr exports_; // List of re-exported Namespaces.
1322 ArrayPtr dependencies_;
1323 ExternalTypedDataPtr kernel_data_;
1324 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
1325 switch (kind) {
1326 case Snapshot::kFullAOT:
1327 return reinterpret_cast<ObjectPtr*>(&exports_);
1328 case Snapshot::kFull:
1329 case Snapshot::kFullJIT:
1330 return reinterpret_cast<ObjectPtr*>(&kernel_data_);
1331 case Snapshot::kMessage:
1332 case Snapshot::kNone:
1333 case Snapshot::kInvalid:
1334 break;
1335 }
1336 UNREACHABLE();
1337 return NULL;
1338 }
1339 ArrayPtr resolved_names_; // Cache of resolved names in library scope.
1340 ArrayPtr exported_names_; // Cache of exported names by library.
1341 ArrayPtr loaded_scripts_; // Array of scripts loaded in this library.
1342 VISIT_TO(ObjectPtr, loaded_scripts_);
1343
1344 Dart_NativeEntryResolver native_entry_resolver_; // Resolves natives.
1345 Dart_NativeEntrySymbol native_entry_symbol_resolver_;
1346 classid_t index_; // Library id number.
1347 uint16_t num_imports_; // Number of entries in imports_.
1348 int8_t load_state_; // Of type LibraryState.
1349 uint8_t flags_; // BitField for LibraryFlags.
1350
1351#if !defined(DART_PRECOMPILED_RUNTIME)
1352 typedef BitField<uint32_t, bool, 0, 1> IsDeclaredInBytecode;
1353 typedef BitField<uint32_t, uint32_t, 1, 31> BinaryDeclarationOffset;
1354 uint32_t binary_declaration_;
1355#endif // !defined(DART_PRECOMPILED_RUNTIME)
1356
1357 friend class Class;
1358 friend class Isolate;
1359};
1360
1361class NamespaceLayout : public ObjectLayout {
1362 RAW_HEAP_OBJECT_IMPLEMENTATION(Namespace);
1363
1364 VISIT_FROM(ObjectPtr, library_);
1365 LibraryPtr library_; // library with name dictionary.
1366 ArrayPtr show_names_; // list of names that are exported.
1367 ArrayPtr hide_names_; // list of names that are hidden.
1368 FieldPtr metadata_field_; // remembers the token pos of metadata if any,
1369 // and the metadata values if computed.
1370 VISIT_TO(ObjectPtr, metadata_field_);
1371 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
1372};
1373
1374class KernelProgramInfoLayout : public ObjectLayout {
1375 RAW_HEAP_OBJECT_IMPLEMENTATION(KernelProgramInfo);
1376
1377 VISIT_FROM(ObjectPtr, string_offsets_);
1378 TypedDataPtr string_offsets_;
1379 ExternalTypedDataPtr string_data_;
1380 TypedDataPtr canonical_names_;
1381 ExternalTypedDataPtr metadata_payloads_;
1382 ExternalTypedDataPtr metadata_mappings_;
1383 ArrayPtr scripts_;
1384 ArrayPtr constants_;
1385 ArrayPtr bytecode_component_;
1386 GrowableObjectArrayPtr potential_natives_;
1387 GrowableObjectArrayPtr potential_pragma_functions_;
1388 ExternalTypedDataPtr constants_table_;
1389 ArrayPtr libraries_cache_;
1390 ArrayPtr classes_cache_;
1391 ObjectPtr retained_kernel_blob_;
1392 VISIT_TO(ObjectPtr, retained_kernel_blob_);
1393
1394 uint32_t kernel_binary_version_;
1395
1396 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
1397 return reinterpret_cast<ObjectPtr*>(&constants_table_);
1398 }
1399};
1400
1401class WeakSerializationReferenceLayout : public ObjectLayout {
1402 RAW_HEAP_OBJECT_IMPLEMENTATION(WeakSerializationReference);
1403
1404#if defined(DART_PRECOMPILED_RUNTIME)
1405 VISIT_NOTHING();
1406 ClassIdTagType cid_;
1407#else
1408 VISIT_FROM(ObjectPtr, target_);
1409 ObjectPtr target_;
1410 VISIT_TO(ObjectPtr, target_);
1411#endif
1412};
1413
1414class CodeLayout : public ObjectLayout {
1415 RAW_HEAP_OBJECT_IMPLEMENTATION(Code);
1416
1417 // When in the precompiled runtime, there is no disabling of Code objects
1418 // and thus no active_instructions_ field. Thus, the entry point caches are
1419 // only set once during deserialization. If not using bare instructions,
1420 // the caches should match the entry points for instructions_.
1421 //
1422 // Otherwise, they should contain entry points for active_instructions_.
1423
1424 uword entry_point_; // Accessed from generated code.
1425
1426 // In AOT this entry-point supports switchable calls. It checks the type of
1427 // the receiver on entry to the function and calls a stub to patch up the
1428 // caller if they mismatch.
1429 uword monomorphic_entry_point_; // Accessed from generated code (AOT only).
1430
1431 // Entry-point used from call-sites with some additional static information.
1432 // The exact behavior of this entry-point depends on the kind of function:
1433 //
1434 // kRegularFunction/kSetter/kGetter:
1435 //
1436 // Call-site is assumed to know that the (type) arguments are invariantly
1437 // type-correct against the actual runtime-type of the receiver. For
1438 // instance, this entry-point is used for invocations against "this" and
1439 // invocations from IC stubs that test the class type arguments.
1440 //
1441 // kClosureFunction:
1442 //
1443 // Call-site is assumed to pass the correct number of positional and type
1444 // arguments (except in the case of partial instantiation, when the type
1445 // arguments are omitted). All (type) arguments are assumed to match the
1446 // corresponding (type) parameter types (bounds).
1447 //
1448 // kImplicitClosureFunction:
1449 //
1450 // Similar to kClosureFunction, except that the types (bounds) of the (type)
1451 // arguments are expected to match the *runtime signature* of the closure,
1452 // which (unlike with kClosureFunction) may have more general (type)
1453 // parameter types (bounds) than the declared type of the forwarded method.
1454 //
1455 // In many cases a distinct static entry-point will not be created for a
1456 // function if it would not be able to skip a lot of work (e.g., no argument
1457 // type checks are necessary or this Code belongs to a stub). In this case
1458 // 'unchecked_entry_point_' will refer to the same position as 'entry_point_'.
1459 //
1460 uword unchecked_entry_point_; // Accessed from generated code.
1461 uword monomorphic_unchecked_entry_point_; // Accessed from generated code.
1462
1463 VISIT_FROM(ObjectPtr, object_pool_);
1464 ObjectPoolPtr object_pool_; // Accessed from generated code.
1465 InstructionsPtr instructions_; // Accessed from generated code.
1466 // If owner_ is Function::null() the owner is a regular stub.
1467 // If owner_ is a Class the owner is the allocation stub for that class.
1468 // Else, owner_ is a regular Dart Function.
1469 ObjectPtr owner_; // Function, Null, or a Class.
1470 ExceptionHandlersPtr exception_handlers_;
1471 PcDescriptorsPtr pc_descriptors_;
1472 // If FLAG_precompiled_mode, then this field contains
1473 // TypedDataPtr catch_entry_moves_maps
1474 // Otherwise, it is
1475 // SmiPtr num_variables
1476 ObjectPtr catch_entry_;
1477 CompressedStackMapsPtr compressed_stackmaps_;
1478 ArrayPtr inlined_id_to_function_;
1479 CodeSourceMapPtr code_source_map_;
1480 NOT_IN_PRECOMPILED(InstructionsPtr active_instructions_);
1481 NOT_IN_PRECOMPILED(ArrayPtr deopt_info_array_);
1482 // (code-offset, function, code) triples.
1483 NOT_IN_PRECOMPILED(ArrayPtr static_calls_target_table_);
1484 // If return_address_metadata_ is a Smi, it is the offset to the prologue.
1485 // Else, return_address_metadata_ is null.
1486 NOT_IN_PRODUCT(ObjectPtr return_address_metadata_);
1487 NOT_IN_PRODUCT(LocalVarDescriptorsPtr var_descriptors_);
1488 NOT_IN_PRODUCT(ArrayPtr comments_);
1489
1490#if !defined(PRODUCT)
1491 VISIT_TO(ObjectPtr, comments_);
1492#elif defined(DART_PRECOMPILED_RUNTIME)
1493 VISIT_TO(ObjectPtr, code_source_map_);
1494#else
1495 VISIT_TO(ObjectPtr, static_calls_target_table_);
1496#endif
1497
1498 // Compilation timestamp.
1499 NOT_IN_PRODUCT(alignas(8) int64_t compile_timestamp_);
1500
1501 // state_bits_ is a bitfield with three fields:
1502 // The optimized bit, the alive bit, and a count of the number of pointer
1503 // offsets.
1504 // Alive: If true, the embedded object pointers will be visited during GC.
1505 int32_t state_bits_;
1506 // Caches the unchecked entry point offset for instructions_, in case we need
1507 // to reset the active_instructions_ to instructions_.
1508 NOT_IN_PRECOMPILED(uint32_t unchecked_offset_);
1509 // Stores the instructions length when not using RawInstructions objects.
1510 ONLY_IN_PRECOMPILED(uint32_t instructions_length_);
1511
1512 // Variable length data follows here.
1513 int32_t* data() { OPEN_ARRAY_START(int32_t, int32_t); }
1514 const int32_t* data() const { OPEN_ARRAY_START(int32_t, int32_t); }
1515
1516 static bool ContainsPC(const ObjectPtr raw_obj, uword pc);
1517
1518 friend class Function;
1519 template <bool>
1520 friend class MarkingVisitorBase;
1521 friend class StackFrame;
1522 friend class Profiler;
1523 friend class FunctionDeserializationCluster;
1524 friend class CallSiteResetter;
1525};
1526
1527class BytecodeLayout : public ObjectLayout {
1528 RAW_HEAP_OBJECT_IMPLEMENTATION(Bytecode);
1529
1530 uword instructions_;
1531 intptr_t instructions_size_;
1532
1533 VISIT_FROM(ObjectPtr, object_pool_);
1534 ObjectPoolPtr object_pool_;
1535 FunctionPtr function_;
1536 ArrayPtr closures_;
1537 ExceptionHandlersPtr exception_handlers_;
1538 PcDescriptorsPtr pc_descriptors_;
1539 NOT_IN_PRODUCT(LocalVarDescriptorsPtr var_descriptors_);
1540#if defined(PRODUCT)
1541 VISIT_TO(ObjectPtr, pc_descriptors_);
1542#else
1543 VISIT_TO(ObjectPtr, var_descriptors_);
1544#endif
1545
1546 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
1547 return reinterpret_cast<ObjectPtr*>(&pc_descriptors_);
1548 }
1549
1550 int32_t instructions_binary_offset_;
1551 int32_t source_positions_binary_offset_;
1552 int32_t local_variables_binary_offset_;
1553
1554 static bool ContainsPC(ObjectPtr raw_obj, uword pc);
1555
1556 friend class Function;
1557 friend class StackFrame;
1558};
1559
1560class ObjectPoolLayout : public ObjectLayout {
1561 RAW_HEAP_OBJECT_IMPLEMENTATION(ObjectPool);
1562
1563 intptr_t length_;
1564
1565 struct Entry {
1566 union {
1567 ObjectPtr raw_obj_;
1568 uword raw_value_;
1569 };
1570 };
1571 Entry* data() { OPEN_ARRAY_START(Entry, Entry); }
1572 Entry const* data() const { OPEN_ARRAY_START(Entry, Entry); }
1573
1574 // The entry bits are located after the last entry. They are encoded versions
1575 // of `ObjectPool::TypeBits() | ObjectPool::PatchabililtyBit()`.
1576 uint8_t* entry_bits() { return reinterpret_cast<uint8_t*>(&data()[length_]); }
1577 uint8_t const* entry_bits() const {
1578 return reinterpret_cast<uint8_t const*>(&data()[length_]);
1579 }
1580
1581 friend class Object;
1582 friend class CodeSerializationCluster;
1583};
1584
1585class InstructionsLayout : public ObjectLayout {
1586 RAW_HEAP_OBJECT_IMPLEMENTATION(Instructions);
1587 VISIT_NOTHING();
1588
1589 // Instructions size in bytes and flags.
1590 // Currently, only flag indicates 1 or 2 entry points.
1591 uint32_t size_and_flags_;
1592
1593 // Variable length data follows here.
1594 uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
1595
1596 // Private helper function used while visiting stack frames. The
1597 // code which iterates over dart frames is also called during GC and
1598 // is not allowed to create handles.
1599 static bool ContainsPC(const InstructionsPtr raw_instr, uword pc);
1600
1601 friend class CodeLayout;
1602 friend class FunctionLayout;
1603 friend class Code;
1604 friend class StackFrame;
1605 template <bool>
1606 friend class MarkingVisitorBase;
1607 friend class Function;
1608 friend class ImageReader;
1609 friend class ImageWriter;
1610 friend class AssemblyImageWriter;
1611 friend class BlobImageWriter;
1612};
1613
1614// Used only to provide memory accounting for the bare instruction payloads
1615// we serialize, since they are no longer part of RawInstructions objects.
1616class InstructionsSectionLayout : public ObjectLayout {
1617 RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection);
1618 VISIT_NOTHING();
1619
1620 // Instructions section payload length in bytes.
1621 uword payload_length_;
1622
1623 // Variable length data follows here.
1624 uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
1625};
1626
1627class PcDescriptorsLayout : public ObjectLayout {
1628 public:
1629// The macro argument V is passed two arguments, the raw name of the enum value
1630// and the initialization expression used within the enum definition. The uses
1631// of enum values inside the initialization expression are hardcoded currently,
1632// so the second argument is useless outside the enum definition and should be
1633// dropped by other users of this macro.
1634#define FOR_EACH_RAW_PC_DESCRIPTOR(V) \
1635 /* Deoptimization continuation point. */ \
1636 V(Deopt, 1) \
1637 /* IC call. */ \
1638 V(IcCall, kDeopt << 1) \
1639 /* Call to a known target via stub. */ \
1640 V(UnoptStaticCall, kIcCall << 1) \
1641 /* Runtime call. */ \
1642 V(RuntimeCall, kUnoptStaticCall << 1) \
1643 /* OSR entry point in unopt. code. */ \
1644 V(OsrEntry, kRuntimeCall << 1) \
1645 /* Call rewind target address. */ \
1646 V(Rewind, kOsrEntry << 1) \
1647 /* Target-word-size relocation. */ \
1648 V(BSSRelocation, kRewind << 1) \
1649 V(Other, kBSSRelocation << 1) \
1650 V(AnyKind, -1)
1651
1652 enum Kind {
1653#define ENUM_DEF(name, init) k##name = init,
1654 FOR_EACH_RAW_PC_DESCRIPTOR(ENUM_DEF)
1655#undef ENUM_DEF
1656 kLastKind = kOther,
1657 };
1658
1659 static const char* KindToCString(Kind k);
1660 static bool ParseKind(const char* cstr, Kind* out);
1661
1662 // Used to represent the absense of a yield index in PcDescriptors.
1663 static constexpr intptr_t kInvalidYieldIndex = -1;
1664
1665 class KindAndMetadata {
1666 public:
1667 // Most of the time try_index will be small and merged field will fit into
1668 // one byte.
1669 static uint32_t Encode(intptr_t kind,
1670 intptr_t try_index,
1671 intptr_t yield_index) {
1672 return KindShiftBits::encode(Utils::ShiftForPowerOfTwo(kind)) |
1673 TryIndexBits::encode(try_index + 1) |
1674 YieldIndexBits::encode(yield_index + 1);
1675 }
1676
1677 static intptr_t DecodeKind(uint32_t kind_and_metadata) {
1678 return 1 << KindShiftBits::decode(kind_and_metadata);
1679 }
1680
1681 static intptr_t DecodeTryIndex(uint32_t kind_and_metadata) {
1682 return TryIndexBits::decode(kind_and_metadata) - 1;
1683 }
1684
1685 static intptr_t DecodeYieldIndex(uint32_t kind_and_metadata) {
1686 return YieldIndexBits::decode(kind_and_metadata) - 1;
1687 }
1688
1689 private:
1690 static const intptr_t kKindShiftSize = 3;
1691 static const intptr_t kTryIndexSize = 10;
1692 static const intptr_t kYieldIndexSize = 32 - kKindShiftSize - kTryIndexSize;
1693
1694 class KindShiftBits
1695 : public BitField<uint32_t, intptr_t, 0, kKindShiftSize> {};
1696 class TryIndexBits : public BitField<uint32_t,
1697 intptr_t,
1698 KindShiftBits::kNextBit,
1699 kTryIndexSize> {};
1700 class YieldIndexBits : public BitField<uint32_t,
1701 intptr_t,
1702 TryIndexBits::kNextBit,
1703 kYieldIndexSize> {};
1704 };
1705
1706 private:
1707 RAW_HEAP_OBJECT_IMPLEMENTATION(PcDescriptors);
1708 VISIT_NOTHING();
1709
1710 // Number of descriptors. This only needs to be an int32_t, but we make it a
1711 // uword so that the variable length data is 64 bit aligned on 64 bit
1712 // platforms.
1713 uword length_;
1714
1715 // Variable length data follows here.
1716 uint8_t* data() { OPEN_ARRAY_START(uint8_t, intptr_t); }
1717 const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, intptr_t); }
1718
1719 friend class Object;
1720 friend class ImageWriter;
1721};
1722
1723// CodeSourceMap encodes a mapping from code PC ranges to source token
1724// positions and the stack of inlined functions.
1725class CodeSourceMapLayout : public ObjectLayout {
1726 private:
1727 RAW_HEAP_OBJECT_IMPLEMENTATION(CodeSourceMap);
1728 VISIT_NOTHING();
1729
1730 // Length in bytes. This only needs to be an int32_t, but we make it a uword
1731 // so that the variable length data is 64 bit aligned on 64 bit platforms.
1732 uword length_;
1733
1734 // Variable length data follows here.
1735 uint8_t* data() { OPEN_ARRAY_START(uint8_t, intptr_t); }
1736 const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, intptr_t); }
1737
1738 friend class Object;
1739 friend class ImageWriter;
1740};
1741
1742// RawCompressedStackMaps is a compressed representation of the stack maps
1743// for certain PC offsets into a set of instructions, where a stack map is a bit
1744// map that marks each live object index starting from the base of the frame.
1745class CompressedStackMapsLayout : public ObjectLayout {
1746 RAW_HEAP_OBJECT_IMPLEMENTATION(CompressedStackMaps);
1747 VISIT_NOTHING();
1748
1749 // The most significant bits are the length of the encoded payload, in bytes.
1750 // The low bits determine the expected payload contents, as described below.
1751 uint32_t flags_and_size_;
1752
1753 // Variable length data follows here. The contents of the payload depend on
1754 // the type of CompressedStackMaps (CSM) being represented. There are three
1755 // major types of CSM:
1756 //
1757 // 1) GlobalTableBit = false, UsesTableBit = false: CSMs that include all
1758 // information about the stack maps. The payload for these contain tightly
1759 // packed entries with the following information:
1760 //
1761 // * A header containing the following three pieces of information:
1762 // * An unsigned integer representing the PC offset as a delta from the
1763 // PC offset of the previous entry (from 0 for the first entry).
1764 // * An unsigned integer representing the number of bits used for
1765 // spill slot entries.
1766 // * An unsigned integer representing the number of bits used for other
1767 // entries.
1768 // * The body containing the bits for the stack map. The length of the body
1769 // in bits is the sum of the spill slot and non-spill slot bit counts.
1770 //
1771 // 2) GlobalTableBit = false, UsesTableBit = true: CSMs where the majority of
1772 // the stack map information has been offloaded and canonicalized into a
1773 // global table. The payload contains tightly packed entries with the
1774 // following information:
1775 //
1776 // * A header containing just an unsigned integer representing the PC offset
1777 // delta as described above.
1778 // * The body is just an unsigned integer containing the offset into the
1779 // payload for the global table.
1780 //
1781 // 3) GlobalTableBit = true, UsesTableBit = false: A CSM implementing the
1782 // global table. Here, the payload contains tightly packed entries with
1783 // the following information:
1784 //
1785 // * A header containing the following two pieces of information:
1786 // * An unsigned integer representing the number of bits used for
1787 // spill slot entries.
1788 // * An unsigned integer representing the number of bits used for other
1789 // entries.
1790 // * The body containing the bits for the stack map. The length of the body
1791 // in bits is the sum of the spill slot and non-spill slot bit counts.
1792 //
1793 // In all types of CSM, each unsigned integer is LEB128 encoded, as generally
1794 // they tend to fit in a single byte or two. Thus, entry headers are not a
1795 // fixed length, and currently there is no random access of entries. In
1796 // addition, PC offsets are currently encoded as deltas, which also inhibits
1797 // random access without accessing previous entries. That means to find an
1798 // entry for a given PC offset, a linear search must be done where the payload
1799 // is decoded up to the entry whose PC offset is >= the given PC.
1800
1801 uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
1802 const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
1803
1804 class GlobalTableBit : public BitField<uint32_t, bool, 0, 1> {};
1805 class UsesTableBit
1806 : public BitField<uint32_t, bool, GlobalTableBit::kNextBit, 1> {};
1807 class SizeField : public BitField<uint32_t,
1808 uint32_t,
1809 UsesTableBit::kNextBit,
1810 sizeof(flags_and_size_) * kBitsPerByte -
1811 UsesTableBit::kNextBit> {};
1812
1813 friend class ImageWriter;
1814};
1815
1816class LocalVarDescriptorsLayout : public ObjectLayout {
1817 public:
1818 enum VarInfoKind {
1819 kStackVar = 1,
1820 kContextVar,
1821 kContextLevel,
1822 kSavedCurrentContext,
1823 };
1824
1825 enum {
1826 kKindPos = 0,
1827 kKindSize = 8,
1828 kIndexPos = kKindPos + kKindSize,
1829 // Since there are 24 bits for the stack slot index, Functions can have
1830 // only ~16.7 million stack slots.
1831 kPayloadSize = sizeof(int32_t) * kBitsPerByte,
1832 kIndexSize = kPayloadSize - kIndexPos,
1833 kIndexBias = 1 << (kIndexSize - 1),
1834 kMaxIndex = (1 << (kIndexSize - 1)) - 1,
1835 };
1836
1837 class IndexBits : public BitField<int32_t, int32_t, kIndexPos, kIndexSize> {};
1838 class KindBits : public BitField<int32_t, int8_t, kKindPos, kKindSize> {};
1839
1840 struct VarInfo {
1841 int32_t index_kind; // Bitfield for slot index on stack or in context,
1842 // and Entry kind of type VarInfoKind.
1843 TokenPosition declaration_pos; // Token position of declaration.
1844 TokenPosition begin_pos; // Token position of scope start.
1845 TokenPosition end_pos; // Token position of scope end.
1846 int16_t scope_id; // Scope to which the variable belongs.
1847
1848 VarInfoKind kind() const {
1849 return static_cast<VarInfoKind>(KindBits::decode(index_kind));
1850 }
1851 void set_kind(VarInfoKind kind) {
1852 index_kind = KindBits::update(kind, index_kind);
1853 }
1854 int32_t index() const { return IndexBits::decode(index_kind) - kIndexBias; }
1855 void set_index(int32_t index) {
1856 index_kind = IndexBits::update(index + kIndexBias, index_kind);
1857 }
1858 };
1859
1860 private:
1861 RAW_HEAP_OBJECT_IMPLEMENTATION(LocalVarDescriptors);
1862 // Number of descriptors. This only needs to be an int32_t, but we make it a
1863 // uword so that the variable length data is 64 bit aligned on 64 bit
1864 // platforms.
1865 uword num_entries_;
1866
1867 VISIT_FROM(ObjectPtr, names()[0]);
1868 StringPtr* names() {
1869 // Array of [num_entries_] variable names.
1870 OPEN_ARRAY_START(StringPtr, StringPtr);
1871 }
1872 StringPtr* nameAddrAt(intptr_t i) { return &(names()[i]); }
1873 VISIT_TO_LENGTH(ObjectPtr, nameAddrAt(length - 1));
1874
1875 // Variable info with [num_entries_] entries.
1876 VarInfo* data() {
1877 return reinterpret_cast<VarInfo*>(nameAddrAt(num_entries_));
1878 }
1879
1880 friend class Object;
1881};
1882
1883class ExceptionHandlersLayout : public ObjectLayout {
1884 private:
1885 RAW_HEAP_OBJECT_IMPLEMENTATION(ExceptionHandlers);
1886
1887 // Number of exception handler entries.
1888 int32_t num_entries_;
1889
1890 // Array with [num_entries_] entries. Each entry is an array of all handled
1891 // exception types.
1892 VISIT_FROM(ObjectPtr, handled_types_data_)
1893 ArrayPtr handled_types_data_;
1894 VISIT_TO_LENGTH(ObjectPtr, &handled_types_data_);
1895
1896 // Exception handler info of length [num_entries_].
1897 const ExceptionHandlerInfo* data() const {
1898 OPEN_ARRAY_START(ExceptionHandlerInfo, intptr_t);
1899 }
1900 ExceptionHandlerInfo* data() {
1901 OPEN_ARRAY_START(ExceptionHandlerInfo, intptr_t);
1902 }
1903
1904 friend class Object;
1905};
1906
1907class ContextLayout : public ObjectLayout {
1908 RAW_HEAP_OBJECT_IMPLEMENTATION(Context);
1909
1910 int32_t num_variables_;
1911
1912 VISIT_FROM(ObjectPtr, parent_);
1913 ContextPtr parent_;
1914
1915 // Variable length data follows here.
1916 ObjectPtr* data() { OPEN_ARRAY_START(ObjectPtr, ObjectPtr); }
1917 ObjectPtr const* data() const { OPEN_ARRAY_START(ObjectPtr, ObjectPtr); }
1918 VISIT_TO_LENGTH(ObjectPtr, &data()[length - 1]);
1919
1920 friend class Object;
1921 friend class SnapshotReader;
1922};
1923
1924class ContextScopeLayout : public ObjectLayout {
1925 RAW_HEAP_OBJECT_IMPLEMENTATION(ContextScope);
1926
1927 // TODO(iposva): Switch to conventional enum offset based structure to avoid
1928 // alignment mishaps.
1929 struct VariableDesc {
1930 SmiPtr declaration_token_pos;
1931 SmiPtr token_pos;
1932 StringPtr name;
1933 SmiPtr flags;
1934 static constexpr intptr_t kIsFinal = 0x1;
1935 static constexpr intptr_t kIsConst = 0x2;
1936 static constexpr intptr_t kIsLate = 0x4;
1937 SmiPtr late_init_offset;
1938 union {
1939 AbstractTypePtr type;
1940 InstancePtr value; // iff is_const is true
1941 };
1942 SmiPtr context_index;
1943 SmiPtr context_level;
1944 };
1945
1946 int32_t num_variables_;
1947 bool is_implicit_; // true, if this context scope is for an implicit closure.
1948
1949 ObjectPtr* from() {
1950 VariableDesc* begin = const_cast<VariableDesc*>(VariableDescAddr(0));
1951 return reinterpret_cast<ObjectPtr*>(begin);
1952 }
1953 // Variable length data follows here.
1954 ObjectPtr const* data() const { OPEN_ARRAY_START(ObjectPtr, ObjectPtr); }
1955 const VariableDesc* VariableDescAddr(intptr_t index) const {
1956 ASSERT((index >= 0) && (index < num_variables_ + 1));
1957 // data() points to the first component of the first descriptor.
1958 return &(reinterpret_cast<const VariableDesc*>(data())[index]);
1959 }
1960 ObjectPtr* to(intptr_t num_vars) {
1961 uword end = reinterpret_cast<uword>(VariableDescAddr(num_vars));
1962 // 'end' is the address just beyond the last descriptor, so step back.
1963 return reinterpret_cast<ObjectPtr*>(end - kWordSize);
1964 }
1965 ObjectPtr* to_snapshot(Snapshot::Kind kind, intptr_t num_vars) {
1966 return to(num_vars);
1967 }
1968
1969 friend class Object;
1970 friend class ClosureDataLayout;
1971 friend class SnapshotReader;
1972};
1973
1974class ParameterTypeCheckLayout : public ObjectLayout {
1975 RAW_HEAP_OBJECT_IMPLEMENTATION(ParameterTypeCheck);
1976 intptr_t index_;
1977 VISIT_FROM(ObjectPtr, param_);
1978 AbstractTypePtr param_;
1979 AbstractTypePtr type_or_bound_;
1980 StringPtr name_;
1981 SubtypeTestCachePtr cache_;
1982 VISIT_TO(ObjectPtr, cache_);
1983 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
1984};
1985
1986class SingleTargetCacheLayout : public ObjectLayout {
1987 RAW_HEAP_OBJECT_IMPLEMENTATION(SingleTargetCache);
1988 VISIT_FROM(ObjectPtr, target_);
1989 CodePtr target_;
1990 VISIT_TO(ObjectPtr, target_);
1991 uword entry_point_;
1992 ClassIdTagType lower_limit_;
1993 ClassIdTagType upper_limit_;
1994};
1995
1996class MonomorphicSmiableCallLayout : public ObjectLayout {
1997 RAW_HEAP_OBJECT_IMPLEMENTATION(MonomorphicSmiableCall);
1998 VISIT_FROM(ObjectPtr, target_);
1999 CodePtr target_; // Entrypoint PC in bare mode, Code in non-bare mode.
2000 VISIT_TO(ObjectPtr, target_);
2001 uword expected_cid_;
2002 uword entrypoint_;
2003 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2004};
2005
2006// Abstract base class for RawICData/RawMegamorphicCache
2007class CallSiteDataLayout : public ObjectLayout {
2008 protected:
2009 StringPtr target_name_; // Name of target function.
2010 // arg_descriptor in RawICData and in RawMegamorphicCache should be
2011 // in the same position so that NoSuchMethod can access it.
2012 ArrayPtr args_descriptor_; // Arguments descriptor.
2013 private:
2014 RAW_HEAP_OBJECT_IMPLEMENTATION(CallSiteData)
2015};
2016
2017class UnlinkedCallLayout : public CallSiteDataLayout {
2018 RAW_HEAP_OBJECT_IMPLEMENTATION(UnlinkedCall);
2019 VISIT_FROM(ObjectPtr, target_name_);
2020 VISIT_TO(ObjectPtr, args_descriptor_);
2021 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2022
2023 bool can_patch_to_monomorphic_;
2024};
2025
2026class ICDataLayout : public CallSiteDataLayout {
2027 RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
2028 VISIT_FROM(ObjectPtr, target_name_);
2029 ArrayPtr entries_; // Contains class-ids, target and count.
2030 // Static type of the receiver, if instance call and available.
2031 NOT_IN_PRECOMPILED(AbstractTypePtr receivers_static_type_);
2032 ObjectPtr owner_; // Parent/calling function or original IC of cloned IC.
2033 VISIT_TO(ObjectPtr, owner_);
2034 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
2035 switch (kind) {
2036 case Snapshot::kFullAOT:
2037 return reinterpret_cast<ObjectPtr*>(&entries_);
2038 case Snapshot::kFull:
2039 case Snapshot::kFullJIT:
2040 return to();
2041 case Snapshot::kMessage:
2042 case Snapshot::kNone:
2043 case Snapshot::kInvalid:
2044 break;
2045 }
2046 UNREACHABLE();
2047 return NULL;
2048 }
2049 NOT_IN_PRECOMPILED(int32_t deopt_id_);
2050 uint32_t state_bits_; // Number of arguments tested in IC, deopt reasons.
2051};
2052
2053class MegamorphicCacheLayout : public CallSiteDataLayout {
2054 RAW_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache);
2055 VISIT_FROM(ObjectPtr, target_name_)
2056 ArrayPtr buckets_;
2057 SmiPtr mask_;
2058 VISIT_TO(ObjectPtr, mask_)
2059 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2060
2061 int32_t filled_entry_count_;
2062};
2063
2064class SubtypeTestCacheLayout : public ObjectLayout {
2065 RAW_HEAP_OBJECT_IMPLEMENTATION(SubtypeTestCache);
2066 VISIT_FROM(ObjectPtr, cache_);
2067 ArrayPtr cache_;
2068 VISIT_TO(ObjectPtr, cache_);
2069};
2070
2071class LoadingUnitLayout : public ObjectLayout {
2072 RAW_HEAP_OBJECT_IMPLEMENTATION(LoadingUnit);
2073 VISIT_FROM(ObjectPtr, parent_);
2074 LoadingUnitPtr parent_;
2075 ArrayPtr base_objects_;
2076 VISIT_TO(ObjectPtr, base_objects_);
2077 int32_t id_;
2078 bool load_outstanding_;
2079 bool loaded_;
2080};
2081
2082class ErrorLayout : public ObjectLayout {
2083 RAW_HEAP_OBJECT_IMPLEMENTATION(Error);
2084};
2085
2086class ApiErrorLayout : public ErrorLayout {
2087 RAW_HEAP_OBJECT_IMPLEMENTATION(ApiError);
2088
2089 VISIT_FROM(ObjectPtr, message_)
2090 StringPtr message_;
2091 VISIT_TO(ObjectPtr, message_)
2092};
2093
2094class LanguageErrorLayout : public ErrorLayout {
2095 RAW_HEAP_OBJECT_IMPLEMENTATION(LanguageError);
2096
2097 VISIT_FROM(ObjectPtr, previous_error_)
2098 ErrorPtr previous_error_; // May be null.
2099 ScriptPtr script_;
2100 StringPtr message_;
2101 StringPtr formatted_message_; // Incl. previous error's formatted message.
2102 VISIT_TO(ObjectPtr, formatted_message_)
2103 TokenPosition token_pos_; // Source position in script_.
2104 bool report_after_token_; // Report message at or after the token.
2105 int8_t kind_; // Of type Report::Kind.
2106
2107 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2108};
2109
2110class UnhandledExceptionLayout : public ErrorLayout {
2111 RAW_HEAP_OBJECT_IMPLEMENTATION(UnhandledException);
2112
2113 VISIT_FROM(ObjectPtr, exception_)
2114 InstancePtr exception_;
2115 InstancePtr stacktrace_;
2116 VISIT_TO(ObjectPtr, stacktrace_)
2117 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2118};
2119
2120class UnwindErrorLayout : public ErrorLayout {
2121 RAW_HEAP_OBJECT_IMPLEMENTATION(UnwindError);
2122
2123 VISIT_FROM(ObjectPtr, message_)
2124 StringPtr message_;
2125 VISIT_TO(ObjectPtr, message_)
2126 bool is_user_initiated_;
2127};
2128
2129class InstanceLayout : public ObjectLayout {
2130 RAW_HEAP_OBJECT_IMPLEMENTATION(Instance);
2131};
2132
2133class LibraryPrefixLayout : public InstanceLayout {
2134 RAW_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix);
2135
2136 VISIT_FROM(ObjectPtr, name_)
2137 StringPtr name_; // Library prefix name.
2138 LibraryPtr importer_; // Library which declares this prefix.
2139 ArrayPtr imports_; // Libraries imported with this prefix.
2140 VISIT_TO(ObjectPtr, imports_)
2141 ObjectPtr* to_snapshot(Snapshot::Kind kind) {
2142 switch (kind) {
2143 case Snapshot::kFull:
2144 case Snapshot::kFullJIT:
2145 case Snapshot::kFullAOT:
2146 return reinterpret_cast<ObjectPtr*>(&imports_);
2147 case Snapshot::kMessage:
2148 case Snapshot::kNone:
2149 case Snapshot::kInvalid:
2150 break;
2151 }
2152 UNREACHABLE();
2153 return NULL;
2154 }
2155 uint16_t num_imports_; // Number of library entries in libraries_.
2156 bool is_deferred_load_;
2157 bool is_loaded_;
2158};
2159
2160class TypeArgumentsLayout : public InstanceLayout {
2161 private:
2162 RAW_HEAP_OBJECT_IMPLEMENTATION(TypeArguments);
2163
2164 VISIT_FROM(ObjectPtr, instantiations_)
2165 // The instantiations_ array remains empty for instantiated type arguments.
2166 ArrayPtr instantiations_; // Of 3-tuple: 2 instantiators, result.
2167 SmiPtr length_;
2168 SmiPtr hash_;
2169 SmiPtr nullability_;
2170
2171 // Variable length data follows here.
2172 AbstractTypePtr const* types() const {
2173 OPEN_ARRAY_START(AbstractTypePtr, AbstractTypePtr);
2174 }
2175 AbstractTypePtr* types() {
2176 OPEN_ARRAY_START(AbstractTypePtr, AbstractTypePtr);
2177 }
2178 ObjectPtr* to(intptr_t length) {
2179 return reinterpret_cast<ObjectPtr*>(&types()[length - 1]);
2180 }
2181
2182 friend class Object;
2183 friend class SnapshotReader;
2184};
2185
2186class AbstractTypeLayout : public InstanceLayout {
2187 public:
2188 enum TypeState {
2189 kAllocated, // Initial state.
2190 kBeingFinalized, // In the process of being finalized.
2191 kFinalizedInstantiated, // Instantiated type ready for use.
2192 kFinalizedUninstantiated, // Uninstantiated type ready for use.
2193 // Adjust kTypeStateBitSize if more are added.
2194 };
2195
2196 protected:
2197 static constexpr intptr_t kTypeStateBitSize = 2;
2198
2199 uword type_test_stub_entry_point_; // Accessed from generated code.
2200 CodePtr type_test_stub_; // Must be the last field, since subclasses use it
2201 // in their VISIT_FROM.
2202
2203 private:
2204 RAW_HEAP_OBJECT_IMPLEMENTATION(AbstractType);
2205
2206 friend class ObjectStore;
2207 friend class StubCode;
2208};
2209
2210class TypeLayout : public AbstractTypeLayout {
2211 private:
2212 RAW_HEAP_OBJECT_IMPLEMENTATION(Type);
2213
2214 VISIT_FROM(ObjectPtr, type_test_stub_)
2215 SmiPtr type_class_id_;
2216 TypeArgumentsPtr arguments_;
2217 SmiPtr hash_;
2218 // This type object represents a function type if its signature field is a
2219 // non-null function object.
2220 FunctionPtr signature_; // If not null, this type is a function type.
2221 VISIT_TO(ObjectPtr, signature_)
2222 TokenPosition token_pos_;
2223 int8_t type_state_;
2224 int8_t nullability_;
2225
2226 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2227
2228 friend class CidRewriteVisitor;
2229 friend class TypeArgumentsLayout;
2230};
2231
2232class TypeRefLayout : public AbstractTypeLayout {
2233 private:
2234 RAW_HEAP_OBJECT_IMPLEMENTATION(TypeRef);
2235
2236 VISIT_FROM(ObjectPtr, type_test_stub_)
2237 AbstractTypePtr type_; // The referenced type.
2238 VISIT_TO(ObjectPtr, type_)
2239 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2240};
2241
2242class TypeParameterLayout : public AbstractTypeLayout {
2243 private:
2244 RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameter);
2245
2246 VISIT_FROM(ObjectPtr, type_test_stub_)
2247 StringPtr name_;
2248 SmiPtr hash_;
2249 AbstractTypePtr bound_; // ObjectType if no explicit bound specified.
2250 FunctionPtr parameterized_function_;
2251 VISIT_TO(ObjectPtr, parameterized_function_)
2252 ClassIdTagType parameterized_class_id_;
2253 TokenPosition token_pos_;
2254 int16_t index_;
2255 uint8_t flags_;
2256 int8_t nullability_;
2257
2258 using FinalizedBit = BitField<decltype(flags_), bool, 0, 1>;
2259 using GenericCovariantImplBit =
2260 BitField<decltype(flags_), bool, FinalizedBit::kNextBit, 1>;
2261 using DeclarationBit =
2262 BitField<decltype(flags_), bool, GenericCovariantImplBit::kNextBit, 1>;
2263 static constexpr intptr_t kFlagsBitSize = DeclarationBit::kNextBit;
2264
2265 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2266
2267 friend class CidRewriteVisitor;
2268};
2269
2270class ClosureLayout : public InstanceLayout {
2271 private:
2272 RAW_HEAP_OBJECT_IMPLEMENTATION(Closure);
2273
2274 // No instance fields should be declared before the following fields whose
2275 // offsets must be identical in Dart and C++.
2276
2277 // The following fields are also declared in the Dart source of class
2278 // _Closure.
2279 VISIT_FROM(RawCompressed, instantiator_type_arguments_)
2280 TypeArgumentsPtr instantiator_type_arguments_;
2281 TypeArgumentsPtr function_type_arguments_;
2282 TypeArgumentsPtr delayed_type_arguments_;
2283 FunctionPtr function_;
2284 ContextPtr context_;
2285 SmiPtr hash_;
2286
2287 VISIT_TO(RawCompressed, hash_)
2288
2289 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2290
2291 // Note that instantiator_type_arguments_, function_type_arguments_ and
2292 // delayed_type_arguments_ are used to instantiate the signature of function_
2293 // when this closure is involved in a type test. In other words, these fields
2294 // define the function type of this closure instance.
2295 //
2296 // function_type_arguments_ and delayed_type_arguments_ may also be used when
2297 // invoking the closure. Whereas the source frontend will save a copy of the
2298 // function's type arguments in the closure's context and only use the
2299 // function_type_arguments_ field for type tests, the kernel frontend will use
2300 // the function_type_arguments_ vector here directly.
2301 //
2302 // If this closure is generic, it can be invoked with function type arguments
2303 // that will be processed in the prolog of the closure function_. For example,
2304 // if the generic closure function_ has a generic parent function, the
2305 // passed-in function type arguments get concatenated to the function type
2306 // arguments of the parent that are found in the context_.
2307 //
2308 // delayed_type_arguments_ is used to support the partial instantiation
2309 // feature. When this field is set to any value other than
2310 // Object::empty_type_arguments(), the types in this vector will be passed as
2311 // type arguments to the closure when invoked. In this case there may not be
2312 // any type arguments passed directly (or NSM will be invoked instead).
2313};
2314
2315class NumberLayout : public InstanceLayout {
2316 RAW_OBJECT_IMPLEMENTATION(Number);
2317};
2318
2319class IntegerLayout : public NumberLayout {
2320 RAW_OBJECT_IMPLEMENTATION(Integer);
2321};
2322
2323class SmiLayout : public IntegerLayout {
2324 RAW_OBJECT_IMPLEMENTATION(Smi);
2325};
2326
2327class MintLayout : public IntegerLayout {
2328 RAW_HEAP_OBJECT_IMPLEMENTATION(Mint);
2329 VISIT_NOTHING();
2330
2331 ALIGN8 int64_t value_;
2332
2333 friend class Api;
2334 friend class Class;
2335 friend class Integer;
2336 friend class SnapshotReader;
2337};
2338COMPILE_ASSERT(sizeof(MintLayout) == 16);
2339
2340class DoubleLayout : public NumberLayout {
2341 RAW_HEAP_OBJECT_IMPLEMENTATION(Double);
2342 VISIT_NOTHING();
2343
2344 ALIGN8 double value_;
2345
2346 friend class Api;
2347 friend class SnapshotReader;
2348 friend class Class;
2349};
2350COMPILE_ASSERT(sizeof(DoubleLayout) == 16);
2351
2352class StringLayout : public InstanceLayout {
2353 RAW_HEAP_OBJECT_IMPLEMENTATION(String);
2354
2355 protected:
2356 VISIT_FROM(ObjectPtr, length_)
2357 SmiPtr length_;
2358#if !defined(HASH_IN_OBJECT_HEADER)
2359 SmiPtr hash_;
2360 VISIT_TO(ObjectPtr, hash_)
2361#else
2362 VISIT_TO(ObjectPtr, length_)
2363#endif
2364
2365 private:
2366 friend class Library;
2367 friend class OneByteStringSerializationCluster;
2368 friend class TwoByteStringSerializationCluster;
2369 friend class OneByteStringDeserializationCluster;
2370 friend class TwoByteStringDeserializationCluster;
2371 friend class RODataSerializationCluster;
2372 friend class ImageWriter;
2373};
2374
2375class OneByteStringLayout : public StringLayout {
2376 RAW_HEAP_OBJECT_IMPLEMENTATION(OneByteString);
2377 VISIT_NOTHING();
2378
2379 // Variable length data follows here.
2380 uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
2381 const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
2382
2383 friend class ApiMessageReader;
2384 friend class RODataSerializationCluster;
2385 friend class SnapshotReader;
2386 friend class String;
2387};
2388
2389class TwoByteStringLayout : public StringLayout {
2390 RAW_HEAP_OBJECT_IMPLEMENTATION(TwoByteString);
2391 VISIT_NOTHING();
2392
2393 // Variable length data follows here.
2394 uint16_t* data() { OPEN_ARRAY_START(uint16_t, uint16_t); }
2395 const uint16_t* data() const { OPEN_ARRAY_START(uint16_t, uint16_t); }
2396
2397 friend class RODataSerializationCluster;
2398 friend class SnapshotReader;
2399 friend class String;
2400};
2401
2402// Abstract base class for RawTypedData/RawExternalTypedData/RawTypedDataView/
2403// Pointer.
2404//
2405// TypedData extends this with a length field, while Pointer extends this with
2406// TypeArguments field.
2407class PointerBaseLayout : public InstanceLayout {
2408 protected:
2409 // The contents of [data_] depends on what concrete subclass is used:
2410 //
2411 // - RawTypedData: Start of the payload.
2412 // - RawExternalTypedData: Start of the C-heap payload.
2413 // - RawTypedDataView: The [data_] field of the backing store for the view
2414 // plus the [offset_in_bytes_] the view has.
2415 // - RawPointer: Pointer into C memory (no length specified).
2416 //
2417 // During allocation or snapshot reading the [data_] can be temporarily
2418 // nullptr (which is the case for views which just got created but haven't
2419 // gotten the backing store set).
2420 uint8_t* data_;
2421
2422 private:
2423 RAW_HEAP_OBJECT_IMPLEMENTATION(PointerBase);
2424};
2425
2426// Abstract base class for RawTypedData/RawExternalTypedData/RawTypedDataView.
2427class TypedDataBaseLayout : public PointerBaseLayout {
2428 protected:
2429 // The length of the view in element sizes (obtainable via
2430 // [TypedDataBase::ElementSizeInBytes]).
2431 SmiPtr length_;
2432
2433 private:
2434 friend class TypedDataViewLayout;
2435 RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataBase);
2436};
2437
2438class TypedDataLayout : public TypedDataBaseLayout {
2439 RAW_HEAP_OBJECT_IMPLEMENTATION(TypedData);
2440
2441 public:
2442 static intptr_t payload_offset() {
2443 return OFFSET_OF_RETURNED_VALUE(TypedDataLayout, internal_data);
2444 }
2445
2446 // Recompute [data_] pointer to internal data.
2447 void RecomputeDataField() { data_ = internal_data(); }
2448
2449 protected:
2450 VISIT_FROM(RawCompressed, length_)
2451 VISIT_TO_LENGTH(RawCompressed, &length_)
2452
2453 // Variable length data follows here.
2454
2455 uint8_t* internal_data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
2456 const uint8_t* internal_data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
2457
2458 uint8_t* data() {
2459 ASSERT(data_ == internal_data());
2460 return data_;
2461 }
2462 const uint8_t* data() const {
2463 ASSERT(data_ == internal_data());
2464 return data_;
2465 }
2466
2467 friend class Api;
2468 friend class Instance;
2469 friend class NativeEntryData;
2470 friend class Object;
2471 friend class ObjectPool;
2472 friend class ObjectPoolDeserializationCluster;
2473 friend class ObjectPoolSerializationCluster;
2474 friend class ObjectPoolLayout;
2475 friend class SnapshotReader;
2476};
2477
2478// All _*ArrayView/_ByteDataView classes share the same layout.
2479class TypedDataViewLayout : public TypedDataBaseLayout {
2480 RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataView);
2481
2482 public:
2483 // Recompute [data_] based on internal/external [typed_data_].
2484 void RecomputeDataField() {
2485 const intptr_t offset_in_bytes = RawSmiValue(offset_in_bytes_);
2486 uint8_t* payload = typed_data_->ptr()->data_;
2487 data_ = payload + offset_in_bytes;
2488 }
2489
2490 // Recopute [data_] based on internal [typed_data_] - needs to be called by GC
2491 // whenever the backing store moved.
2492 //
2493 // NOTICE: This method assumes [this] is the forwarded object and the
2494 // [typed_data_] pointer points to the new backing store. The backing store's
2495 // fields don't need to be valid - only it's address.
2496 void RecomputeDataFieldForInternalTypedData() {
2497 const intptr_t offset_in_bytes = RawSmiValue(offset_in_bytes_);
2498 uint8_t* payload = reinterpret_cast<uint8_t*>(
2499 ObjectLayout::ToAddr(typed_data_) + TypedDataLayout::payload_offset());
2500 data_ = payload + offset_in_bytes;
2501 }
2502
2503 void ValidateInnerPointer() {
2504 if (typed_data_->ptr()->GetClassId() == kNullCid) {
2505 // The view object must have gotten just initialized.
2506 if (data_ != nullptr || RawSmiValue(offset_in_bytes_) != 0 ||
2507 RawSmiValue(length_) != 0) {
2508 FATAL("RawTypedDataView has invalid inner pointer.");
2509 }
2510 } else {
2511 const intptr_t offset_in_bytes = RawSmiValue(offset_in_bytes_);
2512 uint8_t* payload = typed_data_->ptr()->data_;
2513 if ((payload + offset_in_bytes) != data_) {
2514 FATAL("RawTypedDataView has invalid inner pointer.");
2515 }
2516 }
2517 }
2518
2519 protected:
2520 VISIT_FROM(ObjectPtr, length_)
2521 TypedDataBasePtr typed_data_;
2522 SmiPtr offset_in_bytes_;
2523 VISIT_TO(ObjectPtr, offset_in_bytes_)
2524 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2525
2526 friend class Api;
2527 friend class Object;
2528 friend class ObjectPoolDeserializationCluster;
2529 friend class ObjectPoolSerializationCluster;
2530 friend class ObjectPoolLayout;
2531 friend class GCCompactor;
2532 template <bool>
2533 friend class ScavengerVisitorBase;
2534 friend class SnapshotReader;
2535};
2536
2537class ExternalOneByteStringLayout : public StringLayout {
2538 RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalOneByteString);
2539
2540 const uint8_t* external_data_;
2541 void* peer_;
2542 friend class Api;
2543 friend class String;
2544};
2545
2546class ExternalTwoByteStringLayout : public StringLayout {
2547 RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalTwoByteString);
2548
2549 const uint16_t* external_data_;
2550 void* peer_;
2551 friend class Api;
2552 friend class String;
2553};
2554
2555class BoolLayout : public InstanceLayout {
2556 RAW_HEAP_OBJECT_IMPLEMENTATION(Bool);
2557 VISIT_NOTHING();
2558
2559 bool value_;
2560
2561 friend class Object;
2562};
2563
2564class ArrayLayout : public InstanceLayout {
2565 RAW_HEAP_OBJECT_IMPLEMENTATION(Array);
2566
2567 VISIT_FROM(RawCompressed, type_arguments_)
2568 TypeArgumentsPtr type_arguments_;
2569 SmiPtr length_;
2570 // Variable length data follows here.
2571 ObjectPtr* data() { OPEN_ARRAY_START(ObjectPtr, ObjectPtr); }
2572 ObjectPtr const* data() const { OPEN_ARRAY_START(ObjectPtr, ObjectPtr); }
2573 VISIT_TO_LENGTH(RawCompressed, &data()[length - 1])
2574
2575 friend class LinkedHashMapSerializationCluster;
2576 friend class LinkedHashMapDeserializationCluster;
2577 friend class CodeSerializationCluster;
2578 friend class CodeDeserializationCluster;
2579 friend class Deserializer;
2580 friend class CodeLayout;
2581 friend class ImmutableArrayLayout;
2582 friend class SnapshotReader;
2583 friend class GrowableObjectArray;
2584 friend class LinkedHashMap;
2585 friend class LinkedHashMapLayout;
2586 friend class Object;
2587 friend class ICData; // For high performance access.
2588 friend class SubtypeTestCache; // For high performance access.
2589 friend class ReversePc;
2590
2591 friend class OldPage;
2592};
2593
2594class ImmutableArrayLayout : public ArrayLayout {
2595 RAW_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray);
2596
2597 friend class SnapshotReader;
2598};
2599
2600class GrowableObjectArrayLayout : public InstanceLayout {
2601 RAW_HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray);
2602
2603 VISIT_FROM(RawCompressed, type_arguments_)
2604 TypeArgumentsPtr type_arguments_;
2605 SmiPtr length_;
2606 ArrayPtr data_;
2607 VISIT_TO(RawCompressed, data_)
2608 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2609
2610 friend class SnapshotReader;
2611 friend class ReversePc;
2612};
2613
2614class LinkedHashMapLayout : public InstanceLayout {
2615 RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap);
2616
2617 VISIT_FROM(RawCompressed, type_arguments_)
2618 TypeArgumentsPtr type_arguments_;
2619 TypedDataPtr index_;
2620 SmiPtr hash_mask_;
2621 ArrayPtr data_;
2622 SmiPtr used_data_;
2623 SmiPtr deleted_keys_;
2624 VISIT_TO(RawCompressed, deleted_keys_)
2625
2626 friend class SnapshotReader;
2627};
2628
2629class Float32x4Layout : public InstanceLayout {
2630 RAW_HEAP_OBJECT_IMPLEMENTATION(Float32x4);
2631 VISIT_NOTHING();
2632
2633 ALIGN8 float value_[4];
2634
2635 friend class SnapshotReader;
2636 friend class Class;
2637
2638 public:
2639 float x() const { return value_[0]; }
2640 float y() const { return value_[1]; }
2641 float z() const { return value_[2]; }
2642 float w() const { return value_[3]; }
2643};
2644COMPILE_ASSERT(sizeof(Float32x4Layout) == 24);
2645
2646class Int32x4Layout : public InstanceLayout {
2647 RAW_HEAP_OBJECT_IMPLEMENTATION(Int32x4);
2648 VISIT_NOTHING();
2649
2650 ALIGN8 int32_t value_[4];
2651
2652 friend class SnapshotReader;
2653
2654 public:
2655 int32_t x() const { return value_[0]; }
2656 int32_t y() const { return value_[1]; }
2657 int32_t z() const { return value_[2]; }
2658 int32_t w() const { return value_[3]; }
2659};
2660COMPILE_ASSERT(sizeof(Int32x4Layout) == 24);
2661
2662class Float64x2Layout : public InstanceLayout {
2663 RAW_HEAP_OBJECT_IMPLEMENTATION(Float64x2);
2664 VISIT_NOTHING();
2665
2666 ALIGN8 double value_[2];
2667
2668 friend class SnapshotReader;
2669 friend class Class;
2670
2671 public:
2672 double x() const { return value_[0]; }
2673 double y() const { return value_[1]; }
2674};
2675COMPILE_ASSERT(sizeof(Float64x2Layout) == 24);
2676
2677// Define an aliases for intptr_t.
2678#if defined(ARCH_IS_32_BIT)
2679#define kIntPtrCid kTypedDataInt32ArrayCid
2680#define SetIntPtr SetInt32
2681#elif defined(ARCH_IS_64_BIT)
2682#define kIntPtrCid kTypedDataInt64ArrayCid
2683#define SetIntPtr SetInt64
2684#else
2685#error Architecture is not 32-bit or 64-bit.
2686#endif // ARCH_IS_32_BIT
2687
2688class ExternalTypedDataLayout : public TypedDataBaseLayout {
2689 RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalTypedData);
2690
2691 protected:
2692 VISIT_FROM(RawCompressed, length_)
2693 VISIT_TO(RawCompressed, length_)
2694
2695 friend class BytecodeLayout;
2696};
2697
2698class PointerLayout : public PointerBaseLayout {
2699 RAW_HEAP_OBJECT_IMPLEMENTATION(Pointer);
2700
2701 VISIT_FROM(RawCompressed, type_arguments_)
2702 TypeArgumentsPtr type_arguments_;
2703 VISIT_TO(RawCompressed, type_arguments_)
2704
2705 friend class Pointer;
2706};
2707
2708class DynamicLibraryLayout : public InstanceLayout {
2709 RAW_HEAP_OBJECT_IMPLEMENTATION(DynamicLibrary);
2710 VISIT_NOTHING();
2711 void* handle_;
2712
2713 friend class DynamicLibrary;
2714};
2715
2716// VM implementations of the basic types in the isolate.
2717class alignas(8) CapabilityLayout : public InstanceLayout {
2718 RAW_HEAP_OBJECT_IMPLEMENTATION(Capability);
2719 VISIT_NOTHING();
2720 uint64_t id_;
2721};
2722
2723class alignas(8) SendPortLayout : public InstanceLayout {
2724 RAW_HEAP_OBJECT_IMPLEMENTATION(SendPort);
2725 VISIT_NOTHING();
2726 Dart_Port id_;
2727 Dart_Port origin_id_;
2728
2729 friend class ReceivePort;
2730};
2731
2732class ReceivePortLayout : public InstanceLayout {
2733 RAW_HEAP_OBJECT_IMPLEMENTATION(ReceivePort);
2734
2735 VISIT_FROM(ObjectPtr, send_port_)
2736 SendPortPtr send_port_;
2737 InstancePtr handler_;
2738 VISIT_TO(ObjectPtr, handler_)
2739};
2740
2741class TransferableTypedDataLayout : public InstanceLayout {
2742 RAW_HEAP_OBJECT_IMPLEMENTATION(TransferableTypedData);
2743 VISIT_NOTHING();
2744};
2745
2746// VM type for capturing stacktraces when exceptions are thrown,
2747// Currently we don't have any interface that this object is supposed
2748// to implement so we just support the 'toString' method which
2749// converts the stack trace into a string.
2750class StackTraceLayout : public InstanceLayout {
2751 RAW_HEAP_OBJECT_IMPLEMENTATION(StackTrace);
2752
2753 VISIT_FROM(ObjectPtr, async_link_)
2754 StackTracePtr async_link_; // Link to parent async stack trace.
2755 ArrayPtr code_array_; // Code object for each frame in the stack trace.
2756 ArrayPtr pc_offset_array_; // Offset of PC for each frame.
2757 VISIT_TO(ObjectPtr, pc_offset_array_)
2758 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2759
2760 // False for pre-allocated stack trace (used in OOM and Stack overflow).
2761 bool expand_inlined_;
2762 // Whether the link between the stack and the async-link represents a
2763 // synchronous start to an asynchronous function. In this case, we omit the
2764 // <asynchronous suspension> marker when concatenating the stacks.
2765 bool skip_sync_start_in_parent_stack;
2766};
2767
2768// VM type for capturing JS regular expressions.
2769class RegExpLayout : public InstanceLayout {
2770 RAW_HEAP_OBJECT_IMPLEMENTATION(RegExp);
2771
2772 VISIT_FROM(ObjectPtr, num_bracket_expressions_)
2773 SmiPtr num_bracket_expressions_;
2774 ArrayPtr capture_name_map_;
2775 StringPtr pattern_; // Pattern to be used for matching.
2776 union {
2777 FunctionPtr function_;
2778 TypedDataPtr bytecode_;
2779 } one_byte_;
2780 union {
2781 FunctionPtr function_;
2782 TypedDataPtr bytecode_;
2783 } two_byte_;
2784 FunctionPtr external_one_byte_function_;
2785 FunctionPtr external_two_byte_function_;
2786 union {
2787 FunctionPtr function_;
2788 TypedDataPtr bytecode_;
2789 } one_byte_sticky_;
2790 union {
2791 FunctionPtr function_;
2792 TypedDataPtr bytecode_;
2793 } two_byte_sticky_;
2794 FunctionPtr external_one_byte_sticky_function_;
2795 FunctionPtr external_two_byte_sticky_function_;
2796 VISIT_TO(ObjectPtr, external_two_byte_sticky_function_)
2797 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2798
2799 // The same pattern may use different amount of registers if compiled
2800 // for a one-byte target than a two-byte target. For example, we do not
2801 // need to allocate registers to check whether the current position is within
2802 // a surrogate pair when matching a Unicode pattern against a one-byte string.
2803 intptr_t num_one_byte_registers_;
2804 intptr_t num_two_byte_registers_;
2805
2806 // A bitfield with two fields:
2807 // type: Uninitialized, simple or complex.
2808 // flags: Represents global/local, case insensitive, multiline, unicode,
2809 // dotAll.
2810 int8_t type_flags_;
2811};
2812
2813class WeakPropertyLayout : public InstanceLayout {
2814 RAW_HEAP_OBJECT_IMPLEMENTATION(WeakProperty);
2815
2816 VISIT_FROM(ObjectPtr, key_)
2817 ObjectPtr key_;
2818 ObjectPtr value_;
2819 VISIT_TO(ObjectPtr, value_)
2820 ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
2821
2822 // Linked list is chaining all pending weak properties.
2823 // Untyped to make it clear that it is not to be visited by GC.
2824 uword next_;
2825
2826 friend class GCMarker;
2827 template <bool>
2828 friend class MarkingVisitorBase;
2829 friend class Scavenger;
2830 template <bool>
2831 friend class ScavengerVisitorBase;
2832};
2833
2834// MirrorReferences are used by mirrors to hold reflectees that are VM
2835// internal objects, such as libraries, classes, functions or types.
2836class MirrorReferenceLayout : public InstanceLayout {
2837 RAW_HEAP_OBJECT_IMPLEMENTATION(MirrorReference);
2838
2839 VISIT_FROM(ObjectPtr, referent_)
2840 ObjectPtr referent_;
2841 VISIT_TO(ObjectPtr, referent_)
2842};
2843
2844// UserTag are used by the profiler to track Dart script state.
2845class UserTagLayout : public InstanceLayout {
2846 RAW_HEAP_OBJECT_IMPLEMENTATION(UserTag);
2847
2848 VISIT_FROM(ObjectPtr, label_)
2849 StringPtr label_;
2850 VISIT_TO(ObjectPtr, label_)
2851
2852 // Isolate unique tag.
2853 uword tag_;
2854
2855 friend class SnapshotReader;
2856 friend class Object;
2857
2858 public:
2859 uword tag() const { return tag_; }
2860};
2861
2862class FutureOrLayout : public InstanceLayout {
2863 RAW_HEAP_OBJECT_IMPLEMENTATION(FutureOr);
2864
2865 VISIT_FROM(RawCompressed, type_arguments_)
2866 TypeArgumentsPtr type_arguments_;
2867 VISIT_TO(RawCompressed, type_arguments_)
2868
2869 friend class SnapshotReader;
2870};
2871
2872} // namespace dart
2873
2874#endif // RUNTIME_VM_RAW_OBJECT_H_
2875