• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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