Changeset 54743 in webkit


Ignore:
Timestamp:
Feb 12, 2010 3:57:35 PM (14 years ago)
Author:
barraclough@apple.com
Message:

https://bugs.webkit.org/show_bug.cgi?id=33731
Many false leaks in release builds due to PtrAndFlags

Reviewed by Darin Adler.

Remove UntypedPtrAndBitfield (similar to PtrAndFlags) in UStringImpl,
and steal bits from the refCount instead.

  • runtime/UStringImpl.cpp:

(JSC::UStringImpl::baseSharedBuffer):
(JSC::UStringImpl::~UStringImpl):

  • runtime/UStringImpl.h:

(JSC::UStringImpl::cost):
(JSC::UStringImpl::isIdentifier):
(JSC::UStringImpl::setIsIdentifier):
(JSC::UStringImpl::ref):
(JSC::UStringImpl::deref):
(JSC::UStringImpl::UStringImpl):
(JSC::UStringImpl::bufferOwnerString):
(JSC::UStringImpl::bufferOwnership):
(JSC::UStringImpl::isStatic):
(JSC::UStringImpl::):

Location:
trunk/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r54732 r54743  
     12010-02-12  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=33731
     6        Many false leaks in release builds due to PtrAndFlags
     7
     8        Remove UntypedPtrAndBitfield (similar to PtrAndFlags) in UStringImpl,
     9        and steal bits from the refCount instead.
     10
     11        * runtime/UStringImpl.cpp:
     12        (JSC::UStringImpl::baseSharedBuffer):
     13        (JSC::UStringImpl::~UStringImpl):
     14        * runtime/UStringImpl.h:
     15        (JSC::UStringImpl::cost):
     16        (JSC::UStringImpl::isIdentifier):
     17        (JSC::UStringImpl::setIsIdentifier):
     18        (JSC::UStringImpl::ref):
     19        (JSC::UStringImpl::deref):
     20        (JSC::UStringImpl::UStringImpl):
     21        (JSC::UStringImpl::bufferOwnerString):
     22        (JSC::UStringImpl::bufferOwnership):
     23        (JSC::UStringImpl::isStatic):
     24        (JSC::UStringImpl::):
     25
    1262010-02-12  Geoffrey Garen  <ggaren@apple.com>
    227
  • trunk/JavaScriptCore/runtime/UStringImpl.cpp

    r54464 r54743  
    7676{
    7777    ASSERT((bufferOwnership() == BufferShared)
    78         || ((bufferOwnership() == BufferOwned) && !m_dataBuffer.asPtr<void*>()));
     78        || ((bufferOwnership() == BufferOwned) && !m_buffer));
    7979
    80     if (bufferOwnership() != BufferShared)
    81         m_dataBuffer = UntypedPtrAndBitfield(SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(), BufferShared);
     80    if (bufferOwnership() != BufferShared) {
     81        m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
     82        m_bufferShared = SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef();
     83    }
    8284
    83     return m_dataBuffer.asPtr<SharedUChar*>();
     85    return m_bufferShared;
    8486}
    8587
     
    109111            fastFree(m_data);
    110112        else if (bufferOwnership() == BufferSubstring)
    111             m_dataBuffer.asPtr<UStringImpl*>()->deref();
     113            m_bufferSubstring->deref();
    112114        else {
    113115            ASSERT(bufferOwnership() == BufferShared);
    114             m_dataBuffer.asPtr<SharedUChar*>()->deref();
     116            m_bufferShared->deref();
    115117        }
    116118    }
  • trunk/JavaScriptCore/runtime/UStringImpl.h

    r54563 r54743  
    4141typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar;
    4242
    43 class UntypedPtrAndBitfield {
    44 public:
    45     UntypedPtrAndBitfield() {}
    46 
    47     UntypedPtrAndBitfield(void* ptrValue, uintptr_t bitValue)
    48         : m_value(reinterpret_cast<uintptr_t>(ptrValue) | bitValue)
    49 #ifndef NDEBUG
    50         , m_leaksPtr(ptrValue)
    51 #endif
    52     {
    53         ASSERT(ptrValue == asPtr<void*>());
    54         ASSERT((*this & ~s_alignmentMask) == bitValue);
    55     }
    56 
    57     template<typename T>
    58     T asPtr() const { return reinterpret_cast<T>(m_value & s_alignmentMask); }
    59 
    60     UntypedPtrAndBitfield& operator&=(uintptr_t bits)
    61     {
    62         m_value &= bits | s_alignmentMask;
    63         return *this;
    64     }
    65 
    66     UntypedPtrAndBitfield& operator|=(uintptr_t bits)
    67     {
    68         m_value |= bits & ~s_alignmentMask;
    69         return *this;
    70     }
    71 
    72     uintptr_t operator&(uintptr_t mask) const
    73     {
    74         return m_value & mask & ~s_alignmentMask;
    75     }
    76 
    77 private:
    78     static const uintptr_t s_alignmentMask = ~static_cast<uintptr_t>(0x7);
    79     uintptr_t m_value;
    80 #ifndef NDEBUG
    81         void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced.
    82 #endif
    83 };
    84 
    8543class UStringImpl : Noncopyable {
    8644public:
     
    148106        // For substrings, return the cost of the base string.
    149107        if (bufferOwnership() == BufferSubstring)
    150             return m_dataBuffer.asPtr<UStringImpl*>()->cost();
    151 
    152         if (m_dataBuffer & s_reportedCostBit)
     108            return m_bufferSubstring->cost();
     109
     110        if (m_refCountAndFlags & s_refCountFlagHasReportedCost)
    153111            return 0;
    154         m_dataBuffer |= s_reportedCostBit;
     112        m_refCountAndFlags |= s_refCountFlagHasReportedCost;
    155113        return m_length;
    156114    }
     
    158116    unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers
    159117    void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers
    160     bool isIdentifier() const { return m_isIdentifier; }
    161     void setIsIdentifier(bool isIdentifier) { m_isIdentifier = isIdentifier; }
    162 
    163     UStringImpl* ref() { m_refCount += s_refCountIncrement; return this; }
    164     ALWAYS_INLINE void deref() { if (!(m_refCount -= s_refCountIncrement)) delete this; }
     118    bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; }
     119    void setIsIdentifier(bool isIdentifier)
     120    {
     121        if (isIdentifier)
     122            m_refCountAndFlags |= s_refCountFlagIsIdentifier;
     123        else
     124            m_refCountAndFlags &= ~s_refCountFlagIsIdentifier;
     125    }
     126
     127    UStringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; }
     128    ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; }
    165129
    166130    static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
     
    201165    UStringImpl(UChar* data, int length, BufferOwnership ownership)
    202166        : m_data(data)
    203         , m_length(length)
    204         , m_refCount(s_refCountIncrement)
    205         , m_hash(0)
    206         , m_isIdentifier(false)
    207         , m_dataBuffer(0, ownership)
     167        , m_buffer(0)
     168        , m_length(length)
     169        , m_refCountAndFlags(s_refCountIncrement | ownership)
     170        , m_hash(0)
    208171    {
    209172        ASSERT((ownership == BufferInternal) || (ownership == BufferOwned));
     
    217180    UStringImpl(UChar* data, int length, StaticStringConstructType)
    218181        : m_data(data)
    219         , m_length(length)
    220         , m_refCount(s_staticRefCountInitialValue)
    221         , m_hash(0)
    222         , m_isIdentifier(false)
    223         , m_dataBuffer(0, BufferOwned)
     182        , m_buffer(0)
     183        , m_length(length)
     184        , m_refCountAndFlags(s_refCountFlagStatic | BufferOwned)
     185        , m_hash(0)
    224186    {
    225187        checkConsistency();
     
    229191    UStringImpl(UChar* data, int length, PassRefPtr<UStringImpl> base)
    230192        : m_data(data)
    231         , m_length(length)
    232         , m_refCount(s_refCountIncrement)
    233         , m_hash(0)
    234         , m_isIdentifier(false)
    235         , m_dataBuffer(base.releaseRef(), BufferSubstring)
     193        , m_bufferSubstring(base.releaseRef())
     194        , m_length(length)
     195        , m_refCountAndFlags(s_refCountIncrement | BufferSubstring)
     196        , m_hash(0)
    236197    {
    237198        // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes
    238199        // that all pointers will be at least 8-byte aligned, we cannot guarantee that of
    239200        // UStringImpls that are not heap allocated.
    240         ASSERT(m_dataBuffer.asPtr<UStringImpl*>()->size());
    241         ASSERT(!m_dataBuffer.asPtr<UStringImpl*>()->isStatic());
     201        ASSERT(m_bufferSubstring->size());
     202        ASSERT(!m_bufferSubstring->isStatic());
    242203        checkConsistency();
    243204    }
     
    246207    UStringImpl(UChar* data, int length, PassRefPtr<SharedUChar> sharedBuffer)
    247208        : m_data(data)
    248         , m_length(length)
    249         , m_refCount(s_refCountIncrement)
    250         , m_hash(0)
    251         , m_isIdentifier(false)
    252         , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared)
     209        , m_bufferShared(sharedBuffer.releaseRef())
     210        , m_length(length)
     211        , m_refCountAndFlags(s_refCountIncrement | BufferShared)
     212        , m_hash(0)
    253213    {
    254214        checkConsistency();
     
    263223    static const int s_minLengthToShare = 10;
    264224    static const unsigned s_copyCharsInlineCutOff = 20;
    265     static const uintptr_t s_bufferOwnershipMask = 3;
    266     static const uintptr_t s_reportedCostBit = 4;
    267225    // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2.
    268226    // We initialize static strings with an odd number (specifically, 1), such that the refCount cannot reach zero.
    269     static const int s_refCountIncrement = 2;
    270     static const int s_staticRefCountInitialValue = 1;
    271 
    272     UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() :  this; }
    273     const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() :  this; }
     227    static const unsigned s_refCountMask = 0xFFFFFFF0;
     228    static const int s_refCountIncrement = 0x20;
     229    static const int s_refCountFlagStatic = 0x10;
     230    static const unsigned s_refCountFlagHasReportedCost = 0x8;
     231    static const unsigned s_refCountFlagIsIdentifier = 0x4;
     232    static const unsigned s_refCountMaskBufferOwnership = 0x3;
     233
     234    UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring :  this; }
     235    const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring :  this; }
    274236    SharedUChar* baseSharedBuffer();
    275     unsigned bufferOwnership() const { return m_dataBuffer & s_bufferOwnershipMask; }
    276     bool isStatic() const { return m_refCount & 1; }
     237    unsigned bufferOwnership() const { return m_refCountAndFlags & s_refCountMaskBufferOwnership; }
     238    bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; }
    277239
    278240    // unshared data
    279241    UChar* m_data;
     242    union {
     243        void* m_buffer;
     244        UStringImpl* m_bufferSubstring;
     245        SharedUChar* m_bufferShared;
     246    };
    280247    int m_length;
    281     unsigned m_refCount;
    282     mutable unsigned m_hash : 31;
    283     mutable unsigned m_isIdentifier : 1;
    284     UntypedPtrAndBitfield m_dataBuffer;
     248    unsigned m_refCountAndFlags;
     249    mutable unsigned m_hash;
    285250
    286251    JS_EXPORTDATA static UStringImpl* s_empty;
Note: See TracChangeset for help on using the changeset viewer.