v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
sidetable.h
Go to the documentation of this file.
1// Copyright 2022 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_COMPILER_TURBOSHAFT_SIDETABLE_H_
6#define V8_COMPILER_TURBOSHAFT_SIDETABLE_H_
7
8#include <algorithm>
9#include <type_traits>
10
13
15
16#ifdef DEBUG
17V8_EXPORT_PRIVATE bool OpIndexBelongsToTableGraph(const Graph* graph,
18 OpIndex index);
19#endif
20
21namespace detail {
22
23// This sidetable is a conceptually infinite mapping from Turboshaft operation
24// indices to values. It grows automatically and default-initializes the table
25// when accessed out-of-bounds.
26template <class T, class Key>
28 public:
29 static_assert(std::is_same_v<Key, OpIndex> ||
30 std::is_same_v<Key, BlockIndex>);
31
32 T& operator[](Key index) {
33 DCHECK(index.valid());
34 size_t i = index.id();
35 if (V8_UNLIKELY(i >= table_.size())) {
36 table_.resize(NextSize(i));
37 // Make sure we also get access to potential over-allocation by
38 // `resize()`.
39 table_.resize(table_.capacity());
40 }
41 return table_[i];
42 }
43
44 const T& operator[](Key index) const {
45 DCHECK(index.valid());
46 size_t i = index.id();
47 if (V8_UNLIKELY(i >= table_.size())) {
48 table_.resize(NextSize(i));
49 // Make sure we also get access to potential over-allocation by
50 // `resize()`.
51 table_.resize(table_.capacity());
52 }
53 return table_[i];
54 }
55
56 // Reset by filling the table with the default value instead of shrinking to
57 // keep the memory for later phases.
58 void Reset() { std::fill(table_.begin(), table_.end(), T{}); }
59
60 // Returns `true` if the table never contained any values, even before
61 // `Reset()`.
62 bool empty() const { return table_.empty(); }
63
64 protected:
65 // Constructors are protected: use GrowingBlockSidetable or
66 // GrowingOpIndexSidetable instead.
67 explicit GrowingSidetable(Zone* zone) : table_(zone) {}
68 GrowingSidetable(size_t size, const T& initial_value, Zone* zone)
69 : table_(size, initial_value, zone) {}
70
72
73 size_t NextSize(size_t out_of_bounds_index) const {
74 DCHECK_GE(out_of_bounds_index, table_.size());
75 return out_of_bounds_index + out_of_bounds_index / 2 + 32;
76 }
77};
78
79// A fixed-size sidetable mapping from `Key` to `T`.
80// Elements are default-initialized.
81template <class T, class Key>
83 public:
84 static_assert(std::is_same_v<Key, OpIndex> ||
85 std::is_same_v<Key, BlockIndex>);
86
87 T& operator[](Key op) {
88 DCHECK_LT(op.id(), table_.size());
89 return table_[op.id()];
90 }
91
92 const T& operator[](Key op) const {
93 DCHECK_LT(op.id(), table_.size());
94 return table_[op.id()];
95 }
96
97 protected:
98 // Constructors are protected: use FixedBlockSidetable or
99 // FixedOpIndexSidetable instead.
100 explicit FixedSidetable(size_t size, Zone* zone) : table_(size, zone) {}
101 FixedSidetable(size_t size, const T& default_value, Zone* zone)
102 : table_(size, default_value, zone) {}
103
105};
106
107} // namespace detail
108
109template <typename T>
110class GrowingBlockSidetable : public detail::GrowingSidetable<T, BlockIndex> {
112
113 public:
114 explicit GrowingBlockSidetable(Zone* zone) : Base(zone) {}
115
116 GrowingBlockSidetable(size_t size, const T& initial_value, Zone* zone)
117 : Base(size, initial_value, zone) {}
118};
119
120template <typename T>
121class FixedBlockSidetable : public detail::FixedSidetable<T, BlockIndex> {
123
124 public:
125 explicit FixedBlockSidetable(size_t size, Zone* zone) : Base(size, zone) {}
126
127 FixedBlockSidetable(size_t size, const T& initial_value, Zone* zone)
128 : Base(size, initial_value, zone) {}
129};
130
131template <class T>
134
135 public:
136 explicit GrowingOpIndexSidetable(Zone* zone, const Graph* graph)
137 : Base(zone)
138#ifdef DEBUG
139 ,
140 graph_(graph)
141#endif
142 {
143 USE(graph);
144 }
145
146 GrowingOpIndexSidetable(size_t size, const T& initial_value, Zone* zone,
147 const Graph* graph)
148 : Base(size, initial_value, zone)
149#ifdef DEBUG
150 ,
151 graph_(graph)
152#endif
153 {
154 USE(graph);
155 }
156
157 T& operator[](OpIndex index) {
158 DCHECK(OpIndexBelongsToTableGraph(graph_, index));
159 return Base::operator[](index);
160 }
161
162 const T& operator[](OpIndex index) const {
163 DCHECK(OpIndexBelongsToTableGraph(graph_, index));
164 return Base::operator[](index);
165 }
166
168 std::swap(Base::table_, other.table_);
169 }
170
171 public:
172#ifdef DEBUG
173 const Graph* graph_;
174#endif
175};
176
177template <class T>
180
181 public:
182 FixedOpIndexSidetable(size_t size, Zone* zone, const Graph* graph)
183 : Base(size, zone)
184#ifdef DEBUG
185 ,
186 graph_(graph)
187#endif
188 {
189 }
190 FixedOpIndexSidetable(size_t size, const T& default_value, Zone* zone,
191 const Graph* graph)
192 : Base(size, default_value, zone)
193#ifdef DEBUG
194 ,
195 graph_(graph)
196#endif
197 {
198 }
199
200 T& operator[](OpIndex index) {
201 DCHECK(OpIndexBelongsToTableGraph(graph_, index));
202 return Base::operator[](index);
203 }
204
205 const T& operator[](OpIndex index) const {
206 DCHECK(OpIndexBelongsToTableGraph(graph_, index));
207 return Base::operator[](index);
208 }
209
211 std::swap(Base::table_, other.table_);
212 }
213
214 public:
215#ifdef DEBUG
216 const Graph* graph_;
217#endif
218};
219
220template <class T>
222 public:
223 SparseOpIndexSideTable(Zone* zone, const Graph* graph)
224 : data_(zone)
225#ifdef DEBUG
226 ,
227 graph_(graph)
228#endif
229 {
230 }
231
232 T& operator[](OpIndex index) {
233 DCHECK(OpIndexBelongsToTableGraph(graph_, index));
234 return data_[index];
235 }
236
237 const T& operator[](OpIndex index) const {
238 DCHECK(OpIndexBelongsToTableGraph(graph_, index));
239 DCHECK(data_.contains(index));
240 return data_.at(index);
241 }
242
243 bool contains(OpIndex index, const T** value = nullptr) const {
244 DCHECK(OpIndexBelongsToTableGraph(graph_, index));
245 if (auto it = data_.find(index); it != data_.end()) {
246 if (value) *value = &it->second;
247 return true;
248 }
249 return false;
250 }
251
252 void remove(OpIndex index) {
253 DCHECK(OpIndexBelongsToTableGraph(graph_, index));
254 auto it = data_.find(index);
255 if (it != data_.end()) data_.erase(it);
256 }
257
258 auto begin() { return data_.begin(); }
259 auto end() { return data_.end(); }
260
261 private:
263#ifdef DEBUG
264 const Graph* graph_;
265#endif
266};
267
268} // namespace v8::internal::compiler::turboshaft
269
270#endif // V8_COMPILER_TURBOSHAFT_SIDETABLE_H_
FixedBlockSidetable(size_t size, const T &initial_value, Zone *zone)
Definition sidetable.h:127
FixedOpIndexSidetable(size_t size, const T &default_value, Zone *zone, const Graph *graph)
Definition sidetable.h:190
FixedOpIndexSidetable(size_t size, Zone *zone, const Graph *graph)
Definition sidetable.h:182
void SwapData(FixedOpIndexSidetable< T > &other)
Definition sidetable.h:210
GrowingBlockSidetable(size_t size, const T &initial_value, Zone *zone)
Definition sidetable.h:116
void SwapData(GrowingOpIndexSidetable< T > &other)
Definition sidetable.h:167
GrowingOpIndexSidetable(Zone *zone, const Graph *graph)
Definition sidetable.h:136
GrowingOpIndexSidetable(size_t size, const T &initial_value, Zone *zone, const Graph *graph)
Definition sidetable.h:146
bool contains(OpIndex index, const T **value=nullptr) const
Definition sidetable.h:243
SparseOpIndexSideTable(Zone *zone, const Graph *graph)
Definition sidetable.h:223
FixedSidetable(size_t size, const T &default_value, Zone *zone)
Definition sidetable.h:101
GrowingSidetable(size_t size, const T &initial_value, Zone *zone)
Definition sidetable.h:68
size_t NextSize(size_t out_of_bounds_index) const
Definition sidetable.h:73
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define USE(...)
Definition macros.h:293
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_UNLIKELY(condition)
Definition v8config.h:660
TFGraph * graph_