Changeset 52795 in webkit


Ignore:
Timestamp:
Jan 5, 2010 7:14:00 AM (14 years ago)
Author:
yong.li@torchmobile.com
Message:

2010-01-04 Yong Li <yoli@rim.com>

Reviewed by Darin Adler.

Let SharedBuffer use a group of memory segments internally.
It will merge the segments into a flat consecutive buffer only when
necessary.
https://bugs.webkit.org/show_bug.cgi?id=33178

  • platform/SharedBuffer.cpp: (WebCore::allocateSegment): (WebCore::freeSegment): (WebCore::SharedBuffer::SharedBuffer): (WebCore::SharedBuffer::~SharedBuffer): (WebCore::SharedBuffer::adoptVector): (WebCore::SharedBuffer::size): (WebCore::SharedBuffer::data): (WebCore::SharedBuffer::append): (WebCore::SharedBuffer::clear): (WebCore::SharedBuffer::copy): (WebCore::SharedBuffer::buffer): (WebCore::SharedBuffer::getSomeData):
  • platform/SharedBuffer.h:
  • platform/cf/SharedBufferCF.cpp: (WebCore::SharedBuffer::maybeTransferPlatformData):
  • platform/haiku/SharedBufferHaiku.cpp: (WebCore::SharedBuffer::createWithContentsOfFile):
  • platform/qt/SharedBufferQt.cpp: (WebCore::SharedBuffer::createWithContentsOfFile):
  • platform/win/SharedBufferWin.cpp: (WebCore::SharedBuffer::createWithContentsOfFile):
