1 // Copyright 2017 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_UTILS_DETACHABLE_VECTOR_H_ 6 #define V8_UTILS_DETACHABLE_VECTOR_H_ 7 8 #include <stddef.h> 9 10 #include <algorithm> 11 12 #include "src/base/logging.h" 13 #include "src/base/macros.h" 14 15 namespace v8 { 16 namespace internal { 17 18 class V8_EXPORT_PRIVATE DetachableVectorBase { 19 public: 20 // Clear our reference to the backing store. Does not delete it! detach()21 void detach() { 22 data_ = nullptr; 23 capacity_ = 0; 24 size_ = 0; 25 } 26 pop_back()27 void pop_back() { --size_; } capacity()28 size_t capacity() const { return capacity_; } size()29 size_t size() const { return size_; } empty()30 bool empty() const { return size_ == 0; } 31 32 static const size_t kMinimumCapacity; 33 static const size_t kDataOffset; 34 static const size_t kCapacityOffset; 35 static const size_t kSizeOffset; 36 37 protected: 38 void* data_ = nullptr; 39 size_t capacity_ = 0; 40 size_t size_ = 0; 41 }; 42 43 // This class wraps an array and provides a few of the common member 44 // functions for accessing the data. Two extra methods are also provided: free() 45 // and detach(), which allow for manual control of the backing store. This is 46 // currently required for use in the HandleScopeImplementer. Any other class 47 // should just use a std::vector. 48 template <typename T> 49 class DetachableVector : public DetachableVectorBase { 50 public: 51 DetachableVector() = default; ~DetachableVector()52 ~DetachableVector() { delete[] data(); } 53 push_back(const T & value)54 void push_back(const T& value) { 55 if (size_ == capacity_) { 56 size_t new_capacity = std::max(kMinimumCapacity, 2 * capacity_); 57 Resize(new_capacity); 58 } 59 60 data()[size_] = value; 61 ++size_; 62 } 63 64 // Free the backing store and clear our reference to it. free()65 void free() { 66 delete[] data(); 67 data_ = nullptr; 68 capacity_ = 0; 69 size_ = 0; 70 } 71 at(size_t i)72 T& at(size_t i) const { 73 DCHECK_LT(i, size_); 74 return data()[i]; 75 } back()76 T& back() const { return at(size_ - 1); } front()77 T& front() const { return at(0); } 78 shrink_to_fit()79 void shrink_to_fit() { 80 size_t new_capacity = std::max(size_, kMinimumCapacity); 81 if (new_capacity < capacity_ / 2) { 82 Resize(new_capacity); 83 } 84 } 85 86 private: data()87 T* data() const { return static_cast<T*>(data_); } 88 Resize(size_t new_capacity)89 void Resize(size_t new_capacity) { 90 DCHECK_LE(size_, new_capacity); 91 T* new_data_ = new T[new_capacity]; 92 93 std::copy(data(), data() + size_, new_data_); 94 delete[] data(); 95 96 data_ = new_data_; 97 capacity_ = new_capacity; 98 } 99 }; 100 101 } // namespace internal 102 } // namespace v8 103 104 #endif // V8_UTILS_DETACHABLE_VECTOR_H_ 105