• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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/weak-object-worklists.h"
6 
7 #include "src/heap/heap-inl.h"
8 #include "src/heap/heap.h"
9 #include "src/objects/hash-table.h"
10 #include "src/objects/heap-object.h"
11 #include "src/objects/js-function.h"
12 #include "src/objects/js-weak-refs-inl.h"
13 #include "src/objects/js-weak-refs.h"
14 #include "src/objects/shared-function-info.h"
15 #include "src/objects/transitions.h"
16 
17 namespace v8 {
18 
19 namespace internal {
20 
Local(WeakObjects * weak_objects)21 WeakObjects::Local::Local(WeakObjects* weak_objects)
22     : WeakObjects::UnusedBase()
23 #define INIT_LOCAL_WORKLIST(_, name, __) , name##_local(&weak_objects->name)
24           WEAK_OBJECT_WORKLISTS(INIT_LOCAL_WORKLIST)
25 #undef INIT_LOCAL_WORKLIST
26 {
27 }
28 
Publish()29 void WeakObjects::Local::Publish() {
30 #define INVOKE_PUBLISH(_, name, __) name##_local.Publish();
31   WEAK_OBJECT_WORKLISTS(INVOKE_PUBLISH)
32 #undef INVOKE_PUBLISH
33 }
34 
UpdateAfterScavenge()35 void WeakObjects::UpdateAfterScavenge() {
36 #define INVOKE_UPDATE(_, name, Name) Update##Name(name);
37   WEAK_OBJECT_WORKLISTS(INVOKE_UPDATE)
38 #undef INVOKE_UPDATE
39 }
40 
Clear()41 void WeakObjects::Clear() {
42 #define INVOKE_CLEAR(_, name, __) name.Clear();
43   WEAK_OBJECT_WORKLISTS(INVOKE_CLEAR)
44 #undef INVOKE_CLEAR
45 }
46 
47 // static
UpdateTransitionArrays(WeakObjectWorklist<TransitionArray> & transition_arrays)48 void WeakObjects::UpdateTransitionArrays(
49     WeakObjectWorklist<TransitionArray>& transition_arrays) {
50   DCHECK(!ContainsYoungObjects(transition_arrays));
51 }
52 
53 // static
UpdateEphemeronHashTables(WeakObjectWorklist<EphemeronHashTable> & ephemeron_hash_tables)54 void WeakObjects::UpdateEphemeronHashTables(
55     WeakObjectWorklist<EphemeronHashTable>& ephemeron_hash_tables) {
56   ephemeron_hash_tables.Update(
57       [](EphemeronHashTable slot_in, EphemeronHashTable* slot_out) -> bool {
58         EphemeronHashTable forwarded = ForwardingAddress(slot_in);
59 
60         if (!forwarded.is_null()) {
61           *slot_out = forwarded;
62           return true;
63         }
64 
65         return false;
66       });
67 }
68 
69 namespace {
EphemeronUpdater(Ephemeron slot_in,Ephemeron * slot_out)70 bool EphemeronUpdater(Ephemeron slot_in, Ephemeron* slot_out) {
71   HeapObject key = slot_in.key;
72   HeapObject value = slot_in.value;
73   HeapObject forwarded_key = ForwardingAddress(key);
74   HeapObject forwarded_value = ForwardingAddress(value);
75 
76   if (!forwarded_key.is_null() && !forwarded_value.is_null()) {
77     *slot_out = Ephemeron{forwarded_key, forwarded_value};
78     return true;
79   }
80 
81   return false;
82 }
83 }  // anonymous namespace
84 
85 // static
UpdateCurrentEphemerons(WeakObjectWorklist<Ephemeron> & current_ephemerons)86 void WeakObjects::UpdateCurrentEphemerons(
87     WeakObjectWorklist<Ephemeron>& current_ephemerons) {
88   current_ephemerons.Update(EphemeronUpdater);
89 }
90 
91 // static
UpdateNextEphemerons(WeakObjectWorklist<Ephemeron> & next_ephemerons)92 void WeakObjects::UpdateNextEphemerons(
93     WeakObjectWorklist<Ephemeron>& next_ephemerons) {
94   next_ephemerons.Update(EphemeronUpdater);
95 }
96 
97 // static
UpdateDiscoveredEphemerons(WeakObjectWorklist<Ephemeron> & discovered_ephemerons)98 void WeakObjects::UpdateDiscoveredEphemerons(
99     WeakObjectWorklist<Ephemeron>& discovered_ephemerons) {
100   discovered_ephemerons.Update(EphemeronUpdater);
101 }
102 
103 // static
UpdateWeakReferences(WeakObjectWorklist<HeapObjectAndSlot> & weak_references)104 void WeakObjects::UpdateWeakReferences(
105     WeakObjectWorklist<HeapObjectAndSlot>& weak_references) {
106   weak_references.Update(
107       [](HeapObjectAndSlot slot_in, HeapObjectAndSlot* slot_out) -> bool {
108         HeapObject heap_obj = slot_in.first;
109         HeapObject forwarded = ForwardingAddress(heap_obj);
110 
111         if (!forwarded.is_null()) {
112           ptrdiff_t distance_to_slot =
113               slot_in.second.address() - slot_in.first.ptr();
114           Address new_slot = forwarded.ptr() + distance_to_slot;
115           slot_out->first = forwarded;
116           slot_out->second = HeapObjectSlot(new_slot);
117           return true;
118         }
119 
120         return false;
121       });
122 }
123 
124 // static
UpdateWeakObjectsInCode(WeakObjectWorklist<HeapObjectAndCode> & weak_objects_in_code)125 void WeakObjects::UpdateWeakObjectsInCode(
126     WeakObjectWorklist<HeapObjectAndCode>& weak_objects_in_code) {
127   weak_objects_in_code.Update(
128       [](HeapObjectAndCode slot_in, HeapObjectAndCode* slot_out) -> bool {
129         HeapObject heap_obj = slot_in.first;
130         HeapObject forwarded = ForwardingAddress(heap_obj);
131 
132         if (!forwarded.is_null()) {
133           slot_out->first = forwarded;
134           slot_out->second = slot_in.second;
135           return true;
136         }
137 
138         return false;
139       });
140 }
141 
142 // static
UpdateJSWeakRefs(WeakObjectWorklist<JSWeakRef> & js_weak_refs)143 void WeakObjects::UpdateJSWeakRefs(
144     WeakObjectWorklist<JSWeakRef>& js_weak_refs) {
145   js_weak_refs.Update(
146       [](JSWeakRef js_weak_ref_in, JSWeakRef* js_weak_ref_out) -> bool {
147         JSWeakRef forwarded = ForwardingAddress(js_weak_ref_in);
148 
149         if (!forwarded.is_null()) {
150           *js_weak_ref_out = forwarded;
151           return true;
152         }
153 
154         return false;
155       });
156 }
157 
158 // static
UpdateWeakCells(WeakObjectWorklist<WeakCell> & weak_cells)159 void WeakObjects::UpdateWeakCells(WeakObjectWorklist<WeakCell>& weak_cells) {
160   // TODO(syg, marja): Support WeakCells in the young generation.
161   DCHECK(!ContainsYoungObjects(weak_cells));
162 }
163 
164 // static
UpdateCodeFlushingCandidates(WeakObjectWorklist<SharedFunctionInfo> & code_flushing_candidates)165 void WeakObjects::UpdateCodeFlushingCandidates(
166     WeakObjectWorklist<SharedFunctionInfo>& code_flushing_candidates) {
167   DCHECK(!ContainsYoungObjects(code_flushing_candidates));
168 }
169 
170 // static
UpdateFlushedJSFunctions(WeakObjectWorklist<JSFunction> & flushed_js_functions)171 void WeakObjects::UpdateFlushedJSFunctions(
172     WeakObjectWorklist<JSFunction>& flushed_js_functions) {
173   flushed_js_functions.Update(
174       [](JSFunction slot_in, JSFunction* slot_out) -> bool {
175         JSFunction forwarded = ForwardingAddress(slot_in);
176 
177         if (!forwarded.is_null()) {
178           *slot_out = forwarded;
179           return true;
180         }
181 
182         return false;
183       });
184 }
185 
186 // static
UpdateBaselineFlushingCandidates(WeakObjectWorklist<JSFunction> & baseline_flush_candidates)187 void WeakObjects::UpdateBaselineFlushingCandidates(
188     WeakObjectWorklist<JSFunction>& baseline_flush_candidates) {
189   baseline_flush_candidates.Update(
190       [](JSFunction slot_in, JSFunction* slot_out) -> bool {
191         JSFunction forwarded = ForwardingAddress(slot_in);
192 
193         if (!forwarded.is_null()) {
194           *slot_out = forwarded;
195           return true;
196         }
197 
198         return false;
199       });
200 }
201 
202 #ifdef DEBUG
203 // static
204 template <typename Type>
ContainsYoungObjects(WeakObjectWorklist<Type> & worklist)205 bool WeakObjects::ContainsYoungObjects(WeakObjectWorklist<Type>& worklist) {
206   bool result = false;
207   worklist.Iterate([&result](Type candidate) {
208     if (Heap::InYoungGeneration(candidate)) {
209       result = true;
210     }
211   });
212   return result;
213 }
214 #endif
215 
216 }  // namespace internal
217 }  // namespace v8
218