v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
vector.h
Go to the documentation of this file.
1// Copyright 2014 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_BASE_VECTOR_H_
6#define V8_BASE_VECTOR_H_
7
8#include <algorithm>
9#include <cstring>
10#include <iterator>
11#include <limits>
12#include <memory>
13#include <type_traits>
14
15#include "src/base/hashing.h"
16#include "src/base/logging.h"
17#include "src/base/macros.h"
18
19namespace v8 {
20namespace base {
21
22template <typename T>
23class Vector {
24 public:
25 using value_type = T;
26 using iterator = T*;
27 using const_iterator = const T*;
28
29 constexpr Vector() : start_(nullptr), length_(0) {}
30
31 constexpr Vector(T* data, size_t length) : start_(data), length_(length) {
32 DCHECK(length == 0 || data != nullptr);
33 }
34
35 static Vector<T> New(size_t length) {
36 return Vector<T>(new T[length], length);
37 }
38
39 // Returns a vector using the same backing storage as this one,
40 // spanning from and including 'from', to but not including 'to'.
41 Vector<T> SubVector(size_t from, size_t to) const {
42 DCHECK_LE(from, to);
43 DCHECK_LE(to, length_);
44 return Vector<T>(begin() + from, to - from);
45 }
46 Vector<T> SubVectorFrom(size_t from) const {
47 return SubVector(from, length_);
48 }
49
50 template <class U>
52 DCHECK_EQ(size(), other.size());
53 std::copy(other.begin(), other.end(), begin());
54 }
55
56 template <class U, size_t n>
57 void OverwriteWith(const std::array<U, n>& other) {
58 DCHECK_EQ(size(), other.size());
59 std::copy(other.begin(), other.end(), begin());
60 }
61
62 // Returns the length of the vector. Only use this if you really need an
63 // integer return value. Use {size()} otherwise.
64 int length() const {
65 CHECK_GE(std::numeric_limits<int>::max(), length_);
66 return static_cast<int>(length_);
67 }
68
69 // Returns the length of the vector as a size_t.
70 constexpr size_t size() const { return length_; }
71
72 // Returns whether or not the vector is empty.
73 constexpr bool empty() const { return length_ == 0; }
74
75 // Access individual vector elements - checks bounds in debug mode.
76 T& operator[](size_t index) const {
77 DCHECK_LT(index, length_);
78 return start_[index];
79 }
80
81 const T& at(size_t index) const { return operator[](index); }
82
83 T& first() { return start_[0]; }
84 const T& first() const { return start_[0]; }
85
86 T& last() {
88 return start_[length_ - 1];
89 }
90 const T& last() const {
92 return start_[length_ - 1];
93 }
94
95 // Returns a pointer to the start of the data in the vector.
96 constexpr T* begin() const { return start_; }
97 constexpr const T* cbegin() const { return start_; }
98
99 // For consistency with other containers, do also provide a {data} accessor.
100 constexpr T* data() const { return start_; }
101
102 // Returns a pointer past the end of the data in the vector.
103 constexpr T* end() const { return start_ + length_; }
104 constexpr const T* cend() const { return start_ + length_; }
105
106 constexpr std::reverse_iterator<T*> rbegin() const {
107 return std::make_reverse_iterator(end());
108 }
109 constexpr std::reverse_iterator<T*> rend() const {
110 return std::make_reverse_iterator(begin());
111 }
112
113 // Returns a clone of this vector with a new backing store.
114 Vector<T> Clone() const {
115 T* result = new T[length_];
116 for (size_t i = 0; i < length_; i++) result[i] = start_[i];
117 return Vector<T>(result, length_);
118 }
119
120 void Truncate(size_t length) {
121 DCHECK(length <= length_);
122 length_ = length;
123 }
124
125 // Releases the array underlying this vector. Once disposed the
126 // vector is empty.
127 void Dispose() {
128 delete[] start_;
129 start_ = nullptr;
130 length_ = 0;
131 }
132
137
140 start_ += offset;
141 length_ -= offset;
142 return *this;
143 }
144
145 // Implicit conversion from Vector<T> to Vector<const U> if
146 // - T* is convertible to const U*, and
147 // - U and T have the same size.
148 // Note that this conversion is only safe for `*const* U`; writes would
149 // violate covariance.
150 template <typename U>
151 requires std::is_convertible_v<T*, const U*> && (sizeof(U) == sizeof(T))
152 operator Vector<const U>() const {
153 return {start_, length_};
154 }
155
156 template <typename S>
157 static Vector<T> cast(Vector<S> input) {
158 // Casting is potentially dangerous, so be really restrictive here. This
159 // might be lifted once we have use cases for that.
160 static_assert(std::is_trivial_v<S> && std::is_standard_layout_v<S>);
161 static_assert(std::is_trivial_v<T> && std::is_standard_layout_v<T>);
162 DCHECK_EQ(0, (input.size() * sizeof(S)) % sizeof(T));
163 DCHECK_EQ(0, reinterpret_cast<uintptr_t>(input.begin()) % alignof(T));
164 return Vector<T>(reinterpret_cast<T*>(input.begin()),
165 input.size() * sizeof(S) / sizeof(T));
166 }
167
168 bool operator==(const Vector<T>& other) const {
169 return std::equal(begin(), end(), other.begin(), other.end());
170 }
171
172 bool operator!=(const Vector<T>& other) const {
173 return !operator==(other);
174 }
175
176 template <typename TT = T>
177 requires(!std::is_const_v<TT>)
178 bool operator==(const Vector<const T>& other) const {
179 return std::equal(begin(), end(), other.begin(), other.end());
180 }
181
182 template <typename TT = T>
183 requires(!std::is_const_v<TT>)
184 bool operator!=(const Vector<const T>& other) const {
185 return !operator==(other);
186 }
187
188 private:
190 size_t length_;
191};
192
193template <typename T>
195 return hash_range(v.begin(), v.end());
196}
197
198template <typename T>
200 public:
201 explicit ScopedVector(size_t length) : Vector<T>(new T[length], length) {}
202 ~ScopedVector() { delete[] this->begin(); }
203
204 private:
206};
207
208template <typename T>
210 public:
211 OwnedVector() = default;
212
213 OwnedVector(std::unique_ptr<T[]> data, size_t length)
214 : data_(std::move(data)), length_(length) {
215 DCHECK_IMPLIES(length_ > 0, data_ != nullptr);
216 }
217
218 // Disallow copying.
219 OwnedVector(const OwnedVector&) = delete;
221
222 // Move construction and move assignment from {OwnedVector<U>} to
223 // {OwnedVector<T>}, instantiable if {std::unique_ptr<U>} can be converted to
224 // {std::unique_ptr<T>}. Can also be used to convert {OwnedVector<T>} to
225 // {OwnedVector<const T>}.
226 // These also function as the standard move construction/assignment operator.
227 // {other} is left as an empty vector.
228 template <typename U>
229 requires std::is_convertible_v<std::unique_ptr<U>, std::unique_ptr<T>>
231 *this = std::move(other);
232 }
233
234 template <typename U>
235 requires std::is_convertible_v<std::unique_ptr<U>, std::unique_ptr<T>>
237 static_assert(sizeof(U) == sizeof(T));
238 data_ = std::move(other.data_);
239 length_ = other.length_;
240 DCHECK_NULL(other.data_);
241 other.length_ = 0;
242 return *this;
243 }
244
245 // Returns the length of the vector as a size_t.
246 constexpr size_t size() const { return length_; }
247
248 // Returns whether or not the vector is empty.
249 constexpr bool empty() const { return length_ == 0; }
250
251 constexpr T* begin() const {
252 DCHECK_IMPLIES(length_ > 0, data_ != nullptr);
253 return data_.get();
254 }
255
256 constexpr T* end() const { return begin() + length_; }
257
258 // In addition to {begin}, do provide a {data()} accessor for API
259 // compatibility with other sequential containers.
260 constexpr T* data() const { return begin(); }
261
262 constexpr std::reverse_iterator<T*> rbegin() const {
263 return std::make_reverse_iterator(end());
264 }
265 constexpr std::reverse_iterator<T*> rend() const {
266 return std::make_reverse_iterator(begin());
267 }
268
269 // Access individual vector elements - checks bounds in debug mode.
270 T& operator[](size_t index) const {
271 DCHECK_LT(index, length_);
272 return data_[index];
273 }
274
275 // Returns a {Vector<T>} view of the data in this vector.
276 Vector<T> as_vector() const { return {begin(), size()}; }
277
278 // Releases the backing data from this vector and transfers ownership to the
279 // caller. This vector will be empty afterwards.
280 std::unique_ptr<T[]> ReleaseData() {
281 length_ = 0;
282 return std::move(data_);
283 }
284
285 // Allocates a new vector of the specified size via the default allocator.
286 // Elements in the new vector are value-initialized.
287 static OwnedVector<T> New(size_t size) {
288 if (size == 0) return {};
289 return OwnedVector<T>(std::make_unique<T[]>(size), size);
290 }
291
292 // Allocates a new vector of the specified size via the default allocator.
293 // Elements in the new vector are default-initialized.
294 static OwnedVector<T> NewForOverwrite(size_t size) {
295 if (size == 0) return {};
296 return OwnedVector<T>(std::make_unique_for_overwrite<T[]>(size), size);
297 }
298
299 // Allocates a new vector containing the specified collection of values.
300 // {Iterator} is the common type of {std::begin} and {std::end} called on a
301 // {const U&}. This function is only instantiable if that type exists.
302 template <typename U>
303 static OwnedVector<U> NewByCopying(const U* data, size_t size) {
305 std::copy(data, data + size, result.begin());
306 return result;
307 }
308
309 bool operator==(std::nullptr_t) const { return data_ == nullptr; }
310 bool operator!=(std::nullptr_t) const { return data_ != nullptr; }
311
312 private:
313 template <typename U>
314 friend class OwnedVector;
315
316 std::unique_ptr<T[]> data_;
317 size_t length_ = 0;
318};
319
320// The vectors returned by {StaticCharVector}, {CStrVector}, or {OneByteVector}
321// do not contain a null-termination byte. If you want the null byte, use
322// {ArrayVector}.
323
324// Known length, constexpr.
325template <size_t N>
326constexpr Vector<const char> StaticCharVector(const char (&array)[N]) {
327 return {array, N - 1};
328}
329
330// Unknown length, not constexpr.
331inline Vector<const char> CStrVector(const char* data) {
332 return {data, strlen(data)};
333}
334
335// OneByteVector is never constexpr because the data pointer is
336// {reinterpret_cast}ed.
337inline Vector<const uint8_t> OneByteVector(const char* data, size_t length) {
338 return {reinterpret_cast<const uint8_t*>(data), length};
339}
340
341inline Vector<const uint8_t> OneByteVector(const char* data) {
342 return OneByteVector(data, strlen(data));
343}
344
345template <size_t N>
347 return OneByteVector(array, N - 1);
348}
349
350// For string literals, ArrayVector("foo") returns a vector ['f', 'o', 'o', \0]
351// with length 4 and null-termination.
352// If you want ['f', 'o', 'o'], use CStrVector("foo").
353template <typename T, size_t N>
354inline constexpr Vector<T> ArrayVector(T (&arr)[N]) {
355 return {arr, N};
356}
357
358// Construct a Vector from a start pointer and a size.
359template <typename T>
360inline constexpr Vector<T> VectorOf(T* start, size_t size) {
361 return {start, size};
362}
363
364// Construct a Vector from anything compatible with std::data and std::size (ie,
365// an array, or a container providing a {data()} and {size()} accessor).
366template <typename Container>
367inline constexpr auto VectorOf(Container&& c)
368 -> decltype(VectorOf(std::data(c), std::size(c))) {
369 return VectorOf(std::data(c), std::size(c));
370}
371
372// Construct a Vector from an initializer list. The vector can obviously only be
373// used as long as the initializer list is live. Valid uses include direct use
374// in parameter lists: F(VectorOf({1, 2, 3}));
375template <typename T>
376inline constexpr Vector<const T> VectorOf(std::initializer_list<T> list) {
377 return VectorOf(list.begin(), list.size());
378}
379
380// Construct an OwnedVector from a start pointer and a size.
381// The data will be copied.
382template <typename T>
383inline OwnedVector<T> OwnedCopyOf(const T* data, size_t size) {
384 return OwnedVector<T>::NewByCopying(data, size);
385}
386
387// Construct an OwnedVector from anything compatible with std::data and
388// std::size (e.g. an array, or a container providing a {data()} and {size()}
389// accessor). The data will be copied.
390template <typename Container>
391inline auto OwnedCopyOf(const Container& c)
392 -> decltype(OwnedCopyOf(std::data(c), std::size(c))) {
393 return OwnedCopyOf(std::data(c), std::size(c));
394}
395
396template <typename T, size_t kSize>
397class EmbeddedVector : public Vector<T> {
398 public:
399 EmbeddedVector() : Vector<T>(buffer_, kSize) {}
400 explicit EmbeddedVector(const T& initial_value) : Vector<T>(buffer_, kSize) {
401 std::fill_n(buffer_, kSize, initial_value);
402 }
405
406 private:
407 T buffer_[kSize];
408};
409
410} // namespace base
411} // namespace v8
412
413#endif // V8_BASE_VECTOR_H_
#define T
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
EmbeddedVector & operator=(const EmbeddedVector &)=delete
EmbeddedVector(const EmbeddedVector &)=delete
EmbeddedVector(const T &initial_value)
Definition vector.h:400
constexpr T * begin() const
Definition vector.h:251
constexpr bool empty() const
Definition vector.h:249
constexpr size_t size() const
Definition vector.h:246
bool operator==(std::nullptr_t) const
Definition vector.h:309
static OwnedVector< T > New(size_t size)
Definition vector.h:287
static OwnedVector< U > NewByCopying(const U *data, size_t size)
Definition vector.h:303
std::unique_ptr< T[]> ReleaseData()
Definition vector.h:280
OwnedVector(OwnedVector< U > &&other) V8_NOEXCEPT
Definition vector.h:230
std::unique_ptr< T[]> data_
Definition vector.h:316
OwnedVector(const OwnedVector &)=delete
T & operator[](size_t index) const
Definition vector.h:270
OwnedVector(std::unique_ptr< T[]> data, size_t length)
Definition vector.h:213
OwnedVector & operator=(const OwnedVector &)=delete
constexpr std::reverse_iterator< T * > rbegin() const
Definition vector.h:262
constexpr T * end() const
Definition vector.h:256
bool operator!=(std::nullptr_t) const
Definition vector.h:310
constexpr T * data() const
Definition vector.h:260
friend class OwnedVector
Definition vector.h:314
constexpr std::reverse_iterator< T * > rend() const
Definition vector.h:265
Vector< T > as_vector() const
Definition vector.h:276
OwnedVector & operator=(OwnedVector< U > &&other) V8_NOEXCEPT
Definition vector.h:236
static OwnedVector< T > NewForOverwrite(size_t size)
Definition vector.h:294
DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedVector)
ScopedVector(size_t length)
Definition vector.h:201
void OverwriteWith(Vector< U > other)
Definition vector.h:51
Vector< T > Clone() const
Definition vector.h:114
T & operator[](size_t index) const
Definition vector.h:76
const T & first() const
Definition vector.h:84
int length() const
Definition vector.h:64
const T & last() const
Definition vector.h:90
Vector< T > SubVector(size_t from, size_t to) const
Definition vector.h:41
bool operator!=(const Vector< T > &other) const
Definition vector.h:172
constexpr std::reverse_iterator< T * > rend() const
Definition vector.h:109
void Dispose()
Definition vector.h:127
bool operator==(const Vector< T > &other) const
Definition vector.h:168
Vector< T > operator+=(size_t offset)
Definition vector.h:138
constexpr bool empty() const
Definition vector.h:73
constexpr Vector(T *data, size_t length)
Definition vector.h:31
Vector< T > operator+(size_t offset)
Definition vector.h:133
void Truncate(size_t length)
Definition vector.h:120
constexpr size_t size() const
Definition vector.h:70
constexpr Vector()
Definition vector.h:29
const T & at(size_t index) const
Definition vector.h:81
Vector< T > SubVectorFrom(size_t from) const
Definition vector.h:46
void OverwriteWith(const std::array< U, n > &other)
Definition vector.h:57
static Vector< T > New(size_t length)
Definition vector.h:35
constexpr std::reverse_iterator< T * > rbegin() const
Definition vector.h:106
constexpr const T * cend() const
Definition vector.h:104
constexpr T * begin() const
Definition vector.h:96
const T * const_iterator
Definition vector.h:27
constexpr T * data() const
Definition vector.h:100
static Vector< T > cast(Vector< S > input)
Definition vector.h:157
size_t length_
Definition vector.h:190
constexpr const T * cbegin() const
Definition vector.h:97
constexpr T * end() const
Definition vector.h:103
int start
OptionalOpIndex index
int32_t offset
ZoneVector< RpoNumber > & result
STL namespace.
V8_INLINE size_t hash_value(unsigned int v)
Definition hashing.h:205
V8_INLINE size_t hash_range(Iterator first, Iterator last)
Definition hashing.h:308
constexpr Vector< T > ArrayVector(T(&arr)[N])
Definition vector.h:354
Vector< const uint8_t > StaticOneByteVector(const char(&array)[N])
Definition vector.h:346
constexpr Vector< const char > StaticCharVector(const char(&array)[N])
Definition vector.h:326
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
Vector< const char > CStrVector(const char *data)
Definition vector.h:331
OwnedVector< T > OwnedCopyOf(const T *data, size_t size)
Definition vector.h:383
Vector< const uint8_t > OneByteVector(const char *data, size_t length)
Definition vector.h:337
#define V8_NOEXCEPT
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_GE(lhs, rhs)
#define DCHECK_NULL(val)
Definition logging.h:491
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_INLINE
Definition v8config.h:500
#define V8_NODISCARD
Definition v8config.h:693