Changeset 16622 in webkit for trunk/JavaScriptCore/wtf/Vector.h


Ignore:
Timestamp:
Sep 28, 2006, 2:07:39 PM (19 years ago)
Author:
darin
Message:

JavaScriptCore:

Reviewed by Alice.

  • support for change that should fix <rdar://problem/4733044> REGRESSION: XML iBench shows 10% perf. regression (copying strings while decoding)
  • wtf/Vector.h: Changed VectorBuffer so that the general case contains an instance of the 0 case, since deriving from it was violating the Liskov Substitution Principle. (WTF::VectorBuffer::releaseBuffer): Added. Releases the buffer so it can be adopted by another data structure that uses the FastMalloc.h allocator. Returns 0 if the internal buffer was being used. (WTF::Vector::releaseBuffer): Added. Releases the buffer as above or creates a new one in the case where the internal buffer was being used.

WebCore:

Reviewed by Alice.

  • change that should fix <rdar://problem/4733044> REGRESSION: XML iBench shows 10% perf. regression (copying strings while decoding)

Use Vector<UChar> instead of String when building up the decoded string in
the ICU and Mac decoders. Using String leads to O(n2) behavior because
String grows the buffer every single time that append is called. Using
Vector::append instead of String::append also avoids constructing a string
each time just to append and a questionable copy that is done inside the
String::append function which also contributed to the slowness.

  • platform/PlatformString.h:
  • platform/String.cpp: (WebCore::String::adopt): Added. Makes a String from a Vector<UChar>, adopting the buffer from the vector to avoid copying and memory allocation.
  • platform/StringImpl.h:
  • platform/StringImpl.cpp: (WebCore::StringImpl::adopt): Ditto.
  • platform/StreamingTextDecoder.h:
  • platform/StreamingTextDecoder.cpp: (WebCore::TextCodec::appendOmittingBOM): Change to use a Vector<UChar> instead of a String, since vectors have better resizing performance (they store a separate capacity).
  • platform/StreamingTextDecoderICU.cpp: (WebCore::TextCodecICU::decode):
  • platform/mac/StreamingTextDecoderMac.cpp: (WebCore::TextCodecMac::decode): Change to use Vector<UChar> instead of String and then create a string at the end of the process using the new adopt function.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/wtf/Vector.h

    r16533 r16622  
    219219
    220220    template<typename T>
    221     class VectorBuffer<T, 0>
    222     {
     221    class VectorBuffer<T, 0> {
    223222    public:
    224223        VectorBuffer()
     224            : m_buffer(0), m_capacity(0)
     225        {
     226        }
     227       
     228        VectorBuffer(size_t capacity)
     229#if !ASSERT_DISABLED
    225230            : m_capacity(0)
    226             , m_buffer(0)
    227         {
    228         }
    229        
    230         VectorBuffer(size_t capacity)
    231             : m_capacity(0)
     231#endif
    232232        {
    233233            allocateBuffer(capacity);
     
    239239        }
    240240       
    241         void deallocateBuffer(T* buffer)
     241        static void deallocateBuffer(T* buffer)
    242242        {
    243243            fastFree(buffer);
     
    250250            if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
    251251                abort();
    252             m_buffer = reinterpret_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
     252            m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
    253253        }
    254254
     
    257257        size_t capacity() const { return m_capacity; }
    258258
     259        T* releaseBuffer()
     260        {
     261            T* buffer = m_buffer;
     262            m_buffer = 0;
     263            m_capacity = 0;
     264            return buffer;
     265        }
     266
    259267    protected:
    260268        VectorBuffer(T* buffer, size_t capacity)
    261             : m_capacity(capacity)
    262             , m_buffer(buffer)
    263         {
    264         }
    265 
     269            : m_buffer(buffer), m_capacity(capacity)
     270        {
     271        }
     272
     273        T* m_buffer;
     274
     275    private:
    266276        size_t m_capacity;
    267         T *m_buffer;
    268     };
    269 
    270     template<typename T, size_t inlineCapacity>
    271     class VectorBuffer : public VectorBuffer<T, 0> {
     277    };
     278
     279    template<typename T, size_t inlineCapacity>
     280    class VectorBuffer : private VectorBuffer<T, 0> {
    272281    private:
    273282        typedef VectorBuffer<T, 0> BaseBuffer;
    274283    public:
    275         VectorBuffer() 
     284        VectorBuffer()
    276285            : BaseBuffer(inlineBuffer(), inlineCapacity)
    277286        {
     
    282291        {
    283292            if (capacity > inlineCapacity)
    284                 BaseBuffer::allocateBuffer(capacity);
     293                allocateBuffer(capacity);
    285294        }
    286295
    287296        ~VectorBuffer()
    288297        {
    289             if (BaseBuffer::buffer() == inlineBuffer())
     298            if (buffer() == inlineBuffer())
    290299                BaseBuffer::m_buffer = 0;
    291300        }
     
    297306        }
    298307
     308        using BaseBuffer::allocateBuffer;
     309
     310        using BaseBuffer::buffer;
     311        using BaseBuffer::capacity;
     312
     313        T* releaseBuffer()
     314        {
     315            if (buffer() == inlineBuffer())
     316                return 0;
     317            return BaseBuffer::releaseBuffer();
     318        }
     319
    299320    private:
    300321        static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
    301         T *inlineBuffer() { return reinterpret_cast<T *>(&m_inlineBuffer); }
     322        T* inlineBuffer() { return reinterpret_cast<T*>(&m_inlineBuffer); }
     323
    302324        char m_inlineBuffer[m_inlineBufferSize];
    303325    };
     
    409431        void fill(const T& val) { fill(val, size()); }
    410432
     433        T* releaseBuffer();
     434
    411435    private:
    412436        void expandCapacity(size_t newMinCapacity);
     
    598622
    599623    template<typename T, size_t inlineCapacity>
     624    T* Vector<T, inlineCapacity>::releaseBuffer()
     625    {
     626        T* buffer = m_impl.releaseBuffer();
     627        if (!buffer && m_size) {
     628            // If the vector had some data, but no buffer to release,
     629            // that means it was using the inline buffer. In that case,
     630            // we create a brand new buffer so the caller always gets one.
     631            size_t bytes = m_size * sizeof(T);
     632            buffer = static_cast<T*>(fastMalloc(bytes));
     633            memcpy(buffer, data(), bytes);
     634        }
     635        m_size = 0;
     636        return buffer;
     637    }
     638
     639    template<typename T, size_t inlineCapacity>
    600640    void deleteAllValues(const Vector<T, inlineCapacity>& collection)
    601641    {
Note: See TracChangeset for help on using the changeset viewer.