1 // Copyright 2022 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/reference-summarizer.h"
6
7 #include "src/heap/mark-compact-inl.h"
8 #include "src/heap/marking-visitor-inl.h"
9 #include "src/objects/embedder-data-array-inl.h"
10 #include "src/objects/js-array-buffer-inl.h"
11
12 namespace v8 {
13 namespace internal {
14
15 namespace {
16
17 // A class which acts as a MarkingState but does not actually update any marking
18 // bits. It reports all objects as white and all transitions as successful. It
19 // also tracks which objects are retained by the primary object according to the
20 // marking visitor.
21 class ReferenceSummarizerMarkingState final {
22 public:
23 // Declares that this marking state is collecting retainers, so the marking
24 // visitor must fully visit each object and can't update on-heap state.
25 static constexpr bool kCollectRetainers = true;
26
ReferenceSummarizerMarkingState(HeapObject object)27 explicit ReferenceSummarizerMarkingState(HeapObject object)
28 : primary_object_(object),
29 local_marking_worklists_(&marking_worklists_),
30 local_weak_objects_(&weak_objects_) {}
31
~ReferenceSummarizerMarkingState()32 ~ReferenceSummarizerMarkingState() {
33 // Clean up temporary state.
34 local_weak_objects_.Publish();
35 weak_objects_.Clear();
36 local_marking_worklists_.Publish();
37 marking_worklists_.Clear();
38 }
39
40 // Retrieves the references that were collected by this marker. This operation
41 // transfers ownership of the set, so calling it again would yield an empty
42 // result.
DestructivelyRetrieveReferences()43 ReferenceSummary DestructivelyRetrieveReferences() {
44 ReferenceSummary tmp = std::move(references_);
45 references_.Clear();
46 return tmp;
47 }
48
49 // Standard marking visitor functions:
50
IsWhite(HeapObject obj) const51 bool IsWhite(HeapObject obj) const { return true; }
52
IsBlackOrGrey(HeapObject obj) const53 bool IsBlackOrGrey(HeapObject obj) const { return false; }
54
WhiteToGrey(HeapObject obj)55 bool WhiteToGrey(HeapObject obj) { return true; }
56
GreyToBlack(HeapObject obj)57 bool GreyToBlack(HeapObject obj) { return true; }
58
59 // Adds a retaining relationship found by the marking visitor.
AddStrongReferenceForReferenceSummarizer(HeapObject host,HeapObject obj)60 void AddStrongReferenceForReferenceSummarizer(HeapObject host,
61 HeapObject obj) {
62 AddReference(host, obj, references_.strong_references());
63 }
64
65 // Adds a non-retaining weak reference found by the marking visitor. The value
66 // in an ephemeron hash table entry is also included here, since it is not
67 // known to be strong without further information about the key.
AddWeakReferenceForReferenceSummarizer(HeapObject host,HeapObject obj)68 void AddWeakReferenceForReferenceSummarizer(HeapObject host, HeapObject obj) {
69 AddReference(host, obj, references_.weak_references());
70 }
71
72 // Other member functions, not part of the marking visitor contract:
73
local_marking_worklists()74 MarkingWorklists::Local* local_marking_worklists() {
75 return &local_marking_worklists_;
76 }
local_weak_objects()77 WeakObjects::Local* local_weak_objects() { return &local_weak_objects_; }
78
79 private:
AddReference(HeapObject host,HeapObject obj,std::unordered_set<HeapObject,Object::Hasher> & references)80 void AddReference(
81 HeapObject host, HeapObject obj,
82 std::unordered_set<HeapObject, Object::Hasher>& references) {
83 // It's possible that the marking visitor handles multiple objects at once,
84 // such as a Map and its DescriptorArray, but we're only interested in
85 // references from the primary object.
86 if (host == primary_object_) {
87 references.insert(obj);
88 }
89 }
90
91 ReferenceSummary references_;
92 HeapObject primary_object_;
93 MarkingWorklists marking_worklists_;
94 MarkingWorklists::Local local_marking_worklists_;
95 WeakObjects weak_objects_;
96 WeakObjects::Local local_weak_objects_;
97 };
98
99 } // namespace
100
SummarizeReferencesFrom(Heap * heap,HeapObject obj)101 ReferenceSummary ReferenceSummary::SummarizeReferencesFrom(Heap* heap,
102 HeapObject obj) {
103 ReferenceSummarizerMarkingState marking_state(obj);
104
105 MainMarkingVisitor<ReferenceSummarizerMarkingState> visitor(
106 &marking_state, marking_state.local_marking_worklists(),
107 marking_state.local_weak_objects(), heap, 0 /*mark_compact_epoch*/,
108 {} /*code_flush_mode*/, false /*embedder_tracing_enabled*/,
109 true /*should_keep_ages_unchanged*/);
110 visitor.Visit(obj.map(heap->isolate()), obj);
111
112 return marking_state.DestructivelyRetrieveReferences();
113 }
114
115 } // namespace internal
116 } // namespace v8
117