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/heap/verifier.h"
6
7#include "platform/assert.h"
8#include "vm/dart.h"
9#include "vm/dart_api_state.h"
10#include "vm/heap/heap.h"
11#include "vm/isolate.h"
12#include "vm/object.h"
13#include "vm/object_set.h"
14#include "vm/raw_object.h"
15#include "vm/stack_frame.h"
16
17namespace dart {
18
19void VerifyObjectVisitor::VisitObject(ObjectPtr raw_obj) {
20 if (raw_obj->IsHeapObject()) {
21 uword raw_addr = ObjectLayout::ToAddr(raw_obj);
22 if (raw_obj->IsFreeListElement() || raw_obj->IsForwardingCorpse()) {
23 if (raw_obj->IsOldObject() && raw_obj->ptr()->IsMarked()) {
24 FATAL1("Marked free list element encountered %#" Px "\n", raw_addr);
25 }
26 } else {
27 switch (mark_expectation_) {
28 case kForbidMarked:
29 if (raw_obj->IsOldObject() && raw_obj->ptr()->IsMarked()) {
30 FATAL1("Marked object encountered %#" Px "\n", raw_addr);
31 }
32 break;
33 case kAllowMarked:
34 break;
35 case kRequireMarked:
36 if (raw_obj->IsOldObject() && !raw_obj->ptr()->IsMarked()) {
37 FATAL1("Unmarked object encountered %#" Px "\n", raw_addr);
38 }
39 break;
40 }
41 }
42 }
43 allocated_set_->Add(raw_obj);
44 raw_obj->Validate(isolate_group_);
45}
46
47void VerifyPointersVisitor::VisitPointers(ObjectPtr* first, ObjectPtr* last) {
48 for (ObjectPtr* current = first; current <= last; current++) {
49 ObjectPtr raw_obj = *current;
50 if (raw_obj->IsHeapObject()) {
51 if (!allocated_set_->Contains(raw_obj)) {
52 if (raw_obj->IsInstructions() &&
53 allocated_set_->Contains(OldPage::ToWritable(raw_obj))) {
54 continue;
55 }
56 uword raw_addr = ObjectLayout::ToAddr(raw_obj);
57 FATAL1("Invalid object pointer encountered %#" Px "\n", raw_addr);
58 }
59 }
60 }
61}
62
63void VerifyWeakPointersVisitor::VisitHandle(uword addr) {
64 FinalizablePersistentHandle* handle =
65 reinterpret_cast<FinalizablePersistentHandle*>(addr);
66 ObjectPtr raw_obj = handle->raw();
67 visitor_->VisitPointer(&raw_obj);
68}
69
70void VerifyPointersVisitor::VerifyPointers(MarkExpectation mark_expectation) {
71 Thread* thread = Thread::Current();
72 auto isolate_group = thread->isolate_group();
73 HeapIterationScope iteration(thread);
74 StackZone stack_zone(thread);
75 ObjectSet* allocated_set = isolate_group->heap()->CreateAllocatedObjectSet(
76 stack_zone.GetZone(), mark_expectation);
77
78 VerifyPointersVisitor visitor(isolate_group, allocated_set);
79 // Visit all strongly reachable objects.
80 iteration.IterateObjectPointers(&visitor, ValidationPolicy::kValidateFrames);
81 VerifyWeakPointersVisitor weak_visitor(&visitor);
82
83 // Visit weak handles and prologue weak handles.
84 isolate_group->VisitWeakPersistentHandles(&weak_visitor);
85}
86
87#if defined(DEBUG)
88VerifyCanonicalVisitor::VerifyCanonicalVisitor(Thread* thread)
89 : thread_(thread), instanceHandle_(Instance::Handle(thread->zone())) {}
90
91void VerifyCanonicalVisitor::VisitObject(ObjectPtr obj) {
92 // TODO(dartbug.com/36097): The heap walk can encounter canonical objects of
93 // other isolates. We should either scan live objects from the roots of each
94 // individual isolate, or wait until we are ready to share constants across
95 // isolates.
96 if (!FLAG_enable_isolate_groups) {
97 if ((obj->GetClassId() >= kInstanceCid) &&
98 (obj->GetClassId() != kTypeArgumentsCid)) {
99 if (obj->ptr()->IsCanonical()) {
100 instanceHandle_ ^= obj;
101 const bool is_canonical = instanceHandle_.CheckIsCanonical(thread_);
102 if (!is_canonical) {
103 OS::PrintErr("Instance `%s` is not canonical!\n",
104 instanceHandle_.ToCString());
105 }
106 ASSERT(is_canonical);
107 }
108 }
109 }
110}
111#endif // defined(DEBUG)
112
113} // namespace dart
114