V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
objects-visiting.cc
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  return heap->gc_state() == Heap::MARK_COMPACT &&
20  heap->mark_compact_collector()->is_compacting();
21 }
22 
23 
24 template <class T>
26 
27 template <class T>
28 Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) {
29  Object* undefined = ReadOnlyRoots(heap).undefined_value();
30  Object* head = undefined;
31  T* tail = nullptr;
32  bool record_slots = MustRecordSlots(heap);
33 
34  while (list != undefined) {
35  // Check whether to keep the candidate in the list.
36  T* candidate = reinterpret_cast<T*>(list);
37 
38  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  if (retained != nullptr) {
44  if (head == undefined) {
45  // First element in the list.
46  head = retained;
47  } else {
48  // Subsequent elements in the list.
49  DCHECK_NOT_NULL(tail);
50  WeakListVisitor<T>::SetWeakNext(tail, retained);
51  if (record_slots) {
53  int slot_offset = WeakListVisitor<T>::WeakNextOffset();
54  ObjectSlot slot = HeapObject::RawField(slot_holder, 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 = reinterpret_cast<T*>(retained);
62  tail = candidate;
63 
64  // tail is a live object, visit it.
65  WeakListVisitor<T>::VisitLiveObject(heap, tail, retainer);
66 
67  } else {
68  WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
69  }
70  }
71 
72  // Terminate the list if there is one or more elements.
73  if (tail != nullptr) WeakListVisitor<T>::SetWeakNext(tail, undefined);
74  return head;
75 }
76 
77 // TODO(3770): Replacement for the above, temporarily separate to allow
78 // incremental transition. Assumes that T derives from ObjectPtr.
79 template <class T>
80 Object* VisitWeakList2(Heap* heap, Object* list, WeakObjectRetainer* retainer) {
81  Object* undefined = ReadOnlyRoots(heap).undefined_value();
82  Object* head = undefined;
83  T tail;
84  bool record_slots = MustRecordSlots(heap);
85 
86  while (list != undefined) {
87  // Check whether to keep the candidate in the list.
88  T candidate = T::cast(list);
89 
90  Object* retained = retainer->RetainAs(list);
91 
92  // Move to the next element before the WeakNext is cleared.
93  list = WeakListVisitor<T>::WeakNext(candidate);
94 
95  if (retained != nullptr) {
96  if (head == undefined) {
97  // First element in the list.
98  head = retained;
99  } else {
100  // Subsequent elements in the list.
101  DCHECK(!tail.is_null());
102  WeakListVisitor<T>::SetWeakNext(tail, retained);
103  if (record_slots) {
104  HeapObject* slot_holder = WeakListVisitor<T>::WeakNextHolder(tail);
105  int slot_offset = WeakListVisitor<T>::WeakNextOffset();
106  ObjectSlot slot = HeapObject::RawField(slot_holder, slot_offset);
107  MarkCompactCollector::RecordSlot(slot_holder, slot,
108  HeapObject::cast(retained));
109  }
110  }
111  // Retained object is new tail.
112  DCHECK(!retained->IsUndefined(heap->isolate()));
113  candidate = T::cast(retained);
114  tail = candidate;
115 
116  // tail is a live object, visit it.
117  WeakListVisitor<T>::VisitLiveObject(heap, tail, retainer);
118 
119  } else {
120  WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
121  }
122  }
123 
124  // Terminate the list if there is one or more elements.
125  if (!tail.is_null()) WeakListVisitor<T>::SetWeakNext(tail, undefined);
126  return head;
127 }
128 
129 template <class T>
130 static void ClearWeakList(Heap* heap, Object* list) {
131  Object* undefined = ReadOnlyRoots(heap).undefined_value();
132  while (list != undefined) {
133  T candidate = T::cast(list);
134  list = WeakListVisitor<T>::WeakNext(candidate);
135  WeakListVisitor<T>::SetWeakNext(candidate, undefined);
136  }
137 }
138 
139 template <>
141  static void SetWeakNext(Code code, Object* next) {
142  code->code_data_container()->set_next_code_link(next,
143  UPDATE_WEAK_WRITE_BARRIER);
144  }
145 
146  static Object* WeakNext(Code code) {
147  return code->code_data_container()->next_code_link();
148  }
149 
150  static HeapObject* WeakNextHolder(Code code) {
151  return code->code_data_container();
152  }
153 
154  static int WeakNextOffset() { return CodeDataContainer::kNextCodeLinkOffset; }
155 
156  static void VisitLiveObject(Heap*, Code, WeakObjectRetainer*) {}
157 
158  static void VisitPhantomObject(Heap* heap, Code code) {
159  // Even though the code is dying, its code_data_container can still be
160  // alive. Clear the next_code_link slot to avoid a dangling pointer.
161  SetWeakNext(code, ReadOnlyRoots(heap).undefined_value());
162  }
163 };
164 
165 
166 template <>
168  static void SetWeakNext(Context context, Object* next) {
169  context->set(Context::NEXT_CONTEXT_LINK, next, UPDATE_WEAK_WRITE_BARRIER);
170  }
171 
172  static Object* WeakNext(Context context) {
173  return context->next_context_link();
174  }
175 
176  static HeapObject* WeakNextHolder(Context context) { return context; }
177 
178  static int WeakNextOffset() {
179  return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK);
180  }
181 
182  static void VisitLiveObject(Heap* heap, Context context,
183  WeakObjectRetainer* retainer) {
184  if (heap->gc_state() == Heap::MARK_COMPACT) {
185  // Record the slots of the weak entries in the native context.
186  for (int idx = Context::FIRST_WEAK_SLOT;
187  idx < Context::NATIVE_CONTEXT_SLOTS; ++idx) {
188  ObjectSlot slot = context->RawField(Context::OffsetOfElementAt(idx));
189  MarkCompactCollector::RecordSlot(context, slot,
190  HeapObject::cast(*slot));
191  }
192  // Code objects are always allocated in Code space, we do not have to
193  // visit them during scavenges.
194  DoWeakList<Code>(heap, context, retainer, Context::OPTIMIZED_CODE_LIST);
195  DoWeakList<Code>(heap, context, retainer, Context::DEOPTIMIZED_CODE_LIST);
196  }
197  }
198 
199  template <class T>
200  static void DoWeakList(Heap* heap, Context context,
201  WeakObjectRetainer* retainer, int index) {
202  // Visit the weak list, removing dead intermediate elements.
203  Object* list_head = VisitWeakList2<T>(heap, context->get(index), retainer);
204 
205  // Update the list head.
206  context->set(index, list_head, UPDATE_WRITE_BARRIER);
207 
208  if (MustRecordSlots(heap)) {
209  // Record the updated slot if necessary.
210  ObjectSlot head_slot = context->RawField(FixedArray::SizeFor(index));
211  heap->mark_compact_collector()->RecordSlot(context, head_slot,
212  HeapObject::cast(list_head));
213  }
214  }
215 
216  static void VisitPhantomObject(Heap* heap, Context context) {
217  ClearWeakList<Code>(heap, context->get(Context::OPTIMIZED_CODE_LIST));
218  ClearWeakList<Code>(heap, context->get(Context::DEOPTIMIZED_CODE_LIST));
219  }
220 };
221 
222 
223 template <>
225  static void SetWeakNext(AllocationSite* obj, Object* next) {
226  obj->set_weak_next(next, UPDATE_WEAK_WRITE_BARRIER);
227  }
228 
229  static Object* WeakNext(AllocationSite* obj) { return obj->weak_next(); }
230 
231  static HeapObject* WeakNextHolder(AllocationSite* obj) { return obj; }
232 
233  static int WeakNextOffset() { return AllocationSite::kWeakNextOffset; }
234 
235  static void VisitLiveObject(Heap*, AllocationSite*, WeakObjectRetainer*) {}
236 
237  static void VisitPhantomObject(Heap*, AllocationSite*) {}
238 };
239 
240 template Object* VisitWeakList2<Context>(Heap* heap, Object* list,
241  WeakObjectRetainer* retainer);
242 
243 template Object* VisitWeakList<AllocationSite>(Heap* heap, Object* list,
244  WeakObjectRetainer* retainer);
245 } // namespace internal
246 } // namespace v8
Definition: libplatform.h:13