SegmentedVector.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. * Copyright (C) 2008 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifndef SegmentedVector_h
  29. #define SegmentedVector_h
  30. #include <wtf/Noncopyable.h>
  31. #include <wtf/Vector.h>
  32. namespace WTF {
  33. // An iterator for SegmentedVector. It supports only the pre ++ operator
  34. template <typename T, size_t SegmentSize = 8, size_t InlineCapacity = 32, bool shared = false> class SegmentedVector;
  35. template <typename T, size_t SegmentSize = 8, size_t InlineCapacity = 32> class SegmentedVectorIterator {
  36. private:
  37. friend class SegmentedVector<T, SegmentSize, InlineCapacity>;
  38. public:
  39. typedef SegmentedVectorIterator<T, SegmentSize, InlineCapacity> Iterator;
  40. ~SegmentedVectorIterator() { }
  41. T& operator*() const { return m_vector.m_segments.at(m_segment)->at(m_index); }
  42. T* operator->() const { return &m_vector.m_segments.at(m_segment)->at(m_index); }
  43. // Only prefix ++ operator supported
  44. Iterator& operator++()
  45. {
  46. ASSERT(m_index != SegmentSize);
  47. ++m_index;
  48. if (m_index >= m_vector.m_segments.at(m_segment)->size()) {
  49. if (m_segment + 1 < m_vector.m_segments.size()) {
  50. ASSERT(m_vector.m_segments.at(m_segment)->size() > 0);
  51. ++m_segment;
  52. m_index = 0;
  53. } else {
  54. // Points to the "end" symbol
  55. m_segment = 0;
  56. m_index = SegmentSize;
  57. }
  58. }
  59. return *this;
  60. }
  61. bool operator==(const Iterator& other) const
  62. {
  63. return m_index == other.m_index && m_segment == other.m_segment && &m_vector == &other.m_vector;
  64. }
  65. bool operator!=(const Iterator& other) const
  66. {
  67. return m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector;
  68. }
  69. SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize, InlineCapacity>& other)
  70. {
  71. m_vector = other.m_vector;
  72. m_segment = other.m_segment;
  73. m_index = other.m_index;
  74. return *this;
  75. }
  76. private:
  77. SegmentedVectorIterator(SegmentedVector<T, SegmentSize, InlineCapacity>& vector, size_t segment, size_t index)
  78. : m_vector(vector)
  79. , m_segment(segment)
  80. , m_index(index)
  81. {
  82. }
  83. SegmentedVector<T, SegmentSize, InlineCapacity>& m_vector;
  84. size_t m_segment;
  85. size_t m_index;
  86. };
  87. // SegmentedVector is just like Vector, but it doesn't move the values
  88. // stored in its buffer when it grows. Therefore, it is safe to keep
  89. // pointers into a SegmentedVector. The default tuning values are
  90. // optimized for segmented vectors that get large; you may want to use
  91. // SegmentedVector<thingy, 1, 0> if you don't expect a lot of entries.
  92. template <typename T, size_t SegmentSize, size_t InlineCapacity, bool shared>
  93. class SegmentedVector {
  94. friend class SegmentedVectorIterator<T, SegmentSize, InlineCapacity>;
  95. WTF_MAKE_NONCOPYABLE(SegmentedVector);
  96. public:
  97. typedef SegmentedVectorIterator<T, SegmentSize, InlineCapacity> Iterator;
  98. SegmentedVector()
  99. : m_size(0)
  100. {
  101. }
  102. ~SegmentedVector()
  103. {
  104. deleteAllSegments();
  105. }
  106. size_t size() const { return m_size; }
  107. bool isEmpty() const { return !size(); }
  108. T& at(size_t index)
  109. {
  110. return segmentFor(index)->at(subscriptFor(index));
  111. }
  112. const T& at(size_t index) const
  113. {
  114. return const_cast<SegmentedVector<T, SegmentSize, InlineCapacity>*>(this)->at(index);
  115. }
  116. T& operator[](size_t index)
  117. {
  118. return at(index);
  119. }
  120. const T& operator[](size_t index) const
  121. {
  122. return at(index);
  123. }
  124. T& last()
  125. {
  126. return at(size() - 1);
  127. }
  128. template <typename U> void append(const U& value)
  129. {
  130. ++m_size;
  131. if (!segmentExistsFor(m_size - 1))
  132. m_segments.append(
  133. #if ENABLE(DETACHED_JIT)
  134. shared ? sharedNew<Segment>() :
  135. #endif
  136. new Segment);
  137. segmentFor(m_size - 1)->uncheckedAppend(value);
  138. }
  139. T& alloc()
  140. {
  141. append<T>(T());
  142. return last();
  143. }
  144. void removeLast()
  145. {
  146. segmentFor(m_size - 1)->removeLast();
  147. --m_size;
  148. }
  149. void grow(size_t size)
  150. {
  151. ASSERT(size > m_size);
  152. ensureSegmentsFor(size);
  153. m_size = size;
  154. }
  155. void clear()
  156. {
  157. deleteAllSegments();
  158. m_segments.clear();
  159. m_size = 0;
  160. }
  161. Iterator begin()
  162. {
  163. return Iterator(*this, 0, m_size ? 0 : SegmentSize);
  164. }
  165. Iterator end()
  166. {
  167. return Iterator(*this, 0, SegmentSize);
  168. }
  169. void shrinkToFit()
  170. {
  171. m_segments.shrinkToFit();
  172. }
  173. private:
  174. typedef Vector<T, SegmentSize, CrashOnOverflow, shared> Segment;
  175. void deleteAllSegments()
  176. {
  177. for (size_t i = 0; i < m_segments.size(); i++) {
  178. #if ENABLE(DETACHED_JIT)
  179. shared ? sharedDelete<Segment>(m_segments[i]) :
  180. #endif
  181. delete m_segments[i];
  182. }
  183. }
  184. bool segmentExistsFor(size_t index)
  185. {
  186. return index / SegmentSize < m_segments.size();
  187. }
  188. Segment* segmentFor(size_t index)
  189. {
  190. return m_segments[index / SegmentSize];
  191. }
  192. size_t subscriptFor(size_t index)
  193. {
  194. return index % SegmentSize;
  195. }
  196. void ensureSegmentsFor(size_t size)
  197. {
  198. size_t segmentCount = (m_size + SegmentSize - 1) / SegmentSize;
  199. size_t neededSegmentCount = (size + SegmentSize - 1) / SegmentSize;
  200. // Fill up to N - 1 segments.
  201. size_t end = neededSegmentCount - 1;
  202. for (size_t i = segmentCount ? segmentCount - 1 : 0; i < end; ++i)
  203. ensureSegment(i, SegmentSize);
  204. // Grow segment N to accomodate the remainder.
  205. ensureSegment(end, subscriptFor(size - 1) + 1);
  206. }
  207. void ensureSegment(size_t segmentIndex, size_t size)
  208. {
  209. ASSERT_WITH_SECURITY_IMPLICATION(segmentIndex <= m_segments.size());
  210. if (segmentIndex == m_segments.size())
  211. m_segments.append(
  212. #if ENABLE(DETACHED_JIT)
  213. shared ? sharedNew<Segment>() :
  214. #endif
  215. new Segment
  216. );
  217. m_segments[segmentIndex]->grow(size);
  218. }
  219. size_t m_size;
  220. Vector<Segment*, 0, CrashOnOverflow, shared> m_segments;
  221. };
  222. #if ENABLE(DETACHED_JIT)
  223. template <typename T, size_t SegmentSize = 8, size_t InlineCapacity = 32>
  224. using SegmentedVector_shared = SegmentedVector<T, SegmentSize, InlineCapacity, true>;
  225. #else
  226. template <typename T, size_t SegmentSize = 8, size_t InlineCapacity = 32>
  227. using SegmentedVector_shared = SegmentedVector<T, SegmentSize, InlineCapacity, false>;
  228. #endif
  229. } // namespace WTF
  230. using WTF::SegmentedVector;
  231. using WTF::SegmentedVector_shared;
  232. #endif // SegmentedVector_h