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/visitor.h"
6
7 #include "src/heap/cppgc/gc-info-table.h"
8 #include "src/heap/cppgc/heap-object-header.h"
9 #include "src/heap/cppgc/heap-page.h"
10 #include "src/heap/cppgc/page-memory.h"
11 #include "src/heap/cppgc/sanitizers.h"
12
13 namespace cppgc {
14
15 #ifdef V8_ENABLE_CHECKS
CheckObjectNotInConstruction(const void * address)16 void Visitor::CheckObjectNotInConstruction(const void* address) {
17 // TODO(chromium:1056170): |address| is an inner pointer of an object. Check
18 // that the object is not in construction.
19 }
20 #endif // V8_ENABLE_CHECKS
21
22 namespace internal {
23
ConservativeTracingVisitor(HeapBase & heap,PageBackend & page_backend,cppgc::Visitor & visitor)24 ConservativeTracingVisitor::ConservativeTracingVisitor(
25 HeapBase& heap, PageBackend& page_backend, cppgc::Visitor& visitor)
26 : heap_(heap), page_backend_(page_backend), visitor_(visitor) {}
27
28 namespace {
29
TraceConservatively(ConservativeTracingVisitor * conservative_visitor,const HeapObjectHeader & header)30 void TraceConservatively(ConservativeTracingVisitor* conservative_visitor,
31 const HeapObjectHeader& header) {
32 Address* payload = reinterpret_cast<Address*>(header.Payload());
33 const size_t payload_size = header.GetSize();
34 for (size_t i = 0; i < (payload_size / sizeof(Address)); ++i) {
35 Address maybe_ptr = payload[i];
36 #if defined(MEMORY_SANITIZER)
37 // |payload| may be uninitialized by design or just contain padding bytes.
38 // Copy into a local variable that is not poisoned for conservative marking.
39 // Copy into a temporary variable to maintain the original MSAN state.
40 MSAN_UNPOISON(&maybe_ptr, sizeof(maybe_ptr));
41 #endif
42 if (maybe_ptr) {
43 conservative_visitor->TraceConservativelyIfNeeded(maybe_ptr);
44 }
45 }
46 }
47
48 } // namespace
49
TraceConservativelyIfNeeded(const void * address)50 void ConservativeTracingVisitor::TraceConservativelyIfNeeded(
51 const void* address) {
52 // TODO(chromium:1056170): Add page bloom filter
53
54 const BasePage* page = reinterpret_cast<const BasePage*>(
55 page_backend_.Lookup(static_cast<ConstAddress>(address)));
56
57 if (!page) return;
58
59 DCHECK_EQ(&heap_, page->heap());
60
61 auto* header = page->TryObjectHeaderFromInnerAddress(
62 const_cast<Address>(reinterpret_cast<ConstAddress>(address)));
63
64 if (!header) return;
65
66 TraceConservativelyIfNeeded(*header);
67 }
68
TraceConservativelyIfNeeded(HeapObjectHeader & header)69 void ConservativeTracingVisitor::TraceConservativelyIfNeeded(
70 HeapObjectHeader& header) {
71 if (!header.IsInConstruction<AccessMode::kNonAtomic>()) {
72 VisitFullyConstructedConservatively(header);
73 } else {
74 VisitInConstructionConservatively(header, TraceConservatively);
75 }
76 }
77
VisitFullyConstructedConservatively(HeapObjectHeader & header)78 void ConservativeTracingVisitor::VisitFullyConstructedConservatively(
79 HeapObjectHeader& header) {
80 visitor_.Visit(
81 header.Payload(),
82 {header.Payload(),
83 GlobalGCInfoTable::GCInfoFromIndex(header.GetGCInfoIndex()).trace});
84 }
85
86 } // namespace internal
87 } // namespace cppgc
88