Location:
trunk/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r52793 r52795  
     12010-01-04  Yong Li  <yoli@rim.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        Let SharedBuffer use a group of memory segments internally.
     6        It will merge the segments into a flat consecutive buffer only when
     7        necessary.
     8        https://bugs.webkit.org/show_bug.cgi?id=33178
     9
     10        * platform/SharedBuffer.cpp:
     11        (WebCore::allocateSegment):
     12        (WebCore::freeSegment):
     13        (WebCore::SharedBuffer::SharedBuffer):
     14        (WebCore::SharedBuffer::~SharedBuffer):
     15        (WebCore::SharedBuffer::adoptVector):
     16        (WebCore::SharedBuffer::size):
     17        (WebCore::SharedBuffer::data):
     18        (WebCore::SharedBuffer::append):
     19        (WebCore::SharedBuffer::clear):
     20        (WebCore::SharedBuffer::copy):
     21        (WebCore::SharedBuffer::buffer):
     22        (WebCore::SharedBuffer::getSomeData):
     23        * platform/SharedBuffer.h:
     24        * platform/cf/SharedBufferCF.cpp:
     25        (WebCore::SharedBuffer::maybeTransferPlatformData):
     26        * platform/haiku/SharedBufferHaiku.cpp:
     27        (WebCore::SharedBuffer::createWithContentsOfFile):
     28        * platform/qt/SharedBufferQt.cpp:
     29        (WebCore::SharedBuffer::createWithContentsOfFile):
     30        * platform/win/SharedBufferWin.cpp:
     31        (WebCore::SharedBuffer::createWithContentsOfFile):
     32
    1332010-01-05  Simon Hausmann  <simon.hausmann@nokia.com>
    234
  • trunk/WebCore/platform/SharedBuffer.cpp

    r51875 r52795  
    11/*
    22 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
     3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    3132namespace WebCore {
    3233
     34static const unsigned segmentSize = 0x1000;
     35static const unsigned segmentPositionMask = 0x0FFF;
     36
     37static inline unsigned segmentIndex(unsigned position)
     38{
     39    return position / segmentSize;
     40}
     41
     42static inline unsigned offsetInSegment(unsigned position)
     43{
     44    return position & segmentPositionMask;
     45}
     46
     47static inline char* allocateSegment()
     48{
     49    return static_cast<char*>(fastMalloc(segmentSize));
     50}
     51
     52static inline void freeSegment(char* p)
     53{
     54    fastFree(p);
     55}
     56
    3357SharedBuffer::SharedBuffer()
     58    : m_size(0)
    3459{
    3560}
    3661
    3762SharedBuffer::SharedBuffer(const char* data, int size)
    38 {
    39     m_buffer.append(data, size);
     63    : m_size(0)
     64{
     65    append(data, size);
    4066}
    4167
    4268SharedBuffer::SharedBuffer(const unsigned char* data, int size)
    43 {
    44     m_buffer.append(data, size);
     69    : m_size(0)
     70{
     71    append(reinterpret_cast<const char*>(data), size);
    4572}
    4673   
    4774SharedBuffer::~SharedBuffer()
    4875{
     76    clear();
    4977}
    5078
     
    5381    RefPtr<SharedBuffer> buffer = create();
    5482    buffer->m_buffer.swap(vector);
     83    buffer->m_size = buffer->m_buffer.size();
    5584    return buffer.release();
    5685}
     
    72101        return m_purgeableBuffer->size();
    73102   
    74     return m_buffer.size();
     103    return m_size;
    75104}
    76105
     
    83112        return m_purgeableBuffer->data();
    84113   
    85     return m_buffer.data();
    86 }
    87 
    88 void SharedBuffer::append(const char* data, int len)
     114    return buffer().data();
     115}
     116
     117void SharedBuffer::append(const char* data, int length)
    89118{
    90119    ASSERT(!m_purgeableBuffer);
     
    92121    maybeTransferPlatformData();
    93122   
    94     m_buffer.append(data, len);
     123    unsigned positionInSegment = offsetInSegment(m_size - m_buffer.size());
     124    m_size += length;
     125
     126    if (m_size <= segmentSize) {
     127        // No need to use segments for small resource data
     128        m_buffer.append(data, length);
     129        return;
     130    }
     131
     132    char* segment;
     133    if (!positionInSegment) {
     134        segment = allocateSegment();
     135        m_segments.append(segment);
     136    } else
     137        segment = m_segments.last() + positionInSegment;
     138
     139    unsigned segmentFreeSpace = segmentSize - positionInSegment;
     140    unsigned bytesToCopy = length < segmentFreeSpace ? length : segmentFreeSpace;
     141
     142    for (;;) {
     143        memcpy(segment, data, bytesToCopy);
     144        if (length == bytesToCopy)
     145            break;
     146
     147        length -= bytesToCopy;
     148        data += bytesToCopy;
     149        segment = allocateSegment();
     150        m_segments.append(segment);
     151        bytesToCopy = length < segmentSize ? length : segmentSize;
     152    }
    95153}
    96154
     
    99157    clearPlatformData();
    100158   
     159    for (unsigned i = 0; i < m_segments.size(); ++i)
     160        freeSegment(m_segments[i]);
     161
     162    m_segments.clear();
     163    m_size = 0;
     164
    101165    m_buffer.clear();
    102166    m_purgeableBuffer.clear();
     
    105169PassRefPtr<SharedBuffer> SharedBuffer::copy() const
    106170{
    107     return SharedBuffer::create(data(), size());
     171    RefPtr<SharedBuffer> clone(adoptRef(new SharedBuffer));
     172    if (m_purgeableBuffer || hasPlatformData()) {
     173        clone->append(data(), size());
     174        return clone;
     175    }
     176
     177    clone->m_size = m_size;
     178    clone->m_buffer.reserveCapacity(m_size);
     179    clone->m_buffer.append(m_buffer.data(), m_buffer.size());
     180    for (unsigned i = 0; i < m_segments.size(); ++i)
     181        clone->m_buffer.append(m_segments[i], segmentSize);
     182    return clone;
    108183}
    109184
     
    114189}
    115190
     191const Vector<char>& SharedBuffer::buffer() const
     192{
     193    unsigned bufferSize = m_buffer.size();
     194    if (m_size > bufferSize) {
     195        m_buffer.resize(m_size);
     196        char* destination = m_buffer.data() + bufferSize;
     197        unsigned bytesLeft = m_size - bufferSize;
     198        for (unsigned i = 0; i < m_segments.size(); ++i) {
     199            unsigned bytesToCopy = bytesLeft < segmentSize ? bytesLeft : segmentSize;
     200            memcpy(destination, m_segments[i], bytesToCopy);
     201            destination += bytesToCopy;
     202            bytesLeft -= bytesToCopy;
     203            freeSegment(m_segments[i]);
     204        }
     205        m_segments.clear();
     206    }
     207    return m_buffer;
     208}
     209
     210unsigned SharedBuffer::getSomeData(const char*& someData, unsigned position) const
     211{
     212    if (hasPlatformData() || m_purgeableBuffer) {
     213        someData = data() + position;
     214        return size() - position;
     215    }
     216
     217    if (position >= m_size) {
     218        someData = 0;
     219        return 0;
     220    }
     221
     222    unsigned consecutiveSize = m_buffer.size();
     223    if (position < consecutiveSize) {
     224        someData = m_buffer.data() + position;
     225        return consecutiveSize - position;
     226    }
     227 
     228    position -= consecutiveSize;
     229    unsigned segmentedSize = m_size - consecutiveSize;
     230    unsigned segments = m_segments.size();
     231    unsigned segment = segmentIndex(position);
     232    ASSERT(segment < segments);
     233
     234    unsigned positionInSegment = offsetInSegment(position);
     235    someData = m_segments[segment] + positionInSegment;
     236    return segment == segments - 1 ? segmentedSize - position : segmentSize - positionInSegment;
     237}
     238
    116239#if !PLATFORM(CF)
    117240
  • trunk/WebCore/platform/SharedBuffer.h

    r42463 r52795  
    11/*
    22 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
     3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    7475#endif
    7576
     77    // Calling this function will force internal segmented buffers
     78    // to be merged into a flat buffer. Use getSomeData() whenever possible
     79    // for better performance.
    7680    const char* data() const;
     81
    7782    unsigned size() const;
    78     const Vector<char> &buffer() { return m_buffer; }
    7983
    80     bool isEmpty() const { return size() == 0; }
     84    // Calling this function will force internal segmented buffers
     85    // to be merged into a flat buffer. Use getSomeData() whenever possible
     86    // for better performance.
     87    const Vector<char>& buffer() const;
     88
     89    bool isEmpty() const { return size(); }
    8190
    8291    void append(const char*, int);
     
    91100    // Ensure this buffer has no other clients before calling this.
    92101    PurgeableBuffer* releasePurgeableBuffer();
    93    
     102
     103    // Return the number of consecutive bytes after "position". "data"
     104    // points to the first byte.
     105    // Return 0 when no more data left.
     106    // When extracting all data with getSomeData(), the caller should
     107    // repeat calling it until it returns 0.
     108    // Usage:
     109    //      const char* segment;
     110    //      unsigned pos = 0;
     111    //      while (unsigned length = sharedBuffer->getSomeData(segment, pos)) {
     112    //          // Use the data. for example: decoder->decode(segment, length);
     113    //          pos += length;
     114    //      }
     115    unsigned getSomeData(const char*& data, unsigned position = 0) const;
     116
    94117private:
    95118    SharedBuffer();
     
    101124    bool hasPlatformData() const;
    102125   
    103     Vector<char> m_buffer;
     126    unsigned m_size;
     127    mutable Vector<char> m_buffer;
     128    mutable Vector<char*> m_segments;
    104129    OwnPtr<PurgeableBuffer> m_purgeableBuffer;
    105130#if PLATFORM(CF)
     
    111136}
    112137
    113 #endif
     138#endif // SharedBuffer_h
  • trunk/WebCore/platform/cf/SharedBufferCF.cpp

    r42463 r52795  
    7777        return;
    7878   
    79     ASSERT(m_buffer.size() == 0);
     79    ASSERT(m_size == 0);
    8080       
    81     m_buffer.append((const char*)CFDataGetBytePtr(m_cfData.get()), CFDataGetLength(m_cfData.get()));
     81    append((const char*)CFDataGetBytePtr(m_cfData.get()), CFDataGetLength(m_cfData.get()));
    8282       
    8383    m_cfData = 0;
  • trunk/WebCore/platform/haiku/SharedBufferHaiku.cpp

    r47295 r52795  
    4848    if (result->m_buffer.size() != size)
    4949        return 0;
     50    result->m_size = size;
    5051
    5152    file.Read(result->m_buffer.data(), result->m_buffer.size());
  • trunk/WebCore/platform/qt/SharedBufferQt.cpp

    r46170 r52795  
    4646        return 0;
    4747
     48    result->m_size = result->m_buffer.size();
     49
    4850    file.read(result->m_buffer.data(), result->m_buffer.size());
    4951    return result.release();
  • trunk/WebCore/platform/win/SharedBufferWin.cpp

    r47663 r52795  
    5858    }
    5959
     60    result->m_size = result->m_buffer.size();
     61
    6062    if (fread(result->m_buffer.data(), 1, fileStat.st_size, fileDescriptor) != fileStat.st_size)
    6163        LOG_ERROR("Failed to fully read contents of file %s - errno(%i)", filePath.ascii().data(), errno);
Note: See TracChangeset for help on using the changeset viewer.