v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
wasm-code-pointer-table.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::internal::wasm {
11
13
20
23
24std::vector<uint32_t> WasmCodePointerTable::FreelistToVector(
25 WasmCodePointerTable::FreelistHead freelist) {
26 DCHECK(!freelist.is_empty());
27 std::vector<uint32_t> entries(freelist.length());
28
29 uint32_t entry = freelist.next();
30 for (uint32_t i = 0; i < freelist.length(); i++) {
31 entries[i] = entry;
32 entry = at(entry).GetNextFreelistEntryIndex();
33 }
34
35 return entries;
36}
37
38WasmCodePointerTable::FreelistHead WasmCodePointerTable::VectorToFreelist(
39 std::vector<uint32_t> entries) {
40 if (entries.empty()) {
41 return FreelistHead();
42 }
43
44 FreelistHead new_freelist =
45 FreelistHead(entries[0], static_cast<uint32_t>(entries.size()));
46
47 WriteScope write_scope("Freelist write");
48 for (size_t i = 0; i < entries.size() - 1; i++) {
49 uint32_t entry = entries[i];
50 uint32_t next_entry = entries[i + 1];
51 at(entry).MakeFreelistEntry(next_entry);
52 }
53
54 return new_freelist;
55}
56
58 if (threshold < kEntriesPerSegment) {
59 // We need at least a whole empty segment if we want to sweep anything.
60 threshold = kEntriesPerSegment;
61 }
62
63 FreelistHead initial_head, empty_freelist;
64 do {
65 initial_head = ReadFreelistHead();
66 if (initial_head.length() < threshold) {
67 return;
68 }
69
70 // Try to unlink the freelist. If it fails, try again.
71 } while (
72 !freelist_head_.compare_exchange_strong(initial_head, empty_freelist));
73
74 // We unlinked the whole free list, so we have exclusive access to it at
75 // this point.
76
77 // Now search for empty segments (== all entries are freelist entries) and
78 // unlink them.
79
80 std::vector<uint32_t> freelist_entries = FreelistToVector(initial_head);
81 std::sort(freelist_entries.begin(), freelist_entries.end());
82
83 // The minimum threshold is kEntriesPerSegment.
84 DCHECK_GE(freelist_entries.size(), kEntriesPerSegment);
85
86 // We iterate over all freelist entries and copy them over to a new vector,
87 // while skipping and unmapping empty segments.
88 std::vector<uint32_t> new_freelist_entries;
89 for (size_t i = 0; i < freelist_entries.size(); i++) {
90 uint32_t entry = freelist_entries[i];
91 Segment segment = Segment::Containing(entry);
92
93 if (segment.first_entry() == entry &&
94 i + kEntriesPerSegment - 1 < freelist_entries.size()) {
95 uint32_t last_entry = freelist_entries[i + kEntriesPerSegment - 1];
96 if (segment.last_entry() == last_entry) {
97 // The whole segment is empty. Delete the segment and skip all
98 // entries;
99 FreeTableSegment(segment);
100 i += kEntriesPerSegment - 1;
101 continue;
102 }
103 }
104
105 new_freelist_entries.push_back(entry);
106 }
107
108 DCHECK_LE(new_freelist_entries.size(), freelist_entries.size());
109 DCHECK(IsAligned(freelist_entries.size() - new_freelist_entries.size(),
111
112 if (new_freelist_entries.empty()) {
113 return;
114 }
115
116 // Finally, add the new freelist back.
117
118 uint32_t last_element = new_freelist_entries.back();
119 FreelistHead new_freelist = VectorToFreelist(new_freelist_entries);
120
121 LinkFreelist(new_freelist, last_element);
122}
123
125 Address addr) {
127 auto it = native_function_map_.find(addr);
128 if (it != native_function_map_.end()) {
129 return it->second;
130 }
131
133 native_function_map_.insert({addr, handle});
134
135 return handle;
136}
137
139 Address address) {
140 return at(index.value()).GetEntrypointWithoutSignatureCheck() == address;
141}
142
150
151} // namespace v8::internal::wasm
V8_INLINE FreelistHead LinkFreelist(FreelistHead new_freelist, uint32_t last_element)
bool EntrypointEqualTo(WasmCodePointer index, Address address)
FreelistHead VectorToFreelist(std::vector< uint32_t > entries)
WasmCodePointer GetOrCreateHandleForNativeFunction(Address addr)
std::vector< uint32_t > FreelistToVector(FreelistHead freelist)
std::map< Address, WasmCodePointer > native_function_map_
void SweepSegments(size_t threshold=2 *kEntriesPerSegment)
WasmCodePointer AllocateAndInitializeEntry(Address entrypoint, uint64_t signature_hash)
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
ZoneVector< Entry > entries
V8_EXPORT_PRIVATE WasmCodePointerTable * GetProcessWideWasmCodePointerTable()
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
constexpr bool IsAligned(T value, U alignment)
Definition macros.h:403