• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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