forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvisitor.cc
More file actions
132 lines (117 loc) Β· 4.86 KB
/
visitor.cc
File metadata and controls
132 lines (117 loc) Β· 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/cppgc/visitor.h"
#include "src/base/sanitizer/asan.h"
#include "src/base/sanitizer/msan.h"
#include "src/heap/cppgc/gc-info-table.h"
#include "src/heap/cppgc/heap-base.h"
#include "src/heap/cppgc/heap-object-header.h"
#include "src/heap/cppgc/heap-page.h"
#include "src/heap/cppgc/object-view.h"
#include "src/heap/cppgc/page-memory.h"
#if defined(CPPGC_CAGED_HEAP)
#include "src/heap/cppgc/caged-heap.h"
#endif // defined(CPPGC_CAGED_HEAP)
namespace cppgc {
#ifdef V8_ENABLE_CHECKS
void Visitor::CheckObjectNotInConstruction(const void* address) {
// TODO(chromium:1056170): |address| is an inner pointer of an object. Check
// that the object is not in construction.
}
#endif // V8_ENABLE_CHECKS
namespace internal {
#if defined(CPPGC_POINTER_COMPRESSION)
// CompressedPointer is compatible with RawPointer and will find full pointers
// as well.
using PointerRepresentation = CompressedPointer;
#else
using PointerRepresentation = RawPointer;
#endif // defined(CPPGC_POINTER_COMPRESSION)
ConservativeTracingVisitor::ConservativeTracingVisitor(
HeapBase& heap, PageBackend& page_backend, cppgc::Visitor& visitor)
: heap_(heap), page_backend_(page_backend), visitor_(visitor) {}
// Conservative scanning of objects is not compatible with ASAN as we may scan
// over objects reading poisoned memory. One such example was added to libc++
// (June 2024) in the form of container annotations for short std::string.
DISABLE_ASAN
void ConservativeTracingVisitor::TraceConservatively(
const HeapObjectHeader& header) {
const auto object_view = ObjectView<>(header);
uintptr_t* word = reinterpret_cast<uintptr_t*>(object_view.Start());
for (size_t i = 0; i < (object_view.Size() / sizeof(uintptr_t)); ++i) {
uintptr_t maybe_full_ptr = word[i];
// |object| may be uninitialized by design or just contain padding bytes.
// Copy into a local variable that is not poisoned for conservative marking.
// Copy into a temporary variable to maintain the original MSAN state.
MSAN_MEMORY_IS_INITIALIZED(&maybe_full_ptr, sizeof(maybe_full_ptr));
// Neither first OS page, nor first cage page contain Oilpan objects.
if (maybe_full_ptr <= SentinelPointer::kSentinelValue) {
continue;
}
PointerRepresentation::VisitPossiblePointers(
reinterpret_cast<void*>(maybe_full_ptr),
[this](const void* raw_pointer) {
this->TraceConservativelyIfNeeded(raw_pointer);
});
// We must also trace full pointers here as the conservative tracing visitor
// may be overridden to find pointers to other areas conservatively as well.
// E.g., v8::TracedReference points into a different memory region and is
// scanned conservatively when the GCed object is in construction. See
// `UnifiedHeapConservativeMarkingVisitor::TraceConservativelyIfNeeded()`.
this->TraceConservativelyIfNeeded(reinterpret_cast<void*>(maybe_full_ptr));
}
}
void ConservativeTracingVisitor::TryTracePointerConservatively(
ConstAddress address) {
#if defined(CPPGC_CAGED_HEAP)
// TODO(chromium:1056170): Add support for SIMD in stack scanning.
if (V8_LIKELY(!CagedHeapBase::IsWithinCage(address))) return;
#endif // defined(CPPGC_CAGED_HEAP)
const BasePage* page =
reinterpret_cast<const BasePage*>(page_backend_.Lookup(address));
if (!page) {
return;
}
DCHECK_EQ(&heap_, &page->heap());
auto* header = const_cast<HeapObjectHeader*>(
page->TryObjectHeaderFromInnerAddress(address));
if (!header) {
return;
}
TraceConservativelyIfNeeded(*header);
}
void ConservativeTracingVisitor::TraceConservativelyIfNeeded(
const void* address) {
// Neither first OS page, nor first cage page contain Oilpan objects.
if (reinterpret_cast<ConstAddress>(address) <=
reinterpret_cast<ConstAddress>(SentinelPointer::kSentinelValue)) {
return;
}
PointerRepresentation::VisitPossiblePointers(
address, [this](const void* raw_pointer) {
this->TryTracePointerConservatively(
reinterpret_cast<ConstAddress>(raw_pointer));
});
}
void ConservativeTracingVisitor::TraceConservativelyIfNeeded(
HeapObjectHeader& header) {
if (!header.IsInConstruction<AccessMode::kNonAtomic>()) {
VisitFullyConstructedConservatively(header);
} else {
VisitInConstructionConservatively(
header,
[](ConservativeTracingVisitor* v, const HeapObjectHeader& header) {
v->TraceConservatively(header);
});
}
}
void ConservativeTracingVisitor::VisitFullyConstructedConservatively(
HeapObjectHeader& header) {
visitor_.Visit(
header.ObjectStart(),
{header.ObjectStart(),
GlobalGCInfoTable::GCInfoFromIndex(header.GetGCInfoIndex()).trace});
}
} // namespace internal
} // namespace cppgc