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