Flutter Engine
The Flutter Engine
raw_object.cc
Go to the documentation of this file.
1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/raw_object.h"
6
7#include "vm/class_table.h"
8#include "vm/dart.h"
9#include "vm/heap/become.h"
10#include "vm/heap/freelist.h"
11#include "vm/isolate.h"
12#include "vm/isolate_reload.h"
13#include "vm/object.h"
14#include "vm/runtime_entry.h"
15#include "vm/stack_frame.h"
16#include "vm/visitor.h"
17
18namespace dart {
19
21 // All "vm-isolate" objects are pre-marked and in old space
22 // (see [Object::FinalizeVMIsolate]).
23 if (!IsOldObject() || !IsMarked()) return false;
24
25 auto heap = Dart::vm_isolate_group()->heap();
26 ASSERT(heap->UsedInWords(Heap::kNew) == 0);
27 return heap->old_space()->ContainsUnsafe(ToAddr(this));
28}
29
30void ObjectPtr::Validate(IsolateGroup* isolate_group) const {
31 // All Smi values are valid.
32 if (!IsHeapObject()) {
33 return;
34 }
35 // Slightly more readable than a segfault.
37 FATAL("RAW_NULL encountered");
38 }
39 untag()->Validate(isolate_group);
40}
41
42void UntaggedObject::Validate(IsolateGroup* isolate_group) const {
43 if (static_cast<uword>(Object::void_class_) == kHeapObjectTag) {
44 // Validation relies on properly initialized class classes. Skip if the
45 // VM is still being initialized.
46 return;
47 }
48 // Validate that the tags_ field is sensible.
49 uword tags = tags_;
50 if (IsNewObject()) {
52 FATAL("New object missing kNewBit: %" Px "\n", tags);
53 }
55 FATAL("New object has kOldAndNotRememberedBit: %" Px "\n", tags);
56 }
57 }
58 const intptr_t class_id = ClassIdTag::decode(tags);
59 if (!isolate_group->class_table()->IsValidIndex(class_id)) {
60 FATAL("Invalid class id encountered %" Pd "\n", class_id);
61 }
62 if (class_id == kNullCid &&
63 isolate_group->class_table()->HasValidClassAt(class_id)) {
64 // Null class not yet initialized; skip.
65 return;
66 }
67 intptr_t size_from_tags = SizeTag::decode(tags);
68 intptr_t size_from_class = HeapSizeFromClass(tags);
69 if ((size_from_tags != 0) && (size_from_tags != size_from_class)) {
70 FATAL(
71 "Inconsistent size encountered "
72 "cid: %" Pd ", size_from_tags: %" Pd ", size_from_class: %" Pd "\n",
73 class_id, size_from_tags, size_from_class);
74 }
75}
76
77// Can't look at the class object because it can be called during
78// compaction when the class objects are moving. Can use the class
79// id in the header and the sizes in the Class Table.
80// Cannot deference ptr()->tags_. May dereference other parts of the object.
81intptr_t UntaggedObject::HeapSizeFromClass(uword tags) const {
82 intptr_t class_id = ClassIdTag::decode(tags);
83 intptr_t instance_size = 0;
84 switch (class_id) {
85 case kCodeCid: {
86 const CodePtr raw_code = static_cast<const CodePtr>(this);
87 intptr_t pointer_offsets_length =
88 Code::PtrOffBits::decode(raw_code->untag()->state_bits_);
89 instance_size = Code::InstanceSize(pointer_offsets_length);
90 break;
91 }
92 case kInstructionsCid: {
93 const InstructionsPtr raw_instructions =
94 static_cast<const InstructionsPtr>(this);
95 intptr_t instructions_size = Instructions::Size(raw_instructions);
96 instance_size = Instructions::InstanceSize(instructions_size);
97 break;
98 }
99 case kInstructionsSectionCid: {
100 const InstructionsSectionPtr raw_section =
101 static_cast<const InstructionsSectionPtr>(this);
102 intptr_t section_size = InstructionsSection::Size(raw_section);
103 instance_size = InstructionsSection::InstanceSize(section_size);
104 break;
105 }
106 case kContextCid: {
107 const ContextPtr raw_context = static_cast<const ContextPtr>(this);
108 intptr_t num_variables = raw_context->untag()->num_variables_;
109 instance_size = Context::InstanceSize(num_variables);
110 break;
111 }
112 case kContextScopeCid: {
113 const ContextScopePtr raw_context_scope =
114 static_cast<const ContextScopePtr>(this);
115 intptr_t num_variables = raw_context_scope->untag()->num_variables_;
116 instance_size = ContextScope::InstanceSize(num_variables);
117 break;
118 }
119 case kOneByteStringCid: {
120 const OneByteStringPtr raw_string =
121 static_cast<const OneByteStringPtr>(this);
122 intptr_t string_length = Smi::Value(raw_string->untag()->length());
123 instance_size = OneByteString::InstanceSize(string_length);
124 break;
125 }
126 case kTwoByteStringCid: {
127 const TwoByteStringPtr raw_string =
128 static_cast<const TwoByteStringPtr>(this);
129 intptr_t string_length = Smi::Value(raw_string->untag()->length());
130 instance_size = TwoByteString::InstanceSize(string_length);
131 break;
132 }
133 case kArrayCid:
134 case kImmutableArrayCid: {
135 const ArrayPtr raw_array = static_cast<const ArrayPtr>(this);
136 intptr_t array_length =
137 Smi::Value(raw_array->untag()->length<std::memory_order_acquire>());
138 instance_size = Array::InstanceSize(array_length);
139 break;
140 }
141 case kWeakArrayCid: {
142 const WeakArrayPtr raw_array = static_cast<const WeakArrayPtr>(this);
143 intptr_t array_length = Smi::Value(raw_array->untag()->length());
144 instance_size = WeakArray::InstanceSize(array_length);
145 break;
146 }
147 case kObjectPoolCid: {
148 const ObjectPoolPtr raw_object_pool =
149 static_cast<const ObjectPoolPtr>(this);
150 intptr_t len = raw_object_pool->untag()->length_;
151 instance_size = ObjectPool::InstanceSize(len);
152 break;
153 }
154 case kRecordCid: {
155 const RecordPtr raw_record = static_cast<const RecordPtr>(this);
156 intptr_t num_fields =
157 RecordShape(raw_record->untag()->shape()).num_fields();
158 instance_size = Record::InstanceSize(num_fields);
159 break;
160 }
161#define SIZE_FROM_CLASS(clazz) case kTypedData##clazz##Cid:
163 const TypedDataPtr raw_obj = static_cast<const TypedDataPtr>(this);
164 intptr_t array_len = Smi::Value(raw_obj->untag()->length());
165 intptr_t lengthInBytes =
166 array_len * TypedData::ElementSizeInBytes(class_id);
167 instance_size = TypedData::InstanceSize(lengthInBytes);
168 break;
169 }
170#undef SIZE_FROM_CLASS
171 case kPointerCid:
172 instance_size = Pointer::InstanceSize();
173 break;
174 case kSuspendStateCid: {
175 const SuspendStatePtr raw_suspend_state =
176 static_cast<const SuspendStatePtr>(this);
177 intptr_t frame_capacity = raw_suspend_state->untag()->frame_capacity();
178 instance_size = SuspendState::InstanceSize(frame_capacity);
179 break;
180 }
181 case kTypeArgumentsCid: {
182 const TypeArgumentsPtr raw_array =
183 static_cast<const TypeArgumentsPtr>(this);
184 intptr_t array_length = Smi::Value(raw_array->untag()->length());
185 instance_size = TypeArguments::InstanceSize(array_length);
186 break;
187 }
188 case kPcDescriptorsCid: {
189 const PcDescriptorsPtr raw_descriptors =
190 static_cast<const PcDescriptorsPtr>(this);
191 intptr_t length = raw_descriptors->untag()->length_;
192 instance_size = PcDescriptors::InstanceSize(length);
193 break;
194 }
195 case kCodeSourceMapCid: {
196 const CodeSourceMapPtr raw_code_source_map =
197 static_cast<const CodeSourceMapPtr>(this);
198 intptr_t length = raw_code_source_map->untag()->length_;
199 instance_size = CodeSourceMap::InstanceSize(length);
200 break;
201 }
202 case kCompressedStackMapsCid: {
203 const CompressedStackMapsPtr maps =
204 static_cast<const CompressedStackMapsPtr>(this);
207 break;
208 }
209 case kLocalVarDescriptorsCid: {
210 const LocalVarDescriptorsPtr raw_descriptors =
211 static_cast<const LocalVarDescriptorsPtr>(this);
212 intptr_t num_descriptors = raw_descriptors->untag()->num_entries_;
213 instance_size = LocalVarDescriptors::InstanceSize(num_descriptors);
214 break;
215 }
216 case kExceptionHandlersCid: {
217 const ExceptionHandlersPtr raw_handlers =
218 static_cast<const ExceptionHandlersPtr>(this);
219 intptr_t num_handlers = raw_handlers->untag()->num_entries();
220 instance_size = ExceptionHandlers::InstanceSize(num_handlers);
221 break;
222 }
223 case kFreeListElement: {
225 FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
226 instance_size = element->HeapSize(tags);
227 break;
228 }
229 case kForwardingCorpse: {
231 ForwardingCorpse* element = reinterpret_cast<ForwardingCorpse*>(addr);
232 instance_size = element->HeapSize(tags);
233 break;
234 }
235 case kWeakSerializationReferenceCid: {
237 break;
238 }
239 default: {
240 // Get the (constant) instance size out of the class object.
241 // TODO(koda): Add Size(ClassTable*) interface to allow caching in loops.
242 auto isolate_group = IsolateGroup::Current();
243#if defined(DEBUG)
244 auto class_table = isolate_group->heap_walk_class_table();
245 if (!class_table->IsValidIndex(class_id) ||
246 !class_table->HasValidClassAt(class_id)) {
247 FATAL("Invalid cid: %" Pd ", obj: %p, tags: %x. Corrupt heap?",
248 class_id, this, static_cast<uint32_t>(tags));
249 }
250 ASSERT(class_table->SizeAt(class_id) > 0);
251#endif // DEBUG
252 instance_size = isolate_group->heap_walk_class_table()->SizeAt(class_id);
253 }
254 }
255 ASSERT(instance_size != 0);
256#if defined(DEBUG)
257 intptr_t tags_size = SizeTag::decode(tags);
258 if ((class_id == kArrayCid) && (instance_size > tags_size && tags_size > 0)) {
259 // TODO(22501): Array::MakeFixedLength could be in the process of shrinking
260 // the array (see comment therein), having already updated the tags but not
261 // yet set the new length. Wait a millisecond and try again.
262 int retries_remaining = 1000; // ... but not forever.
263 do {
264 OS::Sleep(1);
265 const ArrayPtr raw_array = static_cast<const ArrayPtr>(this);
266 intptr_t array_length = Smi::Value(raw_array->untag()->length());
267 instance_size = Array::InstanceSize(array_length);
268 } while ((instance_size > tags_size) && (--retries_remaining > 0));
269 }
270 if ((instance_size != tags_size) && (tags_size != 0)) {
271 FATAL("Size mismatch: %" Pd " from class vs %" Pd " from tags %" Px "\n",
272 instance_size, tags_size, tags);
273 }
274#endif // DEBUG
275 return instance_size;
276}
277
278intptr_t UntaggedObject::VisitPointersPredefined(ObjectPointerVisitor* visitor,
279 intptr_t class_id) {
280 ASSERT(class_id < kNumPredefinedCids);
281
282 intptr_t size = 0;
283
284 switch (class_id) {
285#define RAW_VISITPOINTERS(clazz) \
286 case k##clazz##Cid: { \
287 clazz##Ptr raw_obj = static_cast<clazz##Ptr>(this); \
288 size = Untagged##clazz::Visit##clazz##Pointers(raw_obj, visitor); \
289 break; \
290 }
292#undef RAW_VISITPOINTERS
293#define RAW_VISITPOINTERS(clazz) case kTypedData##clazz##Cid:
295 TypedDataPtr raw_obj = static_cast<TypedDataPtr>(this);
296 size = UntaggedTypedData::VisitTypedDataPointers(raw_obj, visitor);
297 break;
298 }
299#undef RAW_VISITPOINTERS
300#define RAW_VISITPOINTERS(clazz) case kExternalTypedData##clazz##Cid:
302 auto raw_obj = static_cast<ExternalTypedDataPtr>(this);
303 size = UntaggedExternalTypedData::VisitExternalTypedDataPointers(raw_obj,
304 visitor);
305 break;
306 }
307#undef RAW_VISITPOINTERS
308 case kByteDataViewCid:
310#define RAW_VISITPOINTERS(clazz) \
311 case kTypedData##clazz##ViewCid: \
312 case kUnmodifiableTypedData##clazz##ViewCid:
314 auto raw_obj = static_cast<TypedDataViewPtr>(this);
315 size =
316 UntaggedTypedDataView::VisitTypedDataViewPointers(raw_obj, visitor);
317 break;
318 }
319#undef RAW_VISITPOINTERS
320 case kByteBufferCid: {
321 InstancePtr raw_obj = static_cast<InstancePtr>(this);
322 size = UntaggedInstance::VisitInstancePointers(raw_obj, visitor);
323 break;
324 }
325#define RAW_VISITPOINTERS(clazz) case kFfi##clazz##Cid:
327 // NativeType do not have any fields or type arguments.
328 size = HeapSize();
329 break;
330 }
331#undef RAW_VISITPOINTERS
332 case kFreeListElement: {
334 FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
335 size = element->HeapSize();
336 break;
337 }
338 case kForwardingCorpse: {
340 ForwardingCorpse* forwarder = reinterpret_cast<ForwardingCorpse*>(addr);
341 size = forwarder->HeapSize();
342 break;
343 }
344 case kNullCid:
345 case kNeverCid:
346 size = HeapSize();
347 break;
348 default:
349 FATAL("Invalid cid: %" Pd ", obj: %p, tags: %x. Corrupt heap?", class_id,
350 this, static_cast<uint32_t>(tags_));
351 break;
352 }
353
354#if defined(DEBUG)
355 ASSERT(size != 0);
356 const intptr_t expected_size = HeapSize();
357
358 // In general we expect that visitors return exactly the same size that
359 // HeapSize would compute. However in case of Arrays we might have a
360 // discrepancy when concurrently visiting an array that is being shrunk with
361 // Array::MakeFixedLength: the visitor might have visited the full array while
362 // here we are observing a smaller HeapSize().
363 ASSERT(size == expected_size ||
364 (class_id == kArrayCid && size > expected_size));
365 return size; // Prefer larger size.
366#else
367 return size;
368#endif
369}
370
372 intptr_t class_id = GetClassId();
373 if ((class_id != kInstanceCid) && (class_id < kNumPredefinedCids)) {
374 VisitPointersPredefined(visitor, class_id);
375 return;
376 }
377
378 // N.B.: Not using the heap size!
379 uword next_field_offset = visitor->class_table()
380 ->At(class_id)
381 ->untag()
382 ->host_next_field_offset_in_words_
384 ASSERT(next_field_offset > 0);
385 uword obj_addr = UntaggedObject::ToAddr(this);
386 uword from = obj_addr + sizeof(UntaggedObject);
387 uword to = obj_addr + next_field_offset - kCompressedWordSize;
388 const auto first = reinterpret_cast<CompressedObjectPtr*>(from);
389 const auto last = reinterpret_cast<CompressedObjectPtr*>(to);
390
391 const auto unboxed_fields_bitmap =
392 visitor->class_table()->GetUnboxedFieldsMapAt(class_id);
393
394 if (!unboxed_fields_bitmap.IsEmpty()) {
395 intptr_t bit = sizeof(UntaggedObject) / kCompressedWordSize;
396 for (CompressedObjectPtr* current = first; current <= last; current++) {
397 if (!unboxed_fields_bitmap.Get(bit++)) {
398 visitor->VisitCompressedPointers(heap_base(), current, current);
399 }
400 }
401 } else {
402 visitor->VisitCompressedPointers(heap_base(), first, last);
403 }
404}
405
406// Most objects are visited with this function. It calls the from() and to()
407// methods on the raw object to get the first and last cells that need
408// visiting.
409#define REGULAR_VISITOR(Type) \
410 intptr_t Untagged##Type::Visit##Type##Pointers( \
411 Type##Ptr raw_obj, ObjectPointerVisitor* visitor) { \
412 /* Make sure that we got here with the tagged pointer as this. */ \
413 ASSERT(raw_obj->IsHeapObject()); \
414 ASSERT_UNCOMPRESSED(Type); \
415 visitor->VisitPointers(raw_obj->untag()->from(), raw_obj->untag()->to()); \
416 return Type::InstanceSize(); \
417 }
418
419#if !defined(DART_COMPRESSED_POINTERS)
420#define COMPRESSED_VISITOR(Type) REGULAR_VISITOR(Type)
421#else
422#define COMPRESSED_VISITOR(Type) \
423 intptr_t Untagged##Type::Visit##Type##Pointers( \
424 Type##Ptr raw_obj, ObjectPointerVisitor* visitor) { \
425 /* Make sure that we got here with the tagged pointer as this. */ \
426 ASSERT(raw_obj->IsHeapObject()); \
427 ASSERT_COMPRESSED(Type); \
428 visitor->VisitCompressedPointers(raw_obj->heap_base(), \
429 raw_obj->untag()->from(), \
430 raw_obj->untag()->to()); \
431 return Type::InstanceSize(); \
432 }
433#endif
434
435// It calls the from() and to() methods on the raw object to get the first and
436// last cells that need visiting.
437//
438// Though as opposed to Similar to [REGULAR_VISITOR] this visitor will call the
439// specialized VisitTypedDataViewPointers
440#define TYPED_DATA_VIEW_VISITOR(Type) \
441 intptr_t Untagged##Type::Visit##Type##Pointers( \
442 Type##Ptr raw_obj, ObjectPointerVisitor* visitor) { \
443 /* Make sure that we got here with the tagged pointer as this. */ \
444 ASSERT(raw_obj->IsHeapObject()); \
445 ASSERT_COMPRESSED(Type); \
446 visitor->VisitTypedDataViewPointers(raw_obj, raw_obj->untag()->from(), \
447 raw_obj->untag()->to()); \
448 return Type::InstanceSize(); \
449 }
450
451// For variable length objects. get_length is a code snippet that gets the
452// length of the object, which is passed to InstanceSize and the to() method.
453#define VARIABLE_VISITOR(Type, get_length) \
454 intptr_t Untagged##Type::Visit##Type##Pointers( \
455 Type##Ptr raw_obj, ObjectPointerVisitor* visitor) { \
456 /* Make sure that we got here with the tagged pointer as this. */ \
457 ASSERT(raw_obj->IsHeapObject()); \
458 intptr_t length = get_length; \
459 visitor->VisitPointers(raw_obj->untag()->from(), \
460 raw_obj->untag()->to(length)); \
461 return Type::InstanceSize(length); \
462 }
463
464#if !defined(DART_COMPRESSED_POINTERS)
465#define VARIABLE_COMPRESSED_VISITOR(Type, get_length) \
466 VARIABLE_VISITOR(Type, get_length)
467#else
468#define VARIABLE_COMPRESSED_VISITOR(Type, get_length) \
469 intptr_t Untagged##Type::Visit##Type##Pointers( \
470 Type##Ptr raw_obj, ObjectPointerVisitor* visitor) { \
471 /* Make sure that we got here with the tagged pointer as this. */ \
472 ASSERT(raw_obj->IsHeapObject()); \
473 intptr_t length = get_length; \
474 visitor->VisitCompressedPointers(raw_obj->heap_base(), \
475 raw_obj->untag()->from(), \
476 raw_obj->untag()->to(length)); \
477 return Type::InstanceSize(length); \
478 }
479#endif
480
481// For fixed-length objects that don't have any pointers that need visiting.
482#define NULL_VISITOR(Type) \
483 intptr_t Untagged##Type::Visit##Type##Pointers( \
484 Type##Ptr raw_obj, ObjectPointerVisitor* visitor) { \
485 /* Make sure that we got here with the tagged pointer as this. */ \
486 ASSERT(raw_obj->IsHeapObject()); \
487 ASSERT_NOTHING_TO_VISIT(Type); \
488 return Type::InstanceSize(); \
489 }
490
491// For objects that don't have any pointers that need visiting, but have a
492// variable length.
493#define VARIABLE_NULL_VISITOR(Type, get_length) \
494 intptr_t Untagged##Type::Visit##Type##Pointers( \
495 Type##Ptr raw_obj, ObjectPointerVisitor* visitor) { \
496 /* Make sure that we got here with the tagged pointer as this. */ \
497 ASSERT(raw_obj->IsHeapObject()); \
498 ASSERT_NOTHING_TO_VISIT(Type); \
499 intptr_t length = get_length; \
500 return Type::InstanceSize(length); \
501 }
502
503// For objects that are never instantiated on the heap.
504#define UNREACHABLE_VISITOR(Type) \
505 intptr_t Untagged##Type::Visit##Type##Pointers( \
506 Type##Ptr raw_obj, ObjectPointerVisitor* visitor) { \
507 UNREACHABLE(); \
508 return 0; \
509 }
510
512COMPRESSED_VISITOR(PatchClass)
513COMPRESSED_VISITOR(ClosureData)
514COMPRESSED_VISITOR(FfiTrampolineData)
515COMPRESSED_VISITOR(Script)
516COMPRESSED_VISITOR(Library)
517COMPRESSED_VISITOR(Namespace)
518COMPRESSED_VISITOR(KernelProgramInfo)
519COMPRESSED_VISITOR(WeakSerializationReference)
556 Smi::Value(raw_obj->untag()->length()))
559VARIABLE_COMPRESSED_VISITOR(Context, raw_obj->untag()->num_variables_)
562 TypedData,
563 TypedData::ElementSizeInBytes(raw_obj->GetClassId()) *
564 Smi::Value(raw_obj->untag()->length()))
565VARIABLE_COMPRESSED_VISITOR(ContextScope, raw_obj->untag()->num_variables_)
567 RecordShape(raw_obj->untag()->shape()).num_fields())
583VARIABLE_NULL_VISITOR(PcDescriptors, raw_obj->untag()->length_)
584VARIABLE_NULL_VISITOR(CodeSourceMap, raw_obj->untag()->length_)
586 CompressedStackMaps::PayloadSizeOf(raw_obj))
589// Abstract types don't have their visitor called.
599// Smi has no heap representation.
601
602intptr_t UntaggedField::VisitFieldPointers(FieldPtr raw_obj,
603 ObjectPointerVisitor* visitor) {
604 ASSERT(raw_obj->IsHeapObject());
606 visitor->VisitCompressedPointers(
607 raw_obj->heap_base(), raw_obj->untag()->from(), raw_obj->untag()->to());
608
609 if (visitor->trace_values_through_fields()) {
610 if (Field::StaticBit::decode(raw_obj->untag()->kind_bits_)) {
611 visitor->isolate_group()->ForEachIsolate(
612 [&](Isolate* isolate) {
613 intptr_t index =
614 Smi::Value(raw_obj->untag()->host_offset_or_field_id());
615 visitor->VisitPointer(&isolate->field_table()->table()[index]);
616 },
617 /*at_safepoint=*/true);
618 }
619 }
620 return Field::InstanceSize();
621}
622
623intptr_t UntaggedSuspendState::VisitSuspendStatePointers(
624 SuspendStatePtr raw_obj,
625 ObjectPointerVisitor* visitor) {
626 ASSERT(raw_obj->IsHeapObject());
627 ASSERT_COMPRESSED(SuspendState);
628
629 if (visitor->CanVisitSuspendStatePointers(raw_obj)) {
630 visitor->VisitCompressedPointers(
631 raw_obj->heap_base(), raw_obj->untag()->from(), raw_obj->untag()->to());
632
633 const uword pc = raw_obj->untag()->pc_;
634 if (pc != 0) {
635 Thread* thread = Thread::Current();
636 ASSERT(thread != nullptr);
637 ASSERT(thread->isolate_group() == visitor->isolate_group());
638 const uword sp = reinterpret_cast<uword>(raw_obj->untag()->payload());
639 StackFrame frame(thread);
640 frame.pc_ = pc;
641 frame.sp_ = sp;
642 frame.fp_ = sp + raw_obj->untag()->frame_size_;
643 frame.VisitObjectPointers(visitor);
644 }
645 }
646
647 return SuspendState::InstanceSize(raw_obj->untag()->frame_capacity());
648}
649
650bool UntaggedCode::ContainsPC(const ObjectPtr raw_obj, uword pc) {
651 if (!raw_obj->IsCode()) return false;
652 auto const raw_code = static_cast<const CodePtr>(raw_obj);
653 const uword start = Code::PayloadStartOf(raw_code);
654 const uword size = Code::PayloadSizeOf(raw_code);
655 return (pc - start) <= size; // pc may point just past last instruction.
656}
657
658intptr_t UntaggedCode::VisitCodePointers(CodePtr raw_obj,
659 ObjectPointerVisitor* visitor) {
660 visitor->VisitPointers(raw_obj->untag()->from(), raw_obj->untag()->to());
661
662 UntaggedCode* obj = raw_obj->untag();
663 intptr_t length = Code::PtrOffBits::decode(obj->state_bits_);
664#if defined(TARGET_ARCH_IA32)
665 // On IA32 only we embed pointers to objects directly in the generated
666 // instructions. The variable portion of a Code object describes where to
667 // find those pointers for tracing.
668 if (Code::AliveBit::decode(obj->state_bits_)) {
669 uword entry_point = Code::PayloadStartOf(raw_obj);
670 for (intptr_t i = 0; i < length; i++) {
671 int32_t offset = obj->data()[i];
672 visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(entry_point + offset));
673 }
674 }
676#else
677 // On all other architectures, objects are referenced indirectly through
678 // either an ObjectPool or Thread.
679 ASSERT(length == 0);
680 return Code::InstanceSize(0);
681#endif
682}
683
684intptr_t UntaggedObjectPool::VisitObjectPoolPointers(
685 ObjectPoolPtr raw_obj,
686 ObjectPointerVisitor* visitor) {
687 const intptr_t length = raw_obj->untag()->length_;
688 UntaggedObjectPool::Entry* entries = raw_obj->untag()->data();
689 uint8_t* entry_bits = raw_obj->untag()->entry_bits();
690 for (intptr_t i = 0; i < length; ++i) {
691 ObjectPool::EntryType entry_type =
692 ObjectPool::TypeBits::decode(entry_bits[i]);
693 if (entry_type == ObjectPool::EntryType::kTaggedObject) {
694 visitor->VisitPointer(&entries[i].raw_obj_);
695 }
696 }
698}
699
700bool UntaggedInstructions::ContainsPC(const InstructionsPtr raw_instr,
701 uword pc) {
702 const uword start = Instructions::PayloadStart(raw_instr);
703 const uword size = Instructions::Size(raw_instr);
704 // We use <= instead of < here because the saved-pc can be outside the
705 // instruction stream if the last instruction is a call we don't expect to
706 // return (e.g. because it throws an exception).
707 return (pc - start) <= size;
708}
709
710intptr_t UntaggedInstance::VisitInstancePointers(
711 InstancePtr raw_obj,
712 ObjectPointerVisitor* visitor) {
713 // Make sure that we got here with the tagged pointer as this.
714 ASSERT(raw_obj->IsHeapObject());
715 uword tags = raw_obj->untag()->tags_;
716 intptr_t instance_size = SizeTag::decode(tags);
717 if (instance_size == 0) {
718 instance_size = visitor->class_table()->SizeAt(raw_obj->GetClassId());
719 }
720
721 // Calculate the first and last raw object pointer fields.
722 uword obj_addr = UntaggedObject::ToAddr(raw_obj);
723 uword from = obj_addr + sizeof(UntaggedObject);
724 uword to = obj_addr + instance_size - kCompressedWordSize;
725 visitor->VisitCompressedPointers(raw_obj->heap_base(),
726 reinterpret_cast<CompressedObjectPtr*>(from),
727 reinterpret_cast<CompressedObjectPtr*>(to));
728 return instance_size;
729}
730
731intptr_t UntaggedImmutableArray::VisitImmutableArrayPointers(
732 ImmutableArrayPtr raw_obj,
733 ObjectPointerVisitor* visitor) {
734 return UntaggedArray::VisitArrayPointers(raw_obj, visitor);
735}
736
737intptr_t UntaggedConstMap::VisitConstMapPointers(
738 ConstMapPtr raw_obj,
739 ObjectPointerVisitor* visitor) {
740 return UntaggedMap::VisitMapPointers(raw_obj, visitor);
741}
742
743intptr_t UntaggedConstSet::VisitConstSetPointers(
744 ConstSetPtr raw_obj,
745 ObjectPointerVisitor* visitor) {
746 return UntaggedSet::VisitSetPointers(raw_obj, visitor);
747}
748
749void UntaggedObject::RememberCard(ObjectPtr const* slot) {
750 Page::Of(static_cast<ObjectPtr>(this))->RememberCard(slot);
751}
752
753#if defined(DART_COMPRESSED_POINTERS)
754void UntaggedObject::RememberCard(CompressedObjectPtr const* slot) {
755 Page::Of(static_cast<ObjectPtr>(this))->RememberCard(slot);
756}
757#endif
758
760 RememberCard,
761 2,
762 uword /*ObjectPtr*/ object_in,
763 ObjectPtr* slot) {
764 ObjectPtr object = static_cast<ObjectPtr>(object_in);
765 ASSERT(object->IsOldObject());
766 ASSERT(object->untag()->IsCardRemembered());
767 Page::Of(object)->RememberCard(slot);
768}
770
772 switch (k) {
773#define ENUM_CASE(name, init) \
774 case Kind::k##name: \
775 return #name;
777#undef ENUM_CASE
778 default:
779 return nullptr;
780 }
781}
782
783bool UntaggedPcDescriptors::ParseKind(const char* cstr, Kind* out) {
784 ASSERT(cstr != nullptr && out != nullptr);
785#define ENUM_CASE(name, init) \
786 if (strcmp(#name, cstr) == 0) { \
787 *out = Kind::k##name; \
788 return true; \
789 }
791#undef ENUM_CASE
792 return false;
793}
794#undef PREFIXED_NAME
795
796} // namespace dart
#define CLASS_LIST_NO_OBJECT(V)
Definition: class_id.h:201
#define CLASS_LIST_FFI_TYPE_MARKER(V)
Definition: class_id.h:165
#define CLASS_LIST_TYPED_DATA(V)
Definition: class_id.h:137
static intptr_t InstanceSize()
Definition: object.h:10936
ClassPtr At(intptr_t cid) const
Definition: class_table.h:362
bool IsValidIndex(intptr_t cid) const
Definition: class_table.h:379
UnboxedFieldBitmap GetUnboxedFieldsMapAt(intptr_t cid) const
Definition: class_table.h:388
bool HasValidClassAt(intptr_t cid) const
Definition: class_table.h:386
static intptr_t InstanceSize()
Definition: object.h:6229
static uword PayloadSizeOf(const CodePtr code)
Definition: object.h:6904
static intptr_t InstanceSize()
Definition: object.h:7163
static uword PayloadStartOf(const CodePtr code)
Definition: object.h:6851
static intptr_t InstanceSize()
Definition: object.h:6299
static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw)
Definition: object.h:6270
static intptr_t InstanceSize()
Definition: object.h:7535
static intptr_t InstanceSize()
Definition: object.h:7448
static IsolateGroup * vm_isolate_group()
Definition: dart.h:69
static intptr_t InstanceSize()
Definition: object.h:6606
ObjectPtr * table()
Definition: field_table.h:43
static intptr_t InstanceSize()
Definition: object.h:4558
@ kNew
Definition: heap.h:38
static intptr_t InstanceSize()
Definition: object.h:5935
static intptr_t Size(const InstructionsSectionPtr instr)
Definition: object.h:5932
static intptr_t InstanceSize()
Definition: object.h:5833
uword PayloadStart() const
Definition: object.h:5745
intptr_t Size() const
Definition: object.h:5740
Heap * heap() const
Definition: isolate.h:296
static IsolateGroup * Current()
Definition: isolate.h:539
ClassTable * class_table() const
Definition: isolate.h:496
FieldTable * field_table() const
Definition: isolate.h:1000
static intptr_t InstanceSize()
Definition: object.h:6055
static void Sleep(int64_t millis)
const ClassTable * class_table() const
Definition: visitor.h:71
void VisitCompressedPointers(uword heap_base, CompressedObjectPtr *first, CompressedObjectPtr *last)
Definition: visitor.h:43
compiler::ObjectPoolBuilderEntry::EntryType EntryType
Definition: object.h:5552
static intptr_t InstanceSize()
Definition: object.h:5649
void Validate(IsolateGroup *isolate_group) const
Definition: raw_object.cc:30
UntaggedObject * untag() const
static intptr_t InstanceSize()
Definition: object.h:10564
static Page * Of(ObjectPtr obj)
Definition: page.h:162
void RememberCard(ObjectPtr const *slot)
Definition: page.h:185
static intptr_t InstanceSize()
Definition: object.h:6089
static intptr_t InstanceSize()
Definition: object.h:11887
static intptr_t InstanceSize()
Definition: object.h:11460
intptr_t Value() const
Definition: object.h:9990
static intptr_t InstanceSize()
Definition: object.h:12626
static Thread * Current()
Definition: thread.h:362
static intptr_t InstanceSize()
Definition: object.h:10704
static intptr_t InstanceSize()
Definition: object.h:8988
intptr_t ElementSizeInBytes() const
Definition: object.h:11531
static intptr_t InstanceSize()
Definition: object.h:11673
static constexpr uword decode(uword tag)
Definition: raw_object.h:208
uword tags() const
Definition: raw_object.h:298
void Validate(IsolateGroup *isolate_group) const
Definition: raw_object.cc:42
bool IsCardRemembered() const
Definition: raw_object.h:385
static uword ToAddr(const UntaggedObject *raw_obj)
Definition: raw_object.h:522
bool IsOldObject() const
Definition: raw_object.h:293
intptr_t HeapSize() const
Definition: raw_object.h:401
bool IsMarked() const
Definition: raw_object.h:304
bool InVMIsolateHeap() const
Definition: raw_object.cc:20
void VisitPointersPrecise(ObjectPointerVisitor *visitor)
Definition: raw_object.cc:371
bool IsNewObject() const
Definition: raw_object.h:288
uword heap_base() const
Definition: raw_object.h:590
friend class StackFrame
Definition: raw_object.h:837
intptr_t GetClassId() const
Definition: raw_object.h:392
friend class FreeListElement
Definition: raw_object.h:814
static const char * KindToCString(Kind k)
Definition: raw_object.cc:771
static bool ParseKind(const char *cstr, Kind *out)
Definition: raw_object.cc:783
Definition: il.h:75
static intptr_t InstanceSize()
Definition: object.h:6742
static intptr_t InstanceSize()
Definition: object.h:6679
#define ASSERT(E)
double frame
Definition: examples.cpp:31
#define FATAL(error)
size_t length
Definition: dart_vm.cc:33
static constexpr intptr_t kCompressedWordSizeLog2
Definition: globals.h:43
VARIABLE_COMPRESSED_VISITOR(WeakArray, Smi::Value(raw_obj->untag() ->length())) VARIABLE_COMPRESSED_VISITOR(TypeArguments
@ kForwardingCorpse
Definition: class_id.h:225
@ kNullCid
Definition: class_id.h:252
@ kNumPredefinedCids
Definition: class_id.h:257
@ kByteDataViewCid
Definition: class_id.h:244
@ kByteBufferCid
Definition: class_id.h:247
@ kNeverCid
Definition: class_id.h:255
@ kFreeListElement
Definition: class_id.h:224
@ kUnmodifiableByteDataViewCid
Definition: class_id.h:245
uintptr_t uword
Definition: globals.h:501
static constexpr intptr_t kCompressedWordSize
Definition: globals.h:42
raw_obj untag() -> num_entries()) VARIABLE_COMPRESSED_VISITOR(Array, Smi::Value(raw_obj->untag() ->length())) VARIABLE_COMPRESSED_VISITOR(TypedData, TypedData::ElementSizeInBytes(raw_obj->GetClassId()) *Smi::Value(raw_obj->untag() ->length())) VARIABLE_COMPRESSED_VISITOR(Record, RecordShape(raw_obj->untag() ->shape()).num_fields()) VARIABLE_NULL_VISITOR(CompressedStackMaps, CompressedStackMaps::PayloadSizeOf(raw_obj)) VARIABLE_NULL_VISITOR(OneByteString, Smi::Value(raw_obj->untag() ->length())) VARIABLE_NULL_VISITOR(TwoByteString, Smi::Value(raw_obj->untag() ->length())) intptr_t UntaggedField::VisitFieldPointers(FieldPtr raw_obj, ObjectPointerVisitor *visitor)
Definition: raw_object.cc:558
@ kHeapObjectTag
DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Thread *thread)
ObjectPtr CompressedObjectPtr
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
TSize< Scalar > Size
Definition: size.h:137
#define Px
Definition: globals.h:410
#define Pd
Definition: globals.h:408
static DecodeResult decode(std::string path)
Definition: png_codec.cpp:124
#define SIZE_FROM_CLASS(clazz)
#define TYPED_DATA_VIEW_VISITOR(Type)
Definition: raw_object.cc:440
#define COMPRESSED_VISITOR(Type)
Definition: raw_object.cc:420
#define REGULAR_VISITOR(Type)
Definition: raw_object.cc:409
#define ENUM_CASE(name, init)
#define RAW_VISITPOINTERS(clazz)
#define NULL_VISITOR(Type)
Definition: raw_object.cc:482
#define UNREACHABLE_VISITOR(Type)
Definition: raw_object.cc:504
#define VARIABLE_NULL_VISITOR(Type, get_length)
Definition: raw_object.cc:493
#define FOR_EACH_RAW_PC_DESCRIPTOR(V)
Definition: raw_object.h:2052
#define ASSERT_COMPRESSED(Type)
Definition: raw_object.h:118
#define END_LEAF_RUNTIME_ENTRY
SeparatedVector2 offset