LCOV - code coverage report
Current view: top level - src/base - small-vector.h (source / functions) Hit Total Coverage
Test: app.info Lines: 48 55 87.3 %
Date: 2019-04-18 Functions: 14 18 77.8 %

          Line data    Source code
       1             : // Copyright 2018 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_SMALL_VECTOR_H_
       6             : #define V8_BASE_SMALL_VECTOR_H_
       7             : 
       8             : #include <type_traits>
       9             : 
      10             : #include "src/base/bits.h"
      11             : #include "src/base/macros.h"
      12             : 
      13             : namespace v8 {
      14             : namespace base {
      15             : 
      16             : // Minimal SmallVector implementation. Uses inline storage first, switches to
      17             : // malloc when it overflows.
      18             : template <typename T, size_t kSize>
      19             : class SmallVector {
      20             :   // Currently only support trivially copyable and trivially destructible data
      21             :   // types, as it uses memcpy to copy elements and never calls destructors.
      22             :   ASSERT_TRIVIALLY_COPYABLE(T);
      23             :   STATIC_ASSERT(std::is_trivially_destructible<T>::value);
      24             : 
      25             :  public:
      26             :   static constexpr size_t kInlineSize = kSize;
      27             : 
      28     2275591 :   SmallVector() = default;
      29       13108 :   explicit SmallVector(size_t size) { resize_no_init(size); }
      30             :   SmallVector(const SmallVector& other) V8_NOEXCEPT { *this = other; }
      31      151380 :   SmallVector(SmallVector&& other) V8_NOEXCEPT { *this = std::move(other); }
      32             : 
      33             :   ~SmallVector() {
      34     1329966 :     if (is_big()) free(begin_);
      35     1329966 :   }
      36             : 
      37       56314 :   SmallVector& operator=(const SmallVector& other) V8_NOEXCEPT {
      38       56314 :     if (this == &other) return *this;
      39             :     size_t other_size = other.size();
      40       56316 :     if (capacity() < other_size) {
      41             :       // Create large-enough heap-allocated storage.
      42          12 :       if (is_big()) free(begin_);
      43          12 :       begin_ = reinterpret_cast<T*>(malloc(sizeof(T) * other_size));
      44          12 :       end_of_storage_ = begin_ + other_size;
      45             :     }
      46       56316 :     memcpy(begin_, other.begin_, sizeof(T) * other_size);
      47       56316 :     end_ = begin_ + other_size;
      48       56316 :     return *this;
      49             :   }
      50             : 
      51       75689 :   SmallVector& operator=(SmallVector&& other) V8_NOEXCEPT {
      52       75689 :     if (this == &other) return *this;
      53       75689 :     if (other.is_big()) {
      54           0 :       if (is_big()) free(begin_);
      55           0 :       begin_ = other.begin_;
      56           0 :       end_ = other.end_;
      57           0 :       end_of_storage_ = other.end_of_storage_;
      58             :       other.reset();
      59             :     } else {
      60             :       DCHECK_GE(capacity(), other.size());  // Sanity check.
      61             :       size_t other_size = other.size();
      62       75689 :       memcpy(begin_, other.begin_, sizeof(T) * other_size);
      63       75689 :       end_ = begin_ + other_size;
      64             :     }
      65             :     return *this;
      66             :   }
      67             : 
      68             :   T* data() { return begin_; }
      69             :   const T* data() const { return begin_; }
      70             : 
      71             :   T* begin() { return begin_; }
      72             :   const T* begin() const { return begin_; }
      73             : 
      74             :   T* end() { return end_; }
      75             :   const T* end() const { return end_; }
      76             : 
      77     1505257 :   size_t size() const { return end_ - begin_; }
      78             :   bool empty() const { return end_ == begin_; }
      79      243057 :   size_t capacity() const { return end_of_storage_ - begin_; }
      80             : 
      81             :   T& back() {
      82             :     DCHECK_NE(0, size());
      83      404657 :     return end_[-1];
      84             :   }
      85             : 
      86             :   T& operator[](size_t index) {
      87             :     DCHECK_GT(size(), index);
      88     2586441 :     return begin_[index];
      89             :   }
      90             : 
      91             :   const T& operator[](size_t index) const {
      92             :     DCHECK_GT(size(), index);
      93       19739 :     return begin_[index];
      94             :   }
      95             : 
      96             :   template <typename... Args>
      97     2211592 :   void emplace_back(Args&&... args) {
      98     2211592 :     if (V8_UNLIKELY(end_ == end_of_storage_)) Grow();
      99     2211690 :     new (end_) T(std::forward<Args>(args)...);
     100     2211690 :     ++end_;
     101     2211690 :   }
     102             : 
     103             :   void pop_back(size_t count = 1) {
     104             :     DCHECK_GE(size(), count);
     105     1529738 :     end_ -= count;
     106             :   }
     107             : 
     108       66332 :   void resize_no_init(size_t new_size) {
     109             :     // Resizing without initialization is safe if T is trivially copyable.
     110             :     ASSERT_TRIVIALLY_COPYABLE(T);
     111      280721 :     if (new_size > capacity()) Grow(new_size);
     112      280721 :     end_ = begin_ + new_size;
     113       66332 :   }
     114             : 
     115             :   // Clear without freeing any storage.
     116             :   void clear() { end_ = begin_; }
     117             : 
     118             :   // Clear and go back to inline storage.
     119             :   void reset() {
     120           0 :     begin_ = inline_storage_begin();
     121           0 :     end_ = begin_;
     122           0 :     end_of_storage_ = begin_ + kInlineSize;
     123             :   }
     124             : 
     125             :  private:
     126             :   T* begin_ = inline_storage_begin();
     127             :   T* end_ = begin_;
     128     1109780 :   T* end_of_storage_ = begin_ + kInlineSize;
     129             :   typename std::aligned_storage<sizeof(T) * kInlineSize, alignof(T)>::type
     130             :       inline_storage_;
     131             : 
     132       13147 :   void Grow(size_t min_capacity = 0) {
     133       13147 :     size_t in_use = end_ - begin_;
     134             :     size_t new_capacity =
     135       39441 :         base::bits::RoundUpToPowerOfTwo(std::max(min_capacity, 2 * capacity()));
     136       13147 :     T* new_storage = reinterpret_cast<T*>(malloc(sizeof(T) * new_capacity));
     137       13147 :     memcpy(new_storage, begin_, sizeof(T) * in_use);
     138       13147 :     if (is_big()) free(begin_);
     139       13147 :     begin_ = new_storage;
     140       13147 :     end_ = new_storage + in_use;
     141       13147 :     end_of_storage_ = new_storage + new_capacity;
     142       13147 :   }
     143             : 
     144     1405655 :   bool is_big() const { return begin_ != inline_storage_begin(); }
     145             : 
     146     1109780 :   T* inline_storage_begin() { return reinterpret_cast<T*>(&inline_storage_); }
     147             :   const T* inline_storage_begin() const {
     148     1144669 :     return reinterpret_cast<const T*>(&inline_storage_);
     149             :   }
     150             : };
     151             : 
     152             : }  // namespace base
     153             : }  // namespace v8
     154             : 
     155             : #endif  // V8_BASE_SMALL_VECTOR_H_

Generated by: LCOV version 1.10