1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/heap/cppgc/marking-verifier.h"
6
7 #include "src/base/logging.h"
8 #include "src/heap/cppgc/gc-info-table.h"
9 #include "src/heap/cppgc/heap-object-header.h"
10 #include "src/heap/cppgc/heap.h"
11 #include "src/heap/cppgc/marking-visitor.h"
12
13 namespace cppgc {
14 namespace internal {
15
MarkingVerifierBase(HeapBase & heap,std::unique_ptr<cppgc::Visitor> visitor)16 MarkingVerifierBase::MarkingVerifierBase(
17 HeapBase& heap, std::unique_ptr<cppgc::Visitor> visitor)
18 : ConservativeTracingVisitor(heap, *heap.page_backend(), *visitor.get()),
19 visitor_(std::move(visitor)) {}
20
Run(Heap::Config::StackState stack_state)21 void MarkingVerifierBase::Run(Heap::Config::StackState stack_state) {
22 Traverse(&heap_.raw_heap());
23 if (stack_state == Heap::Config::StackState::kMayContainHeapPointers) {
24 in_construction_objects_ = &in_construction_objects_stack_;
25 heap_.stack()->IteratePointers(this);
26 CHECK_EQ(in_construction_objects_stack_, in_construction_objects_heap_);
27 }
28 }
29
VerifyMarked(const void * base_object_payload) const30 void VerificationState::VerifyMarked(const void* base_object_payload) const {
31 const HeapObjectHeader& child_header =
32 HeapObjectHeader::FromPayload(base_object_payload);
33
34 if (!child_header.IsMarked()) {
35 FATAL(
36 "MarkingVerifier: Encountered unmarked object.\n"
37 "#\n"
38 "# Hint:\n"
39 "# %s\n"
40 "# \\-> %s",
41 parent_->GetName().value, child_header.GetName().value);
42 }
43 }
44
VisitInConstructionConservatively(HeapObjectHeader & header,TraceConservativelyCallback callback)45 void MarkingVerifierBase::VisitInConstructionConservatively(
46 HeapObjectHeader& header, TraceConservativelyCallback callback) {
47 CHECK(header.IsMarked());
48 in_construction_objects_->insert(&header);
49 callback(this, header);
50 }
51
VisitPointer(const void * address)52 void MarkingVerifierBase::VisitPointer(const void* address) {
53 TraceConservativelyIfNeeded(address);
54 }
55
VisitHeapObjectHeader(HeapObjectHeader * header)56 bool MarkingVerifierBase::VisitHeapObjectHeader(HeapObjectHeader* header) {
57 // Verify only non-free marked objects.
58 if (!header->IsMarked()) return true;
59
60 DCHECK(!header->IsFree());
61
62 SetCurrentParent(header);
63
64 if (!header->IsInConstruction()) {
65 header->Trace(visitor_.get());
66 } else {
67 // Dispatches to conservative tracing implementation.
68 TraceConservativelyIfNeeded(*header);
69 }
70
71 return true;
72 }
73
74 namespace {
75
76 class VerificationVisitor final : public cppgc::Visitor {
77 public:
VerificationVisitor(VerificationState & state)78 explicit VerificationVisitor(VerificationState& state)
79 : cppgc::Visitor(VisitorFactory::CreateKey()), state_(state) {}
80
Visit(const void *,TraceDescriptor desc)81 void Visit(const void*, TraceDescriptor desc) final {
82 state_.VerifyMarked(desc.base_object_payload);
83 }
84
VisitWeak(const void *,TraceDescriptor desc,WeakCallback,const void *)85 void VisitWeak(const void*, TraceDescriptor desc, WeakCallback,
86 const void*) final {
87 // Weak objects should have been cleared at this point. As a consequence,
88 // all objects found through weak references have to point to live objects
89 // at this point.
90 state_.VerifyMarked(desc.base_object_payload);
91 }
92
VisitWeakContainer(const void * object,TraceDescriptor,TraceDescriptor weak_desc,WeakCallback,const void *)93 void VisitWeakContainer(const void* object, TraceDescriptor,
94 TraceDescriptor weak_desc, WeakCallback,
95 const void*) {
96 if (!object) return;
97
98 // Contents of weak containers are found themselves through page iteration
99 // and are treated strongly, similar to how they are treated strongly when
100 // found through stack scanning. The verification here only makes sure that
101 // the container itself is properly marked.
102 state_.VerifyMarked(weak_desc.base_object_payload);
103 }
104
105 private:
106 VerificationState& state_;
107 };
108
109 } // namespace
110
MarkingVerifier(HeapBase & heap_base)111 MarkingVerifier::MarkingVerifier(HeapBase& heap_base)
112 : MarkingVerifierBase(heap_base,
113 std::make_unique<VerificationVisitor>(state_)) {}
114
SetCurrentParent(const HeapObjectHeader * parent)115 void MarkingVerifier::SetCurrentParent(const HeapObjectHeader* parent) {
116 state_.SetCurrentParent(parent);
117 }
118
119 } // namespace internal
120 } // namespace cppgc
121