v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
js-weak-refs.cc
Go to the documentation of this file.
1// Copyright 2024 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
6
9
10namespace v8 {
11namespace internal {
12
14 Isolate* isolate, bool* key_map_may_need_shrink) {
16 Tagged<Undefined> undefined = ReadOnlyRoots(isolate).undefined_value();
17
18 Tagged<WeakCell> head = Cast<WeakCell>(cleared_cells());
19 DCHECK(IsUndefined(head->prev(), isolate));
20 Tagged<Union<Undefined, WeakCell>> tail = head->next();
21 head->set_next(undefined);
22 if (IsWeakCell(tail)) Cast<WeakCell>(tail)->set_prev(undefined);
23 set_cleared_cells(tail);
24
25 // If the WeakCell has an unregister token, remove the cell from the
26 // unregister token linked lists and and the unregister token from key_map.
27 // This doesn't shrink key_map, which is done manually after the cleanup loop.
28 if (!IsUndefined(head->unregister_token(), isolate)) {
30 *key_map_may_need_shrink = true;
31 }
32
33 return head;
34}
35
37 Isolate* isolate,
38 DirectHandle<JSFinalizationRegistry> finalization_registry) {
39 if (!IsUndefined(finalization_registry->key_map(), isolate)) {
41 handle(Cast<SimpleNumberDictionary>(finalization_registry->key_map()),
42 isolate);
43 key_map = SimpleNumberDictionary::Shrink(isolate, key_map);
44 finalization_registry->set_key_map(*key_map);
45 }
46}
47
48// ES#sec-cleanup-finalization-registry
49// static
51 Isolate* isolate,
52 DirectHandle<JSFinalizationRegistry> finalization_registry) {
53 // 1. Assert: finalizationRegistry has [[Cells]] and [[CleanupCallback]]
54 // internal slots.
55 // (By construction.)
56
57 // 2. Let callback be finalizationRegistry.[[CleanupCallback]].
58 DirectHandle<Object> callback(finalization_registry->cleanup(), isolate);
59
60 // 3. While finalizationRegistry.[[Cells]] contains a Record cell such that
61 // cell.[[WeakRefTarget]] is empty, an implementation may perform the
62 // following steps:
63 bool key_map_may_need_shrink = false;
64 while (finalization_registry->NeedsCleanup()) {
65 HandleScope scope(isolate);
66
67 // a. Choose any such cell.
68 // b. Remove cell from finalizationRegistry.[[Cells]].
69 DirectHandle<WeakCell> weak_cell(finalization_registry->PopClearedCell(
70 isolate, &key_map_may_need_shrink),
71 isolate);
72
73 // c. Perform ? HostCallJobCallback(callback, undefined,
74 // « cell.[[HeldValue]] »).
76 direct_handle(weak_cell->holdings(), isolate)};
77 if (Execution::Call(isolate, callback,
78 isolate->factory()->undefined_value(),
80 .is_null()) {
81 if (key_map_may_need_shrink) ShrinkKeyMap(isolate, finalization_registry);
82 return Nothing<bool>();
83 }
84 }
85
86 if (key_map_may_need_shrink) ShrinkKeyMap(isolate, finalization_registry);
87 return Just(true);
88}
89
91 Isolate* isolate, Tagged<WeakCell> weak_cell) {
93 DCHECK(!IsUndefined(weak_cell->unregister_token(), isolate));
94 Tagged<Undefined> undefined = ReadOnlyRoots(isolate).undefined_value();
95
96 // Remove weak_cell from the linked list of other WeakCells with the same
97 // unregister token and remove its unregister token from key_map if necessary
98 // without shrinking it. Since shrinking may allocate, it is performed by the
99 // caller after looping, or on exception.
100 if (IsUndefined(weak_cell->key_list_prev(), isolate)) {
102 Cast<SimpleNumberDictionary>(this->key_map());
103 Tagged<HeapObject> unregister_token = weak_cell->unregister_token();
104 uint32_t key = Smi::ToInt(Object::GetHash(unregister_token));
105 InternalIndex entry = key_map->FindEntry(isolate, key);
106 CHECK(entry.is_found());
107
108 if (IsUndefined(weak_cell->key_list_next(), isolate)) {
109 // weak_cell is the only one associated with its key; remove the key
110 // from the hash table.
111 key_map->ClearEntry(entry);
112 key_map->ElementRemoved();
113 } else {
114 // weak_cell is the list head for its key; we need to change the value
115 // of the key in the hash table.
116 Tagged<WeakCell> next = Cast<WeakCell>(weak_cell->key_list_next());
117 DCHECK_EQ(next->key_list_prev(), weak_cell);
118 next->set_key_list_prev(undefined);
119 key_map->ValueAtPut(entry, next);
120 }
121 } else {
122 // weak_cell is somewhere in the middle of its key list.
123 Tagged<WeakCell> prev = Cast<WeakCell>(weak_cell->key_list_prev());
124 prev->set_key_list_next(weak_cell->key_list_next());
125 if (!IsUndefined(weak_cell->key_list_next())) {
126 Tagged<WeakCell> next = Cast<WeakCell>(weak_cell->key_list_next());
127 next->set_key_list_prev(weak_cell->key_list_prev());
128 }
129 }
130
131 // weak_cell is now removed from the unregister token map, so clear its
132 // unregister token-related fields.
133 weak_cell->set_unregister_token(undefined);
134 weak_cell->set_key_list_prev(undefined);
135 weak_cell->set_key_list_next(undefined);
136}
137
138} // namespace internal
139} // namespace v8
uint32_t GetHash()
Definition api.cc:4282
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > Call(Isolate *isolate, DirectHandle< Object > callable, DirectHandle< Object > receiver, base::Vector< const DirectHandle< Object > > args)
Definition execution.cc:523
static void ShrinkKeyMap(Isolate *isolate, DirectHandle< JSFinalizationRegistry > finalization_registry)
V8_EXPORT_PRIVATE void RemoveCellFromUnregisterTokenMap(Isolate *isolate, Tagged< WeakCell > weak_cell)
V8_EXPORT_PRIVATE Tagged< WeakCell > PopClearedCell(Isolate *isolate, bool *key_map_may_need_shrink)
static Maybe< bool > Cleanup(Isolate *isolate, DirectHandle< JSFinalizationRegistry > finalization_registry)
static constexpr int ToInt(const Tagged< Object > object)
Definition smi.h:33
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
TNode< Object > callback
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Maybe< T > Nothing()
Definition v8-maybe.h:112
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485