js/src/assembler/wtf/SegmentedVector.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
    29 #ifndef assembler_wtf_SegmentedVector_h
    30 #define assembler_wtf_SegmentedVector_h
    32 #include "js/Utility.h"
    33 #include "js/Vector.h"
    35 namespace WTF {
    37     // An iterator for SegmentedVector. It supports only the pre ++ operator
    38     template <typename T, size_t SegmentSize> class SegmentedVector;
    39     template <typename T, size_t SegmentSize> class SegmentedVectorIterator {
    40     private:
    41         friend class SegmentedVector<T, SegmentSize>;
    42     public:
    43         typedef SegmentedVectorIterator<T, SegmentSize> Iterator;
    45         ~SegmentedVectorIterator() { }
    47         T& operator*() const { return (*m_vector.m_segments[m_segment])[m_index]; }
    48         T* operator->() const { return &(*m_vector.m_segments[m_segment])[m_index]; }
    50         // Only prefix ++ operator supported
    51         Iterator& operator++()
    52         {
    53             ASSERT(m_index != SegmentSize);
    54             ++m_index;
    55             //if (m_index >= m_vector.m_segments.at(m_segment)->size())  {
    56             if (m_index >= m_vector.m_segments[m_segment]->length())  {
    57                 //if (m_segment + 1 < m_vector.m_segments.size()) {
    58                 if (m_segment + 1 < m_vector.m_segments.length()) {
    59                     //ASSERT(m_vector.m_segments.at(m_segment)->size() > 0);
    60                     ASSERT(m_vector.m_segments[m_segment]->length() > 0);
    61                     ++m_segment;
    62                     m_index = 0;
    63                 } else {
    64                     // Points to the "end" symbol
    65                     m_segment = 0;
    66                     m_index = SegmentSize;
    67                 }
    68             }
    69             return *this;
    70         }
    72         bool operator==(const Iterator& other) const
    73         {
    74             return (m_index == other.m_index && m_segment = other.m_segment && &m_vector == &other.m_vector);
    75         }
    77         bool operator!=(const Iterator& other) const
    78         {
    79             return (m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector);
    80         }
    82         SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize>& other)
    83         {
    84             m_vector = other.m_vector;
    85             m_segment = other.m_segment;
    86             m_index = other.m_index;
    87             return *this;
    88         }
    90     private:
    91         SegmentedVectorIterator(SegmentedVector<T, SegmentSize>& vector, size_t segment, size_t index)
    92             : m_vector(vector)
    93             , m_segment(segment)
    94             , m_index(index)
    95         {
    96         }
    98         SegmentedVector<T, SegmentSize>& m_vector;
    99         size_t m_segment;
   100         size_t m_index;
   101     };
   103     // SegmentedVector is just like Vector, but it doesn't move the values
   104     // stored in its buffer when it grows. Therefore, it is safe to keep
   105     // pointers into a SegmentedVector.
   106     template <typename T, size_t SegmentSize> class SegmentedVector {
   107         friend class SegmentedVectorIterator<T, SegmentSize>;
   108     public:
   109         typedef SegmentedVectorIterator<T, SegmentSize> Iterator;
   111         SegmentedVector()
   112             : m_size(0)
   113         {
   114             m_segments.append(&m_inlineSegment);
   115         }
   117         ~SegmentedVector()
   118         {
   119             deleteAllSegments();
   120         }
   122         size_t size() const { return m_size; }
   123         bool isEmpty() const { return !size(); }
   125         T& at(size_t index)
   126         {
   127             if (index < SegmentSize)
   128                 return m_inlineSegment[index];
   129             return segmentFor(index)->at(subscriptFor(index));
   130         }
   132         T& operator[](size_t index)
   133         {
   134             return at(index);
   135         }
   137         T& last()
   138         {
   139             return at(size() - 1);
   140         }
   142         template <typename U> void append(const U& value)
   143         {
   144             ++m_size;
   146             if (m_size <= SegmentSize) {
   147                 //m_inlineSegment.uncheckedAppend(value);
   148                 m_inlineSegment.append(value);
   149                 return;
   150             }
   152             if (!segmentExistsFor(m_size - 1))
   153                 m_segments.append(js_new<Segment>());
   154             //segmentFor(m_size - 1)->uncheckedAppend(value);
   155             segmentFor(m_size - 1)->append(value);
   156         }
   158         T& alloc()
   159         {
   160             append<T>(T());
   161             return last();
   162         }
   164         void removeLast()
   165         {
   166             if (m_size <= SegmentSize)
   167                 m_inlineSegment.removeLast();
   168             else
   169                 segmentFor(m_size - 1)->removeLast();
   170             --m_size;
   171         }
   173         void grow(size_t size)
   174         {
   175             ASSERT(size > m_size);
   176             ensureSegmentsFor(size);
   177             m_size = size;
   178         }
   180         void clear()
   181         {
   182             deleteAllSegments();
   183             m_segments.resize(1);
   184             m_inlineSegment.clear();
   185             m_size = 0;
   186         }
   188         Iterator begin()
   189         {
   190             return Iterator(*this, 0, m_size ? 0 : SegmentSize);
   191         }
   193         Iterator end()
   194         {
   195             return Iterator(*this, 0, SegmentSize);
   196         }
   198     private:
   199         typedef js::Vector<T, SegmentSize ,js::SystemAllocPolicy > Segment;
   201         void deleteAllSegments()
   202         {
   203             // Skip the first segment, because it's our inline segment, which was
   204             // not created by new.
   205             //for (size_t i = 1; i < m_segments.size(); i++)
   206             for (size_t i = 1; i < m_segments.length(); i++)
   207                 js_delete<Segment>(m_segments[i]);
   208         }
   210         bool segmentExistsFor(size_t index)
   211         {
   212             //return index / SegmentSize < m_segments.size();
   213             return index / SegmentSize < m_segments.length();
   214         }
   216         Segment* segmentFor(size_t index)
   217         {
   218             return m_segments[index / SegmentSize];
   219         }
   221         size_t subscriptFor(size_t index)
   222         {
   223             return index % SegmentSize;
   224         }
   226         void ensureSegmentsFor(size_t size)
   227         {
   228             size_t segmentCount = m_size / SegmentSize;
   229             if (m_size % SegmentSize)
   230                 ++segmentCount;
   231             //segmentCount = std::max<size_t>(segmentCount, 1); // We always have at least our inline segment.
   232             segmentCount = segmentCount > 1 ? segmentCount : 1; // We always have at least our inline segment.
   234             size_t neededSegmentCount = size / SegmentSize;
   235             if (size % SegmentSize)
   236                 ++neededSegmentCount;
   238             // Fill up to N - 1 segments.
   239             size_t end = neededSegmentCount - 1;
   240             for (size_t i = segmentCount - 1; i < end; ++i)
   241                 ensureSegment(i, SegmentSize);
   243             // Grow segment N to accomodate the remainder.
   244             ensureSegment(end, subscriptFor(size - 1) + 1);
   245         }
   247         void ensureSegment(size_t segmentIndex, size_t size)
   248         {
   249             ASSERT(segmentIndex <= m_segments.size());
   250             if (segmentIndex == m_segments.size())
   251                 m_segments.append(js_new<Segment>());
   252             m_segments[segmentIndex]->grow(size);
   253         }
   255         size_t m_size;
   256         Segment m_inlineSegment;
   257         js::Vector<Segment*, 32 ,js::SystemAllocPolicy > m_segments;
   258     };
   260 } // namespace WTF
   262 using WTF::SegmentedVector;
   264 #endif /* assembler_wtf_SegmentedVector_h */

mercurial