summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/js-weak-refs.h
blob: b846c2e60857e26a79a33065c6700aefea8c84fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_JS_WEAK_REFS_H_
#define V8_OBJECTS_JS_WEAK_REFS_H_

#include "src/objects/js-objects.h"
#include "src/objects/microtask.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

class NativeContext;
class WeakCell;

// FinalizationGroup object from the JS Weak Refs spec proposal:
// https://github.com/tc39/proposal-weakrefs
class JSFinalizationGroup : public JSObject {
 public:
  DECL_PRINTER(JSFinalizationGroup)
  EXPORT_DECL_VERIFIER(JSFinalizationGroup)
  DECL_CAST(JSFinalizationGroup)

  DECL_ACCESSORS(native_context, NativeContext)
  DECL_ACCESSORS(cleanup, Object)

  DECL_ACCESSORS(active_cells, Object)
  DECL_ACCESSORS(cleared_cells, Object)
  DECL_ACCESSORS(key_map, Object)

  // For storing a list of JSFinalizationGroup objects in NativeContext.
  DECL_ACCESSORS(next, Object)

  DECL_INT_ACCESSORS(flags)

  inline static void Register(Handle<JSFinalizationGroup> finalization_group,
                              Handle<JSReceiver> target,
                              Handle<Object> holdings, Handle<Object> key,
                              Isolate* isolate);
  inline static void Unregister(Handle<JSFinalizationGroup> finalization_group,
                                Handle<Object> key, Isolate* isolate);

  // Returns true if the cleared_cells list is non-empty.
  inline bool NeedsCleanup() const;

  inline bool scheduled_for_cleanup() const;
  inline void set_scheduled_for_cleanup(bool scheduled_for_cleanup);

  // Remove the first cleared WeakCell from the cleared_cells
  // list (assumes there is one) and return its holdings.
  inline static Object PopClearedCellHoldings(
      Handle<JSFinalizationGroup> finalization_group, Isolate* isolate);

  // Constructs an iterator for the WeakCells in the cleared_cells list and
  // calls the user's cleanup function.
  static void Cleanup(Handle<JSFinalizationGroup> finalization_group,
                      Isolate* isolate);

// Layout description.
#define JS_FINALIZATION_GROUP_FIELDS(V) \
  V(kNativeContextOffset, kTaggedSize)  \
  V(kCleanupOffset, kTaggedSize)        \
  V(kActiveCellsOffset, kTaggedSize)    \
  V(kClearedCellsOffset, kTaggedSize)   \
  V(kKeyMapOffset, kTaggedSize)         \
  V(kNextOffset, kTaggedSize)           \
  V(kFlagsOffset, kTaggedSize)          \
  /* Header size. */                    \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
                                JS_FINALIZATION_GROUP_FIELDS)
#undef JS_FINALIZATION_GROUP_FIELDS

  // Bitfields in flags.
  class ScheduledForCleanupField : public BitField<bool, 0, 1> {};

  OBJECT_CONSTRUCTORS(JSFinalizationGroup, JSObject);
};

// Internal object for storing weak references in JSFinalizationGroup.
class WeakCell : public HeapObject {
 public:
  DECL_PRINTER(WeakCell)
  EXPORT_DECL_VERIFIER(WeakCell)
  DECL_CAST(WeakCell)

  DECL_ACCESSORS(finalization_group, Object)
  DECL_ACCESSORS(target, HeapObject)
  DECL_ACCESSORS(holdings, Object)

  // For storing doubly linked lists of WeakCells in JSFinalizationGroup's
  // "active_cells" and "cleared_cells" lists.
  DECL_ACCESSORS(prev, Object)
  DECL_ACCESSORS(next, Object)

  // For storing doubly linked lists of WeakCells per key in
  // JSFinalizationGroup's key-based hashmap. WeakCell also needs to know its
  // key, so that we can remove the key from the key_map when we remove the last
  // WeakCell associated with it.
  DECL_ACCESSORS(key, Object)
  DECL_ACCESSORS(key_list_prev, Object)
  DECL_ACCESSORS(key_list_next, Object)

// Layout description.
#define WEAK_CELL_FIELDS(V)                \
  V(kFinalizationGroupOffset, kTaggedSize) \
  V(kTargetOffset, kTaggedSize)            \
  V(kHoldingsOffset, kTaggedSize)          \
  V(kPrevOffset, kTaggedSize)              \
  V(kNextOffset, kTaggedSize)              \
  V(kKeyOffset, kTaggedSize)               \
  V(kKeyListPrevOffset, kTaggedSize)       \
  V(kKeyListNextOffset, kTaggedSize)       \
  /* Header size. */                       \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, WEAK_CELL_FIELDS)
#undef WEAK_CELL_FIELDS

  class BodyDescriptor;

  // Nullify is called during GC and it modifies the pointers in WeakCell and
  // JSFinalizationGroup. Thus we need to tell the GC about the modified slots
  // via the gc_notify_updated_slot function. The normal write barrier is not
  // enough, since it's disabled before GC.
  inline void Nullify(
      Isolate* isolate,
      std::function<void(HeapObject object, ObjectSlot slot, Object target)>
          gc_notify_updated_slot);

  inline void RemoveFromFinalizationGroupCells(Isolate* isolate);

  OBJECT_CONSTRUCTORS(WeakCell, HeapObject);
};

class JSWeakRef : public JSObject {
 public:
  DECL_PRINTER(JSWeakRef)
  EXPORT_DECL_VERIFIER(JSWeakRef)
  DECL_CAST(JSWeakRef)

  DECL_ACCESSORS(target, HeapObject)

// Layout description.
#define JS_WEAK_REF_FIELDS(V)   \
  V(kTargetOffset, kTaggedSize) \
  /* Header size. */            \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_WEAK_REF_FIELDS)
#undef JS_WEAK_REF_FIELDS

  class BodyDescriptor;

  OBJECT_CONSTRUCTORS(JSWeakRef, JSObject);
};

class FinalizationGroupCleanupJobTask : public Microtask {
 public:
  DECL_ACCESSORS(finalization_group, JSFinalizationGroup)

  DECL_CAST(FinalizationGroupCleanupJobTask)
  DECL_VERIFIER(FinalizationGroupCleanupJobTask)
  DECL_PRINTER(FinalizationGroupCleanupJobTask)

// Layout description.
#define FINALIZATION_GROUP_CLEANUP_JOB_TASK_FIELDS(V) \
  V(kFinalizationGroupOffset, kTaggedSize)            \
  /* Total size. */                                   \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(Microtask::kHeaderSize,
                                FINALIZATION_GROUP_CLEANUP_JOB_TASK_FIELDS)
#undef FINALIZATION_GROUP_CLEANUP_JOB_TASK_FIELDS

  OBJECT_CONSTRUCTORS(FinalizationGroupCleanupJobTask, Microtask);
};

class JSFinalizationGroupCleanupIterator : public JSObject {
 public:
  DECL_PRINTER(JSFinalizationGroupCleanupIterator)
  DECL_VERIFIER(JSFinalizationGroupCleanupIterator)
  DECL_CAST(JSFinalizationGroupCleanupIterator)

  DECL_ACCESSORS(finalization_group, JSFinalizationGroup)

// Layout description.
#define JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_FIELDS(V) \
  V(kFinalizationGroupOffset, kTaggedSize)               \
  /* Header size. */                                     \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
                                JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_FIELDS)
#undef JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_FIELDS

  OBJECT_CONSTRUCTORS(JSFinalizationGroupCleanupIterator, JSObject);
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_JS_WEAK_REFS_H_