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