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/heap/worklist.h"
10 #include "src/objects/hash-table.h"
11 #include "src/objects/heap-object.h"
12 #include "src/objects/js-function.h"
13 #include "src/objects/js-weak-refs-inl.h"
14 #include "src/objects/js-weak-refs.h"
15 #include "src/objects/shared-function-info.h"
16 #include "src/objects/transitions.h"
17
18 namespace v8 {
19
20 namespace internal {
21
UpdateAfterScavenge()22 void WeakObjects::UpdateAfterScavenge() {
23 #define INVOKE_UPDATE(_, name, Name) Update##Name(name);
24 WEAK_OBJECT_WORKLISTS(INVOKE_UPDATE)
25 #undef INVOKE_UPDATE
26 }
27
UpdateTransitionArrays(WeakObjectWorklist<TransitionArray> & transition_arrays)28 void WeakObjects::UpdateTransitionArrays(
29 WeakObjectWorklist<TransitionArray>& transition_arrays) {
30 DCHECK(!ContainsYoungObjects(transition_arrays));
31 }
32
UpdateEphemeronHashTables(WeakObjectWorklist<EphemeronHashTable> & ephemeron_hash_tables)33 void WeakObjects::UpdateEphemeronHashTables(
34 WeakObjectWorklist<EphemeronHashTable>& ephemeron_hash_tables) {
35 ephemeron_hash_tables.Update(
36 [](EphemeronHashTable slot_in, EphemeronHashTable* slot_out) -> bool {
37 EphemeronHashTable forwarded = ForwardingAddress(slot_in);
38
39 if (!forwarded.is_null()) {
40 *slot_out = forwarded;
41 return true;
42 }
43
44 return false;
45 });
46 }
47
48 namespace {
EphemeronUpdater(Ephemeron slot_in,Ephemeron * slot_out)49 bool EphemeronUpdater(Ephemeron slot_in, Ephemeron* slot_out) {
50 HeapObject key = slot_in.key;
51 HeapObject value = slot_in.value;
52 HeapObject forwarded_key = ForwardingAddress(key);
53 HeapObject forwarded_value = ForwardingAddress(value);
54
55 if (!forwarded_key.is_null() && !forwarded_value.is_null()) {
56 *slot_out = Ephemeron{forwarded_key, forwarded_value};
57 return true;
58 }
59
60 return false;
61 }
62 } // anonymous namespace
63
UpdateCurrentEphemerons(WeakObjectWorklist<Ephemeron> & current_ephemerons)64 void WeakObjects::UpdateCurrentEphemerons(
65 WeakObjectWorklist<Ephemeron>& current_ephemerons) {
66 current_ephemerons.Update(EphemeronUpdater);
67 }
68
UpdateNextEphemerons(WeakObjectWorklist<Ephemeron> & next_ephemerons)69 void WeakObjects::UpdateNextEphemerons(
70 WeakObjectWorklist<Ephemeron>& next_ephemerons) {
71 next_ephemerons.Update(EphemeronUpdater);
72 }
73
UpdateDiscoveredEphemerons(WeakObjectWorklist<Ephemeron> & discovered_ephemerons)74 void WeakObjects::UpdateDiscoveredEphemerons(
75 WeakObjectWorklist<Ephemeron>& discovered_ephemerons) {
76 discovered_ephemerons.Update(EphemeronUpdater);
77 }
78
UpdateWeakReferences(WeakObjectWorklist<HeapObjectAndSlot> & weak_references)79 void WeakObjects::UpdateWeakReferences(
80 WeakObjectWorklist<HeapObjectAndSlot>& weak_references) {
81 weak_references.Update(
82 [](HeapObjectAndSlot slot_in, HeapObjectAndSlot* slot_out) -> bool {
83 HeapObject heap_obj = slot_in.first;
84 HeapObject forwarded = ForwardingAddress(heap_obj);
85
86 if (!forwarded.is_null()) {
87 ptrdiff_t distance_to_slot =
88 slot_in.second.address() - slot_in.first.ptr();
89 Address new_slot = forwarded.ptr() + distance_to_slot;
90 slot_out->first = forwarded;
91 slot_out->second = HeapObjectSlot(new_slot);
92 return true;
93 }
94
95 return false;
96 });
97 }
98
UpdateWeakObjectsInCode(WeakObjectWorklist<HeapObjectAndCode> & weak_objects_in_code)99 void WeakObjects::UpdateWeakObjectsInCode(
100 WeakObjectWorklist<HeapObjectAndCode>& weak_objects_in_code) {
101 weak_objects_in_code.Update(
102 [](HeapObjectAndCode slot_in, HeapObjectAndCode* slot_out) -> bool {
103 HeapObject heap_obj = slot_in.first;
104 HeapObject forwarded = ForwardingAddress(heap_obj);
105
106 if (!forwarded.is_null()) {
107 slot_out->first = forwarded;
108 slot_out->second = slot_in.second;
109 return true;
110 }
111
112 return false;
113 });
114 }
115
UpdateJSWeakRefs(WeakObjectWorklist<JSWeakRef> & js_weak_refs)116 void WeakObjects::UpdateJSWeakRefs(
117 WeakObjectWorklist<JSWeakRef>& js_weak_refs) {
118 if (FLAG_harmony_weak_refs) {
119 js_weak_refs.Update(
120 [](JSWeakRef js_weak_ref_in, JSWeakRef* js_weak_ref_out) -> bool {
121 JSWeakRef forwarded = ForwardingAddress(js_weak_ref_in);
122
123 if (!forwarded.is_null()) {
124 *js_weak_ref_out = forwarded;
125 return true;
126 }
127
128 return false;
129 });
130 }
131 }
132
UpdateWeakCells(WeakObjectWorklist<WeakCell> & weak_cells)133 void WeakObjects::UpdateWeakCells(WeakObjectWorklist<WeakCell>& weak_cells) {
134 // TODO(syg, marja): Support WeakCells in the young generation.
135 DCHECK(!ContainsYoungObjects(weak_cells));
136 }
137
UpdateBytecodeFlushingCandidates(WeakObjectWorklist<SharedFunctionInfo> & bytecode_flushing_candidates)138 void WeakObjects::UpdateBytecodeFlushingCandidates(
139 WeakObjectWorklist<SharedFunctionInfo>& bytecode_flushing_candidates) {
140 DCHECK(!ContainsYoungObjects(bytecode_flushing_candidates));
141 }
142
UpdateFlushedJSFunctions(WeakObjectWorklist<JSFunction> & flushed_js_functions)143 void WeakObjects::UpdateFlushedJSFunctions(
144 WeakObjectWorklist<JSFunction>& flushed_js_functions) {
145 flushed_js_functions.Update(
146 [](JSFunction slot_in, JSFunction* slot_out) -> bool {
147 JSFunction forwarded = ForwardingAddress(slot_in);
148
149 if (!forwarded.is_null()) {
150 *slot_out = forwarded;
151 return true;
152 }
153
154 return false;
155 });
156 }
157
158 #ifdef DEBUG
159 template <typename Type>
ContainsYoungObjects(WeakObjectWorklist<Type> & worklist)160 bool WeakObjects::ContainsYoungObjects(WeakObjectWorklist<Type>& worklist) {
161 bool result = false;
162 worklist.Iterate([&result](Type candidate) {
163 if (Heap::InYoungGeneration(candidate)) {
164 result = true;
165 }
166 });
167 return result;
168 }
169 #endif
170
171 } // namespace internal
172 } // namespace v8
173