Line data Source code
1 : // Copyright 2018 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 : #ifndef V8_OBJECTS_JS_WEAK_REFS_INL_H_
6 : #define V8_OBJECTS_JS_WEAK_REFS_INL_H_
7 :
8 : #include "src/objects/js-weak-refs.h"
9 :
10 : #include "src/api-inl.h"
11 : #include "src/heap/heap-write-barrier-inl.h"
12 : #include "src/objects/microtask-inl.h"
13 : #include "src/objects/smi-inl.h"
14 :
15 : // Has to be the last include (doesn't have include guards):
16 : #include "src/objects/object-macros.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 3300 : OBJECT_CONSTRUCTORS_IMPL(JSWeakCell, JSObject)
22 912 : OBJECT_CONSTRUCTORS_IMPL(JSWeakRef, JSObject)
23 4590 : OBJECT_CONSTRUCTORS_IMPL(JSWeakFactory, JSObject)
24 1026 : OBJECT_CONSTRUCTORS_IMPL(JSWeakFactoryCleanupIterator, JSObject)
25 396 : OBJECT_CONSTRUCTORS_IMPL(WeakFactoryCleanupJobTask, Microtask)
26 :
27 2304 : ACCESSORS(JSWeakFactory, native_context, NativeContext, kNativeContextOffset)
28 2250 : ACCESSORS(JSWeakFactory, cleanup, Object, kCleanupOffset)
29 7329 : ACCESSORS(JSWeakFactory, active_cells, Object, kActiveCellsOffset)
30 8342 : ACCESSORS(JSWeakFactory, cleared_cells, Object, kClearedCellsOffset)
31 2034 : SMI_ACCESSORS(JSWeakFactory, flags, kFlagsOffset)
32 2574 : ACCESSORS(JSWeakFactory, next, Object, kNextOffset)
33 2295 : CAST_ACCESSOR(JSWeakFactory)
34 :
35 5518 : ACCESSORS(JSWeakCell, factory, Object, kFactoryOffset)
36 7747 : ACCESSORS(JSWeakCell, target, Object, kTargetOffset)
37 2972 : ACCESSORS(JSWeakCell, holdings, Object, kHoldingsOffset)
38 11557 : ACCESSORS(JSWeakCell, next, Object, kNextOffset)
39 5521 : ACCESSORS(JSWeakCell, prev, Object, kPrevOffset)
40 1650 : CAST_ACCESSOR(JSWeakCell)
41 :
42 456 : CAST_ACCESSOR(JSWeakRef)
43 3854 : ACCESSORS(JSWeakRef, target, Object, kTargetOffset)
44 :
45 1899 : ACCESSORS(JSWeakFactoryCleanupIterator, factory, JSWeakFactory, kFactoryOffset)
46 513 : CAST_ACCESSOR(JSWeakFactoryCleanupIterator)
47 :
48 990 : ACCESSORS(WeakFactoryCleanupJobTask, factory, JSWeakFactory, kFactoryOffset)
49 198 : CAST_ACCESSOR(WeakFactoryCleanupJobTask)
50 :
51 454 : void JSWeakFactory::AddWeakCell(JSWeakCell weak_cell) {
52 454 : weak_cell->set_factory(*this);
53 454 : weak_cell->set_next(active_cells());
54 908 : if (active_cells()->IsJSWeakCell()) {
55 162 : JSWeakCell::cast(active_cells())->set_prev(weak_cell);
56 : }
57 454 : set_active_cells(weak_cell);
58 454 : }
59 :
60 358 : bool JSWeakFactory::NeedsCleanup() const {
61 716 : return cleared_cells()->IsJSWeakCell();
62 : }
63 :
64 252 : bool JSWeakFactory::scheduled_for_cleanup() const {
65 504 : return ScheduledForCleanupField::decode(flags());
66 : }
67 :
68 396 : void JSWeakFactory::set_scheduled_for_cleanup(bool scheduled_for_cleanup) {
69 792 : set_flags(ScheduledForCleanupField::update(flags(), scheduled_for_cleanup));
70 396 : }
71 :
72 209 : JSWeakCell JSWeakFactory::PopClearedCell(Isolate* isolate) {
73 418 : JSWeakCell weak_cell = JSWeakCell::cast(cleared_cells());
74 : DCHECK(weak_cell->prev()->IsUndefined(isolate));
75 209 : set_cleared_cells(weak_cell->next());
76 209 : weak_cell->set_next(ReadOnlyRoots(isolate).undefined_value());
77 :
78 418 : if (cleared_cells()->IsJSWeakCell()) {
79 136 : JSWeakCell cleared_cells_head = JSWeakCell::cast(cleared_cells());
80 : DCHECK_EQ(cleared_cells_head->prev(), weak_cell);
81 68 : cleared_cells_head->set_prev(ReadOnlyRoots(isolate).undefined_value());
82 : } else {
83 : DCHECK(cleared_cells()->IsUndefined(isolate));
84 : }
85 209 : return weak_cell;
86 : }
87 :
88 307 : void JSWeakCell::Nullify(
89 : Isolate* isolate,
90 : std::function<void(HeapObject object, ObjectSlot slot, Object target)>
91 : gc_notify_updated_slot) {
92 : DCHECK(target()->IsJSReceiver());
93 307 : set_target(ReadOnlyRoots(isolate).undefined_value());
94 :
95 614 : JSWeakFactory weak_factory = JSWeakFactory::cast(factory());
96 : // Remove from the JSWeakCell from the "active_cells" list of its
97 : // JSWeakFactory and insert it into the "cleared" list.
98 614 : if (prev()->IsJSWeakCell()) {
99 : DCHECK_NE(weak_factory->active_cells(), *this);
100 112 : JSWeakCell prev_cell = JSWeakCell::cast(prev());
101 56 : prev_cell->set_next(next());
102 : gc_notify_updated_slot(prev_cell,
103 112 : prev_cell.RawField(JSWeakCell::kNextOffset), next());
104 : } else {
105 : DCHECK_EQ(weak_factory->active_cells(), *this);
106 251 : weak_factory->set_active_cells(next());
107 : gc_notify_updated_slot(
108 : weak_factory, weak_factory.RawField(JSWeakFactory::kActiveCellsOffset),
109 502 : next());
110 : }
111 614 : if (next()->IsJSWeakCell()) {
112 32 : JSWeakCell next_cell = JSWeakCell::cast(next());
113 16 : next_cell->set_prev(prev());
114 : gc_notify_updated_slot(next_cell,
115 32 : next_cell.RawField(JSWeakCell::kPrevOffset), prev());
116 : }
117 :
118 307 : set_prev(ReadOnlyRoots(isolate).undefined_value());
119 307 : Object cleared_head = weak_factory->cleared_cells();
120 307 : if (cleared_head->IsJSWeakCell()) {
121 88 : JSWeakCell cleared_head_cell = JSWeakCell::cast(cleared_head);
122 88 : cleared_head_cell->set_prev(*this);
123 : gc_notify_updated_slot(cleared_head_cell,
124 : cleared_head_cell.RawField(JSWeakCell::kPrevOffset),
125 88 : *this);
126 : }
127 307 : set_next(weak_factory->cleared_cells());
128 614 : gc_notify_updated_slot(*this, RawField(JSWeakCell::kNextOffset), next());
129 307 : weak_factory->set_cleared_cells(*this);
130 : gc_notify_updated_slot(
131 : weak_factory, weak_factory.RawField(JSWeakFactory::kClearedCellsOffset),
132 307 : *this);
133 307 : }
134 :
135 153 : void JSWeakCell::Clear(Isolate* isolate) {
136 : // Unlink the JSWeakCell from the list it's in (if any). The JSWeakCell can be
137 : // in its JSWeakFactory's active_cells list, cleared_cells list or neither (if
138 : // it has been already taken out).
139 :
140 : DCHECK(target()->IsUndefined() || target()->IsJSReceiver());
141 153 : set_target(ReadOnlyRoots(isolate).undefined_value());
142 :
143 306 : if (factory()->IsJSWeakFactory()) {
144 278 : JSWeakFactory weak_factory = JSWeakFactory::cast(factory());
145 278 : if (weak_factory->active_cells() == *this) {
146 : DCHECK(!prev()->IsJSWeakCell());
147 51 : weak_factory->set_active_cells(next());
148 176 : } else if (weak_factory->cleared_cells() == *this) {
149 : DCHECK(!prev()->IsJSWeakCell());
150 46 : weak_factory->set_cleared_cells(next());
151 84 : } else if (prev()->IsJSWeakCell()) {
152 20 : JSWeakCell prev_cell = JSWeakCell::cast(prev());
153 10 : prev_cell->set_next(next());
154 : }
155 278 : if (next()->IsJSWeakCell()) {
156 40 : JSWeakCell next_cell = JSWeakCell::cast(next());
157 20 : next_cell->set_prev(prev());
158 : }
159 139 : set_prev(ReadOnlyRoots(isolate).undefined_value());
160 139 : set_next(ReadOnlyRoots(isolate).undefined_value());
161 :
162 139 : set_holdings(ReadOnlyRoots(isolate).undefined_value());
163 139 : set_factory(ReadOnlyRoots(isolate).undefined_value());
164 : } else {
165 : // Already cleared.
166 : DCHECK(next()->IsUndefined(isolate));
167 : DCHECK(prev()->IsUndefined(isolate));
168 : DCHECK(holdings()->IsUndefined(isolate));
169 : DCHECK(factory()->IsUndefined(isolate));
170 : }
171 153 : }
172 :
173 : } // namespace internal
174 : } // namespace v8
175 :
176 : #include "src/objects/object-macros-undef.h"
177 :
178 : #endif // V8_OBJECTS_JS_WEAK_REFS_INL_H_
|