| // Copyright 2020 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_ZONE_ZONE_LIST_H_ |
| #define V8_ZONE_ZONE_LIST_H_ |
| |
| #include "src/base/logging.h" |
| #include "src/zone/zone.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| template <typename T> |
| class Vector; |
| |
| // ZoneLists are growable lists with constant-time access to the elements. |
| // The list itself and all its elements are supposed to be allocated in zone |
| // memory. Unlike ZoneVector container, the ZoneList instance has minimal |
| // possible size which makes it a good candidate for embedding into other |
| // often-allocated zone objects. |
| // |
| // Note, ZoneLists' elements cannot be deleted individually and the destructor |
| // intentionally does not free the backing store. Because of the latter, the |
| // ZoneList must not be used outsize of zone memory. Consider using ZoneVector |
| // or other containers instead. |
| template <typename T> |
| class ZoneList final : public ZoneObject { |
| public: |
| // Construct a new ZoneList with the given capacity; the length is |
| // always zero. The capacity must be non-negative. |
| ZoneList(int capacity, Zone* zone) : capacity_(capacity) { |
| DCHECK_GE(capacity, 0); |
| data_ = (capacity_ > 0) ? zone->NewArray<T>(capacity_) : nullptr; |
| } |
| |
| // Construct a new ZoneList by copying the elements of the given ZoneList. |
| ZoneList(const ZoneList<T>& other, Zone* zone) |
| : ZoneList(other.length(), zone) { |
| AddAll(other, zone); |
| } |
| |
| // Construct a new ZoneList by copying the elements of the given vector. |
| ZoneList(const Vector<const T>& other, Zone* zone) |
| : ZoneList(other.length(), zone) { |
| AddAll(other, zone); |
| } |
| |
| ZoneList(ZoneList<T>&& other) V8_NOEXCEPT { *this = std::move(other); } |
| |
| // The ZoneList objects are usually allocated as a fields in other |
| // zone-allocated objects for which destructors are not called anyway, so |
| // we are not going to clear the memory here as well. |
| ~ZoneList() = default; |
| |
| ZoneList& operator=(ZoneList&& other) V8_NOEXCEPT { |
| // We don't have a Zone object, so we'll have to drop the data_ array. |
| // If this assert ever fails, consider calling Clear(Zone*) or |
| // DropAndClear() before the move assignment to make it explicit what's |
| // happenning with the lvalue. |
| DCHECK_NULL(data_); |
| data_ = other.data_; |
| capacity_ = other.capacity_; |
| length_ = other.length_; |
| other.DropAndClear(); |
| return *this; |
| } |
| |
| // Returns a reference to the element at index i. This reference is not safe |
| // to use after operations that can change the list's backing store |
| // (e.g. Add). |
| inline T& operator[](int i) const { |
| DCHECK_LE(0, i); |
| DCHECK_GT(static_cast<unsigned>(length_), static_cast<unsigned>(i)); |
| return data_[i]; |
| } |
| inline T& at(int i) const { return operator[](i); } |
| inline T& last() const { return at(length_ - 1); } |
| inline T& first() const { return at(0); } |
| |
| using iterator = T*; |
| inline iterator begin() { return &data_[0]; } |
| inline iterator end() { return &data_[length_]; } |
| |
| using const_iterator = const T*; |
| inline const_iterator begin() const { return &data_[0]; } |
| inline const_iterator end() const { return &data_[length_]; } |
| |
| V8_INLINE bool is_empty() const { return length_ == 0; } |
| V8_INLINE int length() const { return length_; } |
| V8_INLINE int capacity() const { return capacity_; } |
| |
| Vector<T> ToVector() const { return Vector<T>(data_, length_); } |
| Vector<T> ToVector(int start, int length) const { |
| DCHECK_LE(start, length_); |
| return Vector<T>(&data_[start], std::min(length_ - start, length)); |
| } |
| |
| Vector<const T> ToConstVector() const { |
| return Vector<const T>(data_, length_); |
| } |
| |
| // Adds a copy of the given 'element' to the end of the list, |
| // expanding the list if necessary. |
| void Add(const T& element, Zone* zone); |
| // Add all the elements from the argument list to this list. |
| void AddAll(const ZoneList<T>& other, Zone* zone); |
| // Add all the elements from the vector to this list. |
| void AddAll(const Vector<const T>& other, Zone* zone); |
| // Inserts the element at the specific index. |
| void InsertAt(int index, const T& element, Zone* zone); |
| |
| // Added 'count' elements with the value 'value' and returns a |
| // vector that allows access to the elements. The vector is valid |
| // until the next change is made to this list. |
| Vector<T> AddBlock(T value, int count, Zone* zone); |
| |
| // Overwrites the element at the specific index. |
| void Set(int index, const T& element); |
| |
| // Removes the i'th element without deleting it even if T is a |
| // pointer type; moves all elements above i "down". Returns the |
| // removed element. This function's complexity is linear in the |
| // size of the list. |
| T Remove(int i); |
| |
| // Removes the last element without deleting it even if T is a |
| // pointer type. Returns the removed element. |
| V8_INLINE T RemoveLast() { return Remove(length_ - 1); } |
| |
| // Clears the list by freeing the storage memory. If you want to keep the |
| // memory, use Rewind(0) instead. Be aware, that even if T is a |
| // pointer type, clearing the list doesn't delete the entries. |
| V8_INLINE void Clear(Zone* zone); |
| |
| // Clears the list but unlike Clear(), it doesn't free the storage memory. |
| // It's useful when the whole zone containing the backing store will be |
| // released but the list will be used further. |
| V8_INLINE void DropAndClear() { |
| data_ = nullptr; |
| capacity_ = 0; |
| length_ = 0; |
| } |
| |
| // Drops all but the first 'pos' elements from the list. |
| V8_INLINE void Rewind(int pos); |
| |
| inline bool Contains(const T& elm) const { |
| for (int i = 0; i < length_; i++) { |
| if (data_[i] == elm) return true; |
| } |
| return false; |
| } |
| |
| // Iterate through all list entries, starting at index 0. |
| template <class Visitor> |
| void Iterate(Visitor* visitor); |
| |
| // Sort all list entries (using QuickSort) |
| template <typename CompareFunction> |
| void Sort(CompareFunction cmp); |
| template <typename CompareFunction> |
| void StableSort(CompareFunction cmp, size_t start, size_t length); |
| |
| private: |
| T* data_ = nullptr; |
| int capacity_ = 0; |
| int length_ = 0; |
| |
| // Increase the capacity of a full list, and add an element. |
| // List must be full already. |
| void ResizeAdd(const T& element, Zone* zone); |
| |
| // Inlined implementation of ResizeAdd, shared by inlined and |
| // non-inlined versions of ResizeAdd. |
| void ResizeAddInternal(const T& element, Zone* zone); |
| |
| // Resize the list. |
| void Resize(int new_capacity, Zone* zone); |
| |
| DISALLOW_COPY_AND_ASSIGN(ZoneList); |
| }; |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_ZONE_ZONE_LIST_H_ |