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_H_
6 : #define V8_OBJECTS_JS_WEAK_REFS_H_
7 :
8 : #include "src/objects/js-objects.h"
9 : #include "src/objects/microtask.h"
10 :
11 : // Has to be the last include (doesn't have include guards):
12 : #include "src/objects/object-macros.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 : class NativeContext;
18 : class WeakCell;
19 :
20 : // FinalizationGroup object from the JS Weak Refs spec proposal:
21 : // https://github.com/tc39/proposal-weakrefs
22 : class JSFinalizationGroup : public JSObject {
23 : public:
24 : DECL_PRINTER(JSFinalizationGroup)
25 : DECL_VERIFIER(JSFinalizationGroup)
26 : DECL_CAST(JSFinalizationGroup)
27 :
28 : DECL_ACCESSORS(native_context, NativeContext)
29 : DECL_ACCESSORS(cleanup, Object)
30 :
31 : DECL_ACCESSORS(active_cells, Object)
32 : DECL_ACCESSORS(cleared_cells, Object)
33 : DECL_ACCESSORS(key_map, Object)
34 :
35 : // For storing a list of JSFinalizationGroup objects in NativeContext.
36 : DECL_ACCESSORS(next, Object)
37 :
38 : DECL_INT_ACCESSORS(flags)
39 :
40 : inline static void Register(Handle<JSFinalizationGroup> finalization_group,
41 : Handle<JSReceiver> target,
42 : Handle<Object> holdings, Handle<Object> key,
43 : Isolate* isolate);
44 : inline static void Unregister(Handle<JSFinalizationGroup> finalization_group,
45 : Handle<Object> key, Isolate* isolate);
46 :
47 : // Returns true if the cleared_cells list is non-empty.
48 : inline bool NeedsCleanup() const;
49 :
50 : inline bool scheduled_for_cleanup() const;
51 : inline void set_scheduled_for_cleanup(bool scheduled_for_cleanup);
52 :
53 : // Remove the first cleared WeakCell from the cleared_cells
54 : // list (assumes there is one) and return its holdings.
55 : inline static Object PopClearedCellHoldings(
56 : Handle<JSFinalizationGroup> finalization_group, Isolate* isolate);
57 :
58 : // Constructs an iterator for the WeakCells in the cleared_cells list and
59 : // calls the user's cleanup function.
60 : static void Cleanup(Handle<JSFinalizationGroup> finalization_group,
61 : Isolate* isolate);
62 :
63 : // Layout description.
64 : #define JS_FINALIZATION_GROUP_FIELDS(V) \
65 : V(kNativeContextOffset, kTaggedSize) \
66 : V(kCleanupOffset, kTaggedSize) \
67 : V(kActiveCellsOffset, kTaggedSize) \
68 : V(kClearedCellsOffset, kTaggedSize) \
69 : V(kKeyMapOffset, kTaggedSize) \
70 : V(kNextOffset, kTaggedSize) \
71 : V(kFlagsOffset, kTaggedSize) \
72 : /* Header size. */ \
73 : V(kSize, 0)
74 :
75 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
76 : JS_FINALIZATION_GROUP_FIELDS)
77 : #undef JS_FINALIZATION_GROUP_FIELDS
78 :
79 : // Bitfields in flags.
80 : class ScheduledForCleanupField : public BitField<bool, 0, 1> {};
81 :
82 207 : OBJECT_CONSTRUCTORS(JSFinalizationGroup, JSObject);
83 : };
84 :
85 : // Internal object for storing weak references in JSFinalizationGroup.
86 : class WeakCell : public HeapObject {
87 : public:
88 : DECL_PRINTER(WeakCell)
89 : DECL_VERIFIER(WeakCell)
90 : DECL_CAST(WeakCell)
91 :
92 : DECL_ACCESSORS(finalization_group, Object)
93 : DECL_ACCESSORS(target, HeapObject)
94 : DECL_ACCESSORS(holdings, Object)
95 :
96 : // For storing doubly linked lists of WeakCells in JSFinalizationGroup's
97 : // "active_cells" and "cleared_cells" lists.
98 : DECL_ACCESSORS(prev, Object)
99 : DECL_ACCESSORS(next, Object)
100 :
101 : // For storing doubly linked lists of WeakCells per key in
102 : // JSFinalizationGroup's key-based hashmap. WeakCell also needs to know its
103 : // key, so that we can remove the key from the key_map when we remove the last
104 : // WeakCell associated with it.
105 : DECL_ACCESSORS(key, Object)
106 : DECL_ACCESSORS(key_list_prev, Object)
107 : DECL_ACCESSORS(key_list_next, Object)
108 :
109 : // Layout description.
110 : #define WEAK_CELL_FIELDS(V) \
111 : V(kFinalizationGroupOffset, kTaggedSize) \
112 : V(kTargetOffset, kTaggedSize) \
113 : V(kHoldingsOffset, kTaggedSize) \
114 : V(kPrevOffset, kTaggedSize) \
115 : V(kNextOffset, kTaggedSize) \
116 : V(kKeyOffset, kTaggedSize) \
117 : V(kKeyListPrevOffset, kTaggedSize) \
118 : V(kKeyListNextOffset, kTaggedSize) \
119 : /* Header size. */ \
120 : V(kSize, 0)
121 :
122 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, WEAK_CELL_FIELDS)
123 : #undef WEAK_CELL_FIELDS
124 :
125 : class BodyDescriptor;
126 :
127 : // Nullify is called during GC and it modifies the pointers in WeakCell and
128 : // JSFinalizationGroup. Thus we need to tell the GC about the modified slots
129 : // via the gc_notify_updated_slot function. The normal write barrier is not
130 : // enough, since it's disabled before GC.
131 : inline void Nullify(
132 : Isolate* isolate,
133 : std::function<void(HeapObject object, ObjectSlot slot, Object target)>
134 : gc_notify_updated_slot);
135 :
136 : inline void RemoveFromFinalizationGroupCells(Isolate* isolate);
137 :
138 342 : OBJECT_CONSTRUCTORS(WeakCell, HeapObject);
139 : };
140 :
141 : class JSWeakRef : public JSObject {
142 : public:
143 : DECL_PRINTER(JSWeakRef)
144 : DECL_VERIFIER(JSWeakRef)
145 : DECL_CAST(JSWeakRef)
146 :
147 : DECL_ACCESSORS(target, HeapObject)
148 :
149 : // Layout description.
150 : #define JS_WEAK_REF_FIELDS(V) \
151 : V(kTargetOffset, kTaggedSize) \
152 : /* Header size. */ \
153 : V(kSize, 0)
154 :
155 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_WEAK_REF_FIELDS)
156 : #undef JS_WEAK_REF_FIELDS
157 :
158 : class BodyDescriptor;
159 :
160 157 : OBJECT_CONSTRUCTORS(JSWeakRef, JSObject);
161 : };
162 :
163 : class FinalizationGroupCleanupJobTask : public Microtask {
164 : public:
165 : DECL_ACCESSORS(finalization_group, JSFinalizationGroup)
166 :
167 : DECL_CAST(FinalizationGroupCleanupJobTask)
168 : DECL_VERIFIER(FinalizationGroupCleanupJobTask)
169 : DECL_PRINTER(FinalizationGroupCleanupJobTask)
170 :
171 : // Layout description.
172 : #define FINALIZATION_GROUP_CLEANUP_JOB_TASK_FIELDS(V) \
173 : V(kFinalizationGroupOffset, kTaggedSize) \
174 : /* Total size. */ \
175 : V(kSize, 0)
176 :
177 : DEFINE_FIELD_OFFSET_CONSTANTS(Microtask::kHeaderSize,
178 : FINALIZATION_GROUP_CLEANUP_JOB_TASK_FIELDS)
179 : #undef FINALIZATION_GROUP_CLEANUP_JOB_TASK_FIELDS
180 :
181 : OBJECT_CONSTRUCTORS(FinalizationGroupCleanupJobTask, Microtask);
182 : };
183 :
184 : class JSFinalizationGroupCleanupIterator : public JSObject {
185 : public:
186 : DECL_PRINTER(JSFinalizationGroupCleanupIterator)
187 : DECL_VERIFIER(JSFinalizationGroupCleanupIterator)
188 : DECL_CAST(JSFinalizationGroupCleanupIterator)
189 :
190 : DECL_ACCESSORS(finalization_group, JSFinalizationGroup)
191 :
192 : // Layout description.
193 : #define JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_FIELDS(V) \
194 : V(kFinalizationGroupOffset, kTaggedSize) \
195 : /* Header size. */ \
196 : V(kSize, 0)
197 :
198 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
199 : JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_FIELDS)
200 : #undef JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_FIELDS
201 :
202 : OBJECT_CONSTRUCTORS(JSFinalizationGroupCleanupIterator, JSObject);
203 : };
204 :
205 : } // namespace internal
206 : } // namespace v8
207 :
208 : #include "src/objects/object-macros-undef.h"
209 :
210 : #endif // V8_OBJECTS_JS_WEAK_REFS_H_
|