Line data Source code
1 : // Copyright 2011 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/objects-visiting.h"
6 :
7 : #include "src/heap/heap-inl.h"
8 : #include "src/heap/mark-compact-inl.h"
9 : #include "src/heap/objects-visiting-inl.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 : // We don't record weak slots during marking or scavenges. Instead we do it
15 : // once when we complete mark-compact cycle. Note that write barrier has no
16 : // effect if we are already in the middle of compacting mark-sweep cycle and we
17 : // have to record slots manually.
18 : static bool MustRecordSlots(Heap* heap) {
19 903654 : return heap->gc_state() == Heap::MARK_COMPACT &&
20 : heap->mark_compact_collector()->is_compacting();
21 : }
22 :
23 :
24 : template <class T>
25 : struct WeakListVisitor;
26 :
27 : template <class T>
28 315638 : Object VisitWeakList(Heap* heap, Object list, WeakObjectRetainer* retainer) {
29 : Object undefined = ReadOnlyRoots(heap).undefined_value();
30 : Object head = undefined;
31 : T tail;
32 : bool record_slots = MustRecordSlots(heap);
33 :
34 4201106 : while (list != undefined) {
35 : // Check whether to keep the candidate in the list.
36 : T candidate = T::cast(list);
37 :
38 1942734 : Object retained = retainer->RetainAs(list);
39 :
40 : // Move to the next element before the WeakNext is cleared.
41 : list = WeakListVisitor<T>::WeakNext(candidate);
42 :
43 1942734 : if (retained != Object()) {
44 1790800 : if (head == undefined) {
45 : // First element in the list.
46 : head = retained;
47 : } else {
48 : // Subsequent elements in the list.
49 : DCHECK(!tail.is_null());
50 119668 : WeakListVisitor<T>::SetWeakNext(tail, retained);
51 1644585 : if (record_slots) {
52 : HeapObject slot_holder = WeakListVisitor<T>::WeakNextHolder(tail);
53 : int slot_offset = WeakListVisitor<T>::WeakNextOffset();
54 : ObjectSlot slot = slot_holder.RawField(slot_offset);
55 : MarkCompactCollector::RecordSlot(slot_holder, slot,
56 : HeapObject::cast(retained));
57 : }
58 : }
59 : // Retained object is new tail.
60 : DCHECK(!retained->IsUndefined(heap->isolate()));
61 : candidate = T::cast(retained);
62 : tail = candidate;
63 :
64 : // tail is a live object, visit it.
65 138912 : WeakListVisitor<T>::VisitLiveObject(heap, tail, retainer);
66 :
67 : } else {
68 4551 : WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
69 : }
70 : }
71 :
72 : // Terminate the list if there is one or more elements.
73 315638 : if (!tail.is_null()) WeakListVisitor<T>::SetWeakNext(tail, undefined);
74 315638 : return head;
75 : }
76 :
77 : template <class T>
78 9102 : static void ClearWeakList(Heap* heap, Object list) {
79 : Object undefined = ReadOnlyRoots(heap).undefined_value();
80 30388 : while (list != undefined) {
81 : T candidate = T::cast(list);
82 : list = WeakListVisitor<T>::WeakNext(candidate);
83 10643 : WeakListVisitor<T>::SetWeakNext(candidate, undefined);
84 : }
85 9102 : }
86 :
87 : template <>
88 : struct WeakListVisitor<Code> {
89 184806 : static void SetWeakNext(Code code, Object next) {
90 369612 : code->code_data_container()->set_next_code_link(next,
91 184806 : UPDATE_WEAK_WRITE_BARRIER);
92 184806 : }
93 :
94 : static Object WeakNext(Code code) {
95 : return code->code_data_container()->next_code_link();
96 : }
97 :
98 : static HeapObject WeakNextHolder(Code code) {
99 : return code->code_data_container();
100 : }
101 :
102 : static int WeakNextOffset() { return CodeDataContainer::kNextCodeLinkOffset; }
103 :
104 : static void VisitLiveObject(Heap*, Code, WeakObjectRetainer*) {}
105 :
106 : static void VisitPhantomObject(Heap* heap, Code code) {
107 : // Even though the code is dying, its code_data_container can still be
108 : // alive. Clear the next_code_link slot to avoid a dangling pointer.
109 80263 : SetWeakNext(code, ReadOnlyRoots(heap).undefined_value());
110 : }
111 : };
112 :
113 :
114 : template <>
115 : struct WeakListVisitor<Context> {
116 138912 : static void SetWeakNext(Context context, Object next) {
117 : context->set(Context::NEXT_CONTEXT_LINK, next, UPDATE_WEAK_WRITE_BARRIER);
118 138912 : }
119 :
120 : static Object WeakNext(Context context) {
121 143463 : return context->next_context_link();
122 : }
123 :
124 : static HeapObject WeakNextHolder(Context context) { return context; }
125 :
126 : static int WeakNextOffset() {
127 : return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK);
128 : }
129 :
130 138912 : static void VisitLiveObject(Heap* heap, Context context,
131 : WeakObjectRetainer* retainer) {
132 138912 : if (heap->gc_state() == Heap::MARK_COMPACT) {
133 : // Record the slots of the weak entries in the native context.
134 225144 : for (int idx = Context::FIRST_WEAK_SLOT;
135 300192 : idx < Context::NATIVE_CONTEXT_SLOTS; ++idx) {
136 : ObjectSlot slot = context->RawField(Context::OffsetOfElementAt(idx));
137 : MarkCompactCollector::RecordSlot(context, slot,
138 : HeapObject::cast(*slot));
139 : }
140 : // Code objects are always allocated in Code space, we do not have to
141 : // visit them during scavenges.
142 75048 : DoWeakList<Code>(heap, context, retainer, Context::OPTIMIZED_CODE_LIST);
143 75048 : DoWeakList<Code>(heap, context, retainer, Context::DEOPTIMIZED_CODE_LIST);
144 : }
145 138912 : }
146 :
147 : template <class T>
148 150096 : static void DoWeakList(Heap* heap, Context context,
149 : WeakObjectRetainer* retainer, int index) {
150 : // Visit the weak list, removing dead intermediate elements.
151 150096 : Object list_head = VisitWeakList<T>(heap, context->get(index), retainer);
152 :
153 : // Update the list head.
154 : context->set(index, list_head, UPDATE_WRITE_BARRIER);
155 :
156 150096 : if (MustRecordSlots(heap)) {
157 : // Record the updated slot if necessary.
158 : ObjectSlot head_slot = context->RawField(FixedArray::SizeFor(index));
159 : heap->mark_compact_collector()->RecordSlot(context, head_slot,
160 : HeapObject::cast(list_head));
161 : }
162 150096 : }
163 :
164 4551 : static void VisitPhantomObject(Heap* heap, Context context) {
165 4551 : ClearWeakList<Code>(heap, context->get(Context::OPTIMIZED_CODE_LIST));
166 4551 : ClearWeakList<Code>(heap, context->get(Context::DEOPTIMIZED_CODE_LIST));
167 4551 : }
168 : };
169 :
170 :
171 : template <>
172 : struct WeakListVisitor<AllocationSite> {
173 : static void SetWeakNext(AllocationSite obj, Object next) {
174 1557988 : obj->set_weak_next(next, UPDATE_WEAK_WRITE_BARRIER);
175 : }
176 :
177 : static Object WeakNext(AllocationSite obj) { return obj->weak_next(); }
178 :
179 : static HeapObject WeakNextHolder(AllocationSite obj) { return obj; }
180 :
181 : static int WeakNextOffset() { return AllocationSite::kWeakNextOffset; }
182 :
183 : static void VisitLiveObject(Heap*, AllocationSite, WeakObjectRetainer*) {}
184 :
185 : static void VisitPhantomObject(Heap*, AllocationSite) {}
186 : };
187 :
188 : template Object VisitWeakList<Context>(Heap* heap, Object list,
189 : WeakObjectRetainer* retainer);
190 :
191 : template Object VisitWeakList<AllocationSite>(Heap* heap, Object list,
192 : WeakObjectRetainer* retainer);
193 : } // namespace internal
194 121996 : } // namespace v8
|