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
133
134
135
136
137
138
139
140
141
142
143
|
// 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/marking-visitor.h"
#include "include/cppgc/garbage-collected.h"
#include "include/cppgc/internal/accessors.h"
#include "src/heap/cppgc/heap-object-header-inl.h"
#include "src/heap/cppgc/heap.h"
namespace cppgc {
namespace internal {
// static
bool MarkingVisitor::IsInConstruction(const HeapObjectHeader& header) {
return header.IsInConstruction<HeapObjectHeader::AccessMode::kNonAtomic>();
}
MarkingVisitor::MarkingVisitor(Marker* marking_handler, int task_id)
: marker_(marking_handler),
marking_worklist_(marking_handler->marking_worklist(), task_id),
not_fully_constructed_worklist_(
marking_handler->not_fully_constructed_worklist(), task_id),
weak_callback_worklist_(marking_handler->weak_callback_worklist(),
task_id) {}
void MarkingVisitor::AccountMarkedBytes(const HeapObjectHeader& header) {
marked_bytes_ +=
header.IsLargeObject()
? reinterpret_cast<const LargePage*>(BasePage::FromPayload(&header))
->PayloadSize()
: header.GetSize();
}
void MarkingVisitor::Visit(const void* object, TraceDescriptor desc) {
DCHECK_NOT_NULL(object);
if (desc.base_object_payload ==
cppgc::GarbageCollectedMixin::kNotFullyConstructedObject) {
// This means that the objects are not-yet-fully-constructed. See comments
// on GarbageCollectedMixin for how those objects are handled.
not_fully_constructed_worklist_.Push(object);
return;
}
MarkHeader(&HeapObjectHeader::FromPayload(
const_cast<void*>(desc.base_object_payload)),
desc);
}
void MarkingVisitor::VisitWeak(const void* object, TraceDescriptor desc,
WeakCallback weak_callback,
const void* weak_member) {
// Filter out already marked values. The write barrier for WeakMember
// ensures that any newly set value after this point is kept alive and does
// not require the callback.
if (desc.base_object_payload !=
cppgc::GarbageCollectedMixin::kNotFullyConstructedObject &&
HeapObjectHeader::FromPayload(desc.base_object_payload)
.IsMarked<HeapObjectHeader::AccessMode::kAtomic>())
return;
RegisterWeakCallback(weak_callback, weak_member);
}
void MarkingVisitor::VisitRoot(const void* object, TraceDescriptor desc) {
Visit(object, desc);
}
void MarkingVisitor::VisitWeakRoot(const void* object, TraceDescriptor desc,
WeakCallback weak_callback,
const void* weak_root) {
if (desc.base_object_payload ==
cppgc::GarbageCollectedMixin::kNotFullyConstructedObject) {
// This method is only called at the end of marking. If the object is in
// construction, then it should be reachable from the stack.
return;
}
// Since weak roots arev only traced at the end of marking, we can execute
// the callback instead of registering it.
weak_callback(LivenessBrokerFactory::Create(), weak_root);
}
void MarkingVisitor::MarkHeader(HeapObjectHeader* header,
TraceDescriptor desc) {
DCHECK(header);
DCHECK_NOT_NULL(desc.callback);
if (IsInConstruction(*header)) {
not_fully_constructed_worklist_.Push(header->Payload());
} else if (MarkHeaderNoTracing(header)) {
marking_worklist_.Push(desc);
}
}
bool MarkingVisitor::MarkHeaderNoTracing(HeapObjectHeader* header) {
DCHECK(header);
// A GC should only mark the objects that belong in its heap.
DCHECK_EQ(marker_->heap(), BasePage::FromPayload(header)->heap());
// Never mark free space objects. This would e.g. hint to marking a promptly
// freed backing store.
DCHECK(!header->IsFree());
return header->TryMarkAtomic();
}
void MarkingVisitor::RegisterWeakCallback(WeakCallback callback,
const void* object) {
weak_callback_worklist_.Push({callback, object});
}
void MarkingVisitor::FlushWorklists() {
marking_worklist_.FlushToGlobal();
not_fully_constructed_worklist_.FlushToGlobal();
weak_callback_worklist_.FlushToGlobal();
}
void MarkingVisitor::DynamicallyMarkAddress(ConstAddress address) {
for (auto* header : marker_->heap()->objects()) {
if (address >= header->Payload() &&
address < (header->Payload() + header->GetSize())) {
header->TryMarkAtomic();
}
}
// TODO(chromium:1056170): Implement dynamically getting HeapObjectHeader
// for handling previously_not_fully_constructed objects. Requires object
// start bitmap.
}
void MarkingVisitor::VisitPointer(const void* address) {
for (auto* header : marker_->heap()->objects()) {
if (address >= header->Payload() &&
address < (header->Payload() + header->GetSize())) {
header->TryMarkAtomic();
}
}
// TODO(chromium:1056170): Implement proper conservative scanning for
// on-stack objects. Requires page bloom filter.
}
MutatorThreadMarkingVisitor::MutatorThreadMarkingVisitor(Marker* marker)
: MarkingVisitor(marker, Marker::kMutatorThreadId) {}
} // namespace internal
} // namespace cppgc
|