Changeset 55878 in webkit


Ignore:
Timestamp:
Mar 11, 2010 7:14:17 PM (14 years ago)
Author:
barraclough@apple.com
Message:

https://bugs.webkit.org/show_bug.cgi?id=36041
Remove unnecessary differences in common code between WebCore::StringImpl & JSC::UStringImpl

Reviewed by Oliver Hunt.

Much of the code in WebCore::StringImpl and JSC::UStringImpl is now very similar,
but has trivial and unnecessary formatting differences, such as the exact wording
of comments, missing ASSERTs, functions implemented in the .h vs .cpp etc.

JavaScriptCore:

  • runtime/Identifier.cpp:

(JSC::Identifier::add): UStringImpl::empty() now automatically hashes, uas per WebCore strings.
(JSC::Identifier::addSlowCase): UStringImpl::empty() now automatically hashes, uas per WebCore strings.

  • runtime/UStringImpl.cpp:

(JSC::UStringImpl::~UStringImpl): Only call bufferOwnership() once, add missing ASSERTs.
(JSC::UStringImpl::createUninitialized): Move from .h, not commonly called, no need to inline.
(JSC::UStringImpl::create): Move from .h, not commonly called, no need to inline.
(JSC::UStringImpl::sharedBuffer): Rewritten to more closely match WebCore implementation, remove need for separate baseSharedBuffer() method.

  • runtime/UStringImpl.h:

(JSC::UStringImpl::UStringImpl): Automatically hash static strings, ASSERT m_data & m_length are non-null/non-zero in non-static strings.
(JSC::UStringImpl::setHash): Add missing ASSERT.
(JSC::UStringImpl::create): Moved to .cpp / added missing check for empty string creation.
(JSC::UStringImpl::adopt): Vector.size() returns size_t, not unsigned.
(JSC::UStringImpl::cost): Renamed m_bufferSubstring -> m_substringBuffer
(JSC::UStringImpl::hash): Reordered in file.
(JSC::UStringImpl::existingHash): Reordered in file.
(JSC::UStringImpl::computeHash): Reordered in file, renamed parameter.
(JSC::UStringImpl::checkConsistency): rewrote ASSERT.
(JSC::UStringImpl::bufferOwnership): Return type should be BufferOwnership.
(JSC::UStringImpl::): Moved friends to head of class.

WebCore:

  • platform/text/StringImpl.cpp:

(WebCore::StringImpl::empty): Reordered in file, made empty()->characters() return a non-null value to match JSC.
(WebCore::StringImpl::createUninitialized): Added overflow check.
(WebCore::StringImpl::create): Reordered in file.
(WebCore::StringImpl::sharedBuffer): Reordered in file.

  • platform/text/StringImpl.h:

(WebCore::StringImpl::): Remove ThreadGlobalData as friend, move SharableUChar & SharedUChar to WebCore namespace.
(WebCore::StringImpl::StringImpl): Made static constructor method (used to create empty string) take arguments, to match JSC & prevent accidental use.
(WebCore::StringImpl::setHash): Added missing ASSERT.
(WebCore::StringImpl::adopt): Make adpot work with Vectors with a non-zero inline capacity.
(WebCore::StringImpl::characters): Mark as const to match JSC.
(WebCore::StringImpl::hash): Use !m_hash instead of m_hash == 0.
(WebCore::StringImpl::computeHash): Remove redundant 'inline'.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r55871 r55878  
     12010-03-11  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=36041
     6        Remove unnecessary differences in common code between WebCore::StringImpl & JSC::UStringImpl
     7
     8        Much of the code in WebCore::StringImpl and JSC::UStringImpl is now very similar,
     9        but has trivial and unnecessary formatting differences, such as the exact wording
     10        of comments, missing ASSERTs, functions implemented in the .h vs .cpp etc.
     11
     12        * runtime/Identifier.cpp:
     13        (JSC::Identifier::add): UStringImpl::empty() now automatically hashes, uas per WebCore strings.
     14        (JSC::Identifier::addSlowCase): UStringImpl::empty() now automatically hashes, uas per WebCore strings.
     15        * runtime/UStringImpl.cpp:
     16        (JSC::UStringImpl::~UStringImpl): Only call bufferOwnership() once, add missing ASSERTs.
     17        (JSC::UStringImpl::createUninitialized): Move from .h, not commonly called, no need to inline.
     18        (JSC::UStringImpl::create): Move from .h, not commonly called, no need to inline.
     19        (JSC::UStringImpl::sharedBuffer): Rewritten to more closely match WebCore implementation, remove need for separate baseSharedBuffer() method.
     20        * runtime/UStringImpl.h:
     21        (JSC::UStringImpl::UStringImpl): Automatically hash static strings, ASSERT m_data & m_length are non-null/non-zero in non-static strings.
     22        (JSC::UStringImpl::setHash): Add missing ASSERT.
     23        (JSC::UStringImpl::create): Moved to .cpp / added missing check for empty string creation.
     24        (JSC::UStringImpl::adopt): Vector.size() returns size_t, not unsigned.
     25        (JSC::UStringImpl::cost): Renamed m_bufferSubstring -> m_substringBuffer
     26        (JSC::UStringImpl::hash): Reordered in file.
     27        (JSC::UStringImpl::existingHash): Reordered in file.
     28        (JSC::UStringImpl::computeHash): Reordered in file, renamed parameter.
     29        (JSC::UStringImpl::checkConsistency): rewrote ASSERT.
     30        (JSC::UStringImpl::bufferOwnership): Return type should be BufferOwnership.
     31        (JSC::UStringImpl::): Moved friends to head of class.
     32
    1332010-03-11  Mark Rowe  <mrowe@apple.com>
    234
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r55825 r55878  
    108108__ZN3JSC11UStringImpl12sharedBufferEv
    109109__ZN3JSC11UStringImpl5emptyEv
     110__ZN3JSC11UStringImpl6createEN3WTF10PassRefPtrINS1_21CrossThreadRefCountedINS1_16OwnFastMallocPtrIKtEEEEEEPS5_j
    110111__ZN3JSC11UStringImplD1Ev
    111112__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
  • trunk/JavaScriptCore/runtime/Identifier.cpp

    r55833 r55878  
    4444            (*iter)->setIsIdentifier(false);
    4545    }
    46    
     46
    4747    std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value)
    4848    {
     
    130130        return rep;
    131131    }
    132     if (!c[0]) {
    133         UString::Rep::empty()->hash();
     132    if (!c[0])
    134133        return UString::Rep::empty();
    135     }
    136134    if (!c[1])
    137135        return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0])));
     
    194192            return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
    195193    }
    196     if (!length) {
    197         UString::Rep::empty()->hash();
     194    if (!length)
    198195        return UString::Rep::empty();
    199     }
    200196    UCharBuffer buf = {s, length};
    201197    pair<HashSet<UString::Rep*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf);
     
    225221            }
    226222    }
    227     if (!r->length()) {
    228         UString::Rep::empty()->hash();
     223    if (!r->length())
    229224        return UString::Rep::empty();
    230     }
    231225    return *globalData->identifierTable->add(r).first;
    232226}
  • trunk/JavaScriptCore/runtime/UStringImpl.cpp

    r55825 r55878  
    3737namespace JSC {
    3838
     39static const unsigned minLengthToShare = 20;
     40
     41UStringImpl::~UStringImpl()
     42{
     43    ASSERT(!isStatic());
     44    checkConsistency();
     45
     46    if (isIdentifier())
     47        Identifier::remove(this);
     48
     49    BufferOwnership ownership = bufferOwnership();
     50    if (ownership != BufferInternal) {
     51        if (ownership == BufferOwned) {
     52            ASSERT(!m_sharedBuffer);
     53            ASSERT(m_data);
     54            fastFree(const_cast<UChar*>(m_data));
     55        } else if (ownership == BufferSubstring) {
     56            ASSERT(m_substringBuffer);
     57            m_substringBuffer->deref();
     58        } else {
     59            ASSERT(ownership == BufferShared);
     60            ASSERT(m_sharedBuffer);
     61            m_sharedBuffer->deref();
     62        }
     63    }
     64}
     65
    3966UStringImpl* UStringImpl::empty()
    4067{
     
    4471    DEFINE_STATIC_LOCAL(UStringImpl, emptyString, (invalidNonNullUCharPtr, 0, ConstructStaticString));
    4572    return &emptyString;
     73}
     74
     75PassRefPtr<UStringImpl> UStringImpl::createUninitialized(unsigned length, UChar*& data)
     76{
     77    if (!length) {
     78        data = 0;
     79        return empty();
     80    }
     81
     82    // Allocate a single buffer large enough to contain the StringImpl
     83    // struct as well as the data which it contains. This removes one
     84    // heap allocation from this call.
     85    if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar)))
     86        CRASH();
     87    size_t size = sizeof(UStringImpl) + length * sizeof(UChar);
     88    UStringImpl* string = static_cast<UStringImpl*>(fastMalloc(size));
     89
     90    data = reinterpret_cast<UChar*>(string + 1);
     91    return adoptRef(new (string) UStringImpl(length));
    4692}
    4793
     
    78124}
    79125
    80 SharedUChar* UStringImpl::baseSharedBuffer()
     126PassRefPtr<UStringImpl> UStringImpl::create(PassRefPtr<SharedUChar> sharedBuffer, const UChar* buffer, unsigned length)
    81127{
    82     ASSERT((bufferOwnership() == BufferShared)
    83         || ((bufferOwnership() == BufferOwned) && !m_buffer));
    84 
    85     if (bufferOwnership() != BufferShared) {
    86         m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
    87         m_bufferShared = SharedUChar::create(new SharableUChar(m_data)).releaseRef();
    88     }
    89 
    90     return m_bufferShared;
     128    if (!length)
     129        return empty();
     130    return adoptRef(new UStringImpl(buffer, length, sharedBuffer));
    91131}
    92132
    93133SharedUChar* UStringImpl::sharedBuffer()
    94134{
    95     if (m_length < s_minLengthToShare)
     135    if (m_length < minLengthToShare)
    96136        return 0;
     137    // All static strings are smaller that the minimim length to share.
    97138    ASSERT(!isStatic());
    98139
    99     UStringImpl* owner = bufferOwnerString();
    100     if (owner->bufferOwnership() == BufferInternal)
     140    BufferOwnership ownership = bufferOwnership();
     141
     142    if (ownership == BufferInternal)
    101143        return 0;
     144    if (ownership == BufferSubstring)
     145        return m_substringBuffer->sharedBuffer();
     146    if (ownership == BufferOwned) {
     147        ASSERT(!m_sharedBuffer);
     148        m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).releaseRef();
     149        m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
     150    }
    102151
    103     return owner->baseSharedBuffer();
    104 }
    105 
    106 UStringImpl::~UStringImpl()
    107 {
    108     ASSERT(!isStatic());
    109     checkConsistency();
    110 
    111     if (isIdentifier())
    112         Identifier::remove(this);
    113 
    114     if (bufferOwnership() != BufferInternal) {
    115         if (bufferOwnership() == BufferOwned)
    116             fastFree(const_cast<UChar*>(m_data));
    117         else if (bufferOwnership() == BufferSubstring)
    118             m_bufferSubstring->deref();
    119         else {
    120             ASSERT(bufferOwnership() == BufferShared);
    121             m_bufferShared->deref();
    122         }
    123     }
     152    ASSERT(bufferOwnership() == BufferShared);
     153    ASSERT(m_sharedBuffer);
     154    return m_sharedBuffer;
    124155}
    125156
  • trunk/JavaScriptCore/runtime/UStringImpl.h

    r55833 r55878  
    106106
    107107class UStringImpl : public UStringOrRopeImpl {
     108    friend class CStringTranslator;
     109    friend class UCharBufferTranslator;
     110    friend class JIT;
     111    friend class SmallStringsStorage;
     112    friend class UStringOrRopeImpl;
     113    friend void initializeUString();
     114private:
     115    // For SmallStringStorage, which allocates an array and uses an in-place new.
     116    UStringImpl() { }
     117
     118    // Used to construct static strings, which have an special refCount that can never hit zero.
     119    // This means that the static string will never be destroyed, which is important because
     120    // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
     121    UStringImpl(const UChar* characters, unsigned length, StaticStringConstructType)
     122        : UStringOrRopeImpl(length, ConstructStaticString)
     123        , m_data(characters)
     124        , m_buffer(0)
     125        , m_hash(0)
     126    {
     127        hash();
     128        checkConsistency();
     129    }
     130
     131    // Create a normal string with internal storage (BufferInternal)
     132    UStringImpl(unsigned length)
     133        : UStringOrRopeImpl(length, BufferInternal)
     134        , m_data(reinterpret_cast<UChar*>(this + 1))
     135        , m_buffer(0)
     136        , m_hash(0)
     137    {
     138        ASSERT(m_data);
     139        ASSERT(m_length);
     140        checkConsistency();
     141    }
     142
     143    // Create a UStringImpl adopting ownership of the provided buffer (BufferOwned)
     144    UStringImpl(const UChar* characters, unsigned length)
     145        : UStringOrRopeImpl(length, BufferOwned)
     146        , m_data(characters)
     147        , m_buffer(0)
     148        , m_hash(0)
     149    {
     150        ASSERT(m_data);
     151        ASSERT(m_length);
     152        checkConsistency();
     153    }
     154
     155    // Used to create new strings that are a substring of an existing UStringImpl (BufferSubstring)
     156    UStringImpl(const UChar* characters, unsigned length, PassRefPtr<UStringImpl> base)
     157        : UStringOrRopeImpl(length, BufferSubstring)
     158        , m_data(characters)
     159        , m_substringBuffer(base.releaseRef())
     160        , m_hash(0)
     161    {
     162        ASSERT(m_data);
     163        ASSERT(m_length);
     164        checkConsistency();
     165    }
     166
     167    // Used to construct new strings sharing an existing SharedUChar (BufferShared)
     168    UStringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
     169        : UStringOrRopeImpl(length, BufferShared)
     170        , m_data(characters)
     171        , m_sharedBuffer(sharedBuffer.releaseRef())
     172        , m_hash(0)
     173    {
     174        ASSERT(m_data);
     175        ASSERT(m_length);
     176        checkConsistency();
     177    }
     178
     179    // For use only by Identifier's XXXTranslator helpers.
     180    void setHash(unsigned hash)
     181    {
     182        ASSERT(!m_hash);
     183        ASSERT(hash == computeHash(m_data, m_length));
     184        m_hash = hash;
     185    }
     186
    108187public:
    109     template<size_t inlineCapacity>
    110     static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
    111     {
    112         if (unsigned length = vector.size()) {
    113             ASSERT(vector.data());
    114             return adoptRef(new UStringImpl(vector.releaseBuffer(), length));
    115         }
    116         return empty();
    117     }
    118 
    119     static PassRefPtr<UStringImpl> create(const UChar* buffer, unsigned length);
    120     static PassRefPtr<UStringImpl> create(const char* c, unsigned length);
    121     static PassRefPtr<UStringImpl> create(const char* c);
    122 
     188    ~UStringImpl();
     189
     190    static PassRefPtr<UStringImpl> create(const UChar*, unsigned length);
     191    static PassRefPtr<UStringImpl> create(const char*, unsigned length);
     192    static PassRefPtr<UStringImpl> create(const char*);
     193    static PassRefPtr<UStringImpl> create(PassRefPtr<SharedUChar>, const UChar*, unsigned length);
    123194    static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, unsigned offset, unsigned length)
    124195    {
     196        if (!length)
     197            return empty();
    125198        ASSERT(rep);
    126199        rep->checkConsistency();
    127         return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->bufferOwnerString()));
    128     }
    129 
    130     static PassRefPtr<UStringImpl> create(PassRefPtr<SharedUChar> sharedBuffer, const UChar* buffer, unsigned length)
    131     {
    132         return adoptRef(new UStringImpl(buffer, length, sharedBuffer));
    133     }
    134 
    135     static PassRefPtr<UStringImpl> createUninitialized(unsigned length, UChar*& output)
    136     {
    137         if (!length) {
    138             output = 0;
    139             return empty();
    140         }
    141 
    142         if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar)))
    143             CRASH();
    144         UStringImpl* resultImpl = static_cast<UStringImpl*>(fastMalloc(sizeof(UChar) * length + sizeof(UStringImpl)));
    145         output = reinterpret_cast<UChar*>(resultImpl + 1);
    146         return adoptRef(new(resultImpl) UStringImpl(length));
    147     }
    148 
     200        UStringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get();
     201        return adoptRef(new UStringImpl(rep->m_data + offset, length, ownerRep));
     202    }
     203
     204    static PassRefPtr<UStringImpl> createUninitialized(unsigned length, UChar*& output);
    149205    static PassRefPtr<UStringImpl> tryCreateUninitialized(unsigned length, UChar*& output)
    150206    {
     
    163219    }
    164220
     221    template<size_t inlineCapacity>
     222    static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
     223    {
     224        if (size_t size = vector.size()) {
     225            ASSERT(vector.data());
     226            return adoptRef(new UStringImpl(vector.releaseBuffer(), size));
     227        }
     228        return empty();
     229    }
     230
    165231    SharedUChar* sharedBuffer();
    166232    const UChar* characters() const { return m_data; }
     233
    167234    size_t cost()
    168235    {
    169236        // For substrings, return the cost of the base string.
    170237        if (bufferOwnership() == BufferSubstring)
    171             return m_bufferSubstring->cost();
     238            return m_substringBuffer->cost();
    172239
    173240        if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) {
     
    177244        return 0;
    178245    }
    179     unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; }
    180     unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers
    181     void setHash(unsigned hash) { ASSERT(hash == computeHash(m_data, m_length)); m_hash = hash; } // fast path for Identifiers
     246
    182247    bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; }
    183248    void setIsIdentifier(bool isIdentifier)
     
    189254    }
    190255
     256// SYNC SYNC SYNC
     257// SYNC SYNC SYNC
     258// SYNC SYNC SYNC
     259// SYNC SYNC SYNC
     260// SYNC SYNC SYNC
     261
     262    unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; }
     263    unsigned existingHash() const { ASSERT(m_hash); return m_hash; }
     264    static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); }
     265    static unsigned computeHash(const char* data, unsigned length) { return WTF::stringHash(data, length); }
     266    static unsigned computeHash(const char* data) { return WTF::stringHash(data); }
     267
    191268    ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; }
     269
     270    static UStringImpl* empty();
    192271
    193272    static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
     
    200279    }
    201280
    202     static unsigned computeHash(const UChar* s, unsigned length) { return WTF::stringHash(s, length); }
    203     static unsigned computeHash(const char* s, unsigned length) { return WTF::stringHash(s, length); }
    204     static unsigned computeHash(const char* s) { return WTF::stringHash(s); }
    205 
    206     static UStringImpl* empty();
    207 
    208281    ALWAYS_INLINE void checkConsistency() const
    209282    {
    210283        // There is no recursion of substrings.
    211         ASSERT(bufferOwnerString()->bufferOwnership() != BufferSubstring);
     284        ASSERT((bufferOwnership() != BufferSubstring) || (m_substringBuffer->bufferOwnership() != BufferSubstring));
    212285        // Static strings cannot be put in identifier tables, because they are globally shared.
    213286        ASSERT(!isStatic() || !isIdentifier());
     
    215288
    216289private:
    217     // For SmallStringStorage, which allocates an array and uses an in-place new.
    218     UStringImpl() { }
    219 
    220     // Used to construct normal strings with an internal buffer.
    221     UStringImpl(unsigned length)
    222         : UStringOrRopeImpl(length, BufferInternal)
    223         , m_data(reinterpret_cast<UChar*>(this + 1))
    224         , m_buffer(0)
    225         , m_hash(0)
    226     {
    227         checkConsistency();
    228     }
    229 
    230     // Used to construct normal strings with an external buffer.
    231     UStringImpl(const UChar* data, unsigned length)
    232         : UStringOrRopeImpl(length, BufferOwned)
    233         , m_data(data)
    234         , m_buffer(0)
    235         , m_hash(0)
    236     {
    237         checkConsistency();
    238     }
    239 
    240     // Used to construct static strings, which have an special refCount that can never hit zero.
    241     // This means that the static string will never be destroyed, which is important because
    242     // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
    243     UStringImpl(const UChar* data, unsigned length, StaticStringConstructType)
    244         : UStringOrRopeImpl(length, ConstructStaticString)
    245         , m_data(data)
    246         , m_buffer(0)
    247         , m_hash(0)
    248     {
    249         checkConsistency();
    250     }
    251 
    252     // Used to create new strings that are a substring of an existing string.
    253     UStringImpl(const UChar* data, unsigned length, PassRefPtr<UStringImpl> base)
    254         : UStringOrRopeImpl(length, BufferSubstring)
    255         , m_data(data)
    256         , m_bufferSubstring(base.releaseRef())
    257         , m_hash(0)
    258     {
    259         // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes
    260         // that all pointers will be at least 8-byte aligned, we cannot guarantee that of
    261         // UStringImpls that are not heap allocated.
    262         ASSERT(m_bufferSubstring->length());
    263         ASSERT(!m_bufferSubstring->isStatic());
    264         checkConsistency();
    265     }
    266 
    267     // Used to construct new strings sharing an existing shared buffer.
    268     UStringImpl(const UChar* data, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
    269         : UStringOrRopeImpl(length, BufferShared)
    270         , m_data(data)
    271         , m_bufferShared(sharedBuffer.releaseRef())
    272         , m_hash(0)
    273     {
    274         checkConsistency();
    275     }
    276 
    277     ~UStringImpl();
    278 
    279290    // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings.
    280     static const unsigned s_minLengthToShare = 10;
    281291    static const unsigned s_copyCharsInlineCutOff = 20;
    282292
    283     UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring :  this; }
    284     const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring :  this; }
    285     SharedUChar* baseSharedBuffer();
    286     unsigned bufferOwnership() const { return m_refCountAndFlags & s_refCountMaskBufferOwnership; }
     293    BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); }
    287294    bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; }
    288295
     
    291298    union {
    292299        void* m_buffer;
    293         UStringImpl* m_bufferSubstring;
    294         SharedUChar* m_bufferShared;
     300        UStringImpl* m_substringBuffer;
     301        SharedUChar* m_sharedBuffer;
    295302    };
    296303    mutable unsigned m_hash;
    297 
    298     friend class JIT;
    299     friend class SmallStringsStorage;
     304};
     305
     306class URopeImpl : public UStringOrRopeImpl {
    300307    friend class UStringOrRopeImpl;
    301     friend void initializeUString();
    302 };
    303 
    304 class URopeImpl : public UStringOrRopeImpl {
    305308public:
    306309    // A URopeImpl is composed from a set of smaller strings called Fibers.
     
    340343    unsigned m_fiberCount;
    341344    Fiber m_fibers[1];
    342 
    343     friend class UStringOrRopeImpl;
    344345};
    345346
  • trunk/WebCore/ChangeLog

    r55871 r55878  
     12010-03-11  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=36041
     6        Remove unnecessary differences in common code between WebCore::StringImpl & JSC::UStringImpl
     7
     8        Much of the code in WebCore::StringImpl and JSC::UStringImpl is now very similar,
     9        but has trivial and unnecessary formatting differences, such as the exact wording
     10        of comments, missing ASSERTs, functions implemented in the .h vs .cpp etc.
     11
     12        * platform/text/StringImpl.cpp:
     13        (WebCore::StringImpl::empty): Reordered in file, made empty()->characters() return a non-null value to match JSC.
     14        (WebCore::StringImpl::createUninitialized): Added overflow check.
     15        (WebCore::StringImpl::create): Reordered in file.
     16        (WebCore::StringImpl::sharedBuffer): Reordered in file.
     17        * platform/text/StringImpl.h:
     18        (WebCore::StringImpl::): Remove ThreadGlobalData as friend, move SharableUChar & SharedUChar to WebCore namespace.
     19        (WebCore::StringImpl::StringImpl): Made static constructor method (used to create empty string) take arguments, to match JSC & prevent accidental use.
     20        (WebCore::StringImpl::setHash): Added missing ASSERT.
     21        (WebCore::StringImpl::adopt): Make adpot work with Vectors with a non-zero inline capacity.
     22        (WebCore::StringImpl::characters): Mark as const to match JSC.
     23        (WebCore::StringImpl::hash): Use !m_hash instead of m_hash == 0.
     24        (WebCore::StringImpl::computeHash): Remove redundant 'inline'.
     25
    1262010-03-11  Mark Rowe  <mrowe@apple.com>
    227
  • trunk/WebCore/platform/text/StringImpl.cpp

    r55832 r55878  
    3434#include "TextBreakIterator.h"
    3535#include "TextEncoding.h"
    36 #include "ThreadGlobalData.h"
    3736#include <runtime/UString.h>
    3837#include <wtf/dtoa.h>
     
    4746
    4847static const unsigned minLengthToShare = 20;
    49 
    50 static inline UChar* newUCharVector(unsigned n)
    51 {
    52     return static_cast<UChar*>(fastMalloc(sizeof(UChar) * n));
    53 }
    54 
    55 // This constructor is used only to create the empty string.
    56 StringImpl::StringImpl()
    57     : m_data(0)
    58     , m_sharedBuffer(0)
    59     , m_length(0)
    60     , m_refCountAndFlags(s_refCountFlagStatic | BufferInternal)
    61     , m_hash(0)
    62 {
    63     // Ensure that the hash is computed so that AtomicStringHash can call existingHash()
    64     // with impunity. The empty string is special because it is never entered into
    65     // AtomicString's HashKey, but still needs to compare correctly.
    66     hash();
    67 }
    68 
    69 inline StringImpl::StringImpl(unsigned length)
    70     : m_data(reinterpret_cast<const UChar*>(this + 1))
    71     , m_sharedBuffer(0)
    72     , m_length(length)
    73     , m_refCountAndFlags(s_refCountIncrement | BufferInternal)
    74     , m_hash(0)
    75 {
    76     ASSERT(m_data);
    77     ASSERT(m_length);
    78 }
    79 
    80 inline StringImpl::StringImpl(const UChar* characters, unsigned length)
    81     : m_data(characters)
    82     , m_sharedBuffer(0)
    83     , m_length(length)
    84     , m_refCountAndFlags(s_refCountIncrement | BufferOwned)
    85     , m_hash(0)
    86 {
    87     ASSERT(m_data);
    88     ASSERT(m_length);
    89 }
    90 
    91 inline StringImpl::StringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
    92     : m_data(characters)
    93     , m_sharedBuffer(sharedBuffer.releaseRef())
    94     , m_length(length)
    95     , m_refCountAndFlags(s_refCountIncrement | BufferShared)
    96     , m_hash(0)
    97 {
    98     ASSERT(m_data);
    99     ASSERT(m_length);
    100 }
    10148
    10249StringImpl::~StringImpl()
     
    12168StringImpl* StringImpl::empty()
    12269{
    123     DEFINE_STATIC_LOCAL(StringImpl, emptyString, ());
     70    // A non-null pointer at an invalid address (in page zero) so that if it were to be accessed we
     71    // should catch the error with fault (however it should be impossible to access, since length is zero).
     72    static const UChar* invalidNonNullUCharPtr = reinterpret_cast<UChar*>(static_cast<intptr_t>(1));
     73    DEFINE_STATIC_LOCAL(StringImpl, emptyString, (invalidNonNullUCharPtr, 0, ConstructStaticString));
    12474    return &emptyString;
     75}
     76
     77PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data)
     78{
     79    if (!length) {
     80        data = 0;
     81        return empty();
     82    }
     83
     84    // Allocate a single buffer large enough to contain the StringImpl
     85    // struct as well as the data which it contains. This removes one
     86    // heap allocation from this call.
     87    if (length > ((std::numeric_limits<size_t>::max() - sizeof(StringImpl)) / sizeof(UChar)))
     88        CRASH();
     89    size_t size = sizeof(StringImpl) + length * sizeof(UChar);
     90    StringImpl* string = static_cast<StringImpl*>(fastMalloc(size));
     91
     92    data = reinterpret_cast<UChar*>(string + 1);
     93    return adoptRef(new (string) StringImpl(length));
     94}
     95
     96PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
     97{
     98    if (!characters || !length)
     99        return empty();
     100
     101    UChar* data;
     102    PassRefPtr<StringImpl> string = createUninitialized(length, data);
     103    memcpy(data, characters, length * sizeof(UChar));
     104    return string;
     105}
     106
     107PassRefPtr<StringImpl> StringImpl::create(const char* characters, unsigned length)
     108{
     109    if (!characters || !length)
     110        return empty();
     111
     112    UChar* data;
     113    PassRefPtr<StringImpl> string = createUninitialized(length, data);
     114    for (unsigned i = 0; i != length; ++i) {
     115        unsigned char c = characters[i];
     116        data[i] = c;
     117    }
     118    return string;
     119}
     120
     121PassRefPtr<StringImpl> StringImpl::create(const char* string)
     122{
     123    if (!string)
     124        return empty();
     125    return create(string, strlen(string));
     126}
     127
     128SharedUChar* StringImpl::sharedBuffer()
     129{
     130    if (m_length < minLengthToShare)
     131        return 0;
     132
     133    BufferOwnership ownership = bufferOwnership();
     134
     135    if (ownership == BufferInternal)
     136        return 0;
     137    if (ownership == BufferOwned) {
     138        ASSERT(!m_sharedBuffer);
     139        m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).releaseRef();
     140        m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
     141    }
     142
     143    ASSERT(bufferOwnership() == BufferShared);
     144    ASSERT(m_sharedBuffer);
     145    return m_sharedBuffer;
    125146}
    126147
     
    914935}
    915936
    916 PassRefPtr<StringImpl> StringImpl::adopt(Vector<UChar>& vector)
    917 {
    918     size_t size = vector.size();
    919     if (size == 0)
    920         return empty();
    921     return adoptRef(new StringImpl(vector.releaseBuffer(), size));
    922 }
    923 
    924 PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data)
    925 {
    926     if (!length) {
    927         data = 0;
    928         return empty();
    929     }
    930 
    931     // Allocate a single buffer large enough to contain the StringImpl
    932     // struct as well as the data which it contains. This removes one
    933     // heap allocation from this call.
    934     size_t size = sizeof(StringImpl) + length * sizeof(UChar);
    935     StringImpl* string = static_cast<StringImpl*>(fastMalloc(size));
    936     data = reinterpret_cast<UChar*>(string + 1);
    937     string = new (string) StringImpl(length);
    938     return adoptRef(string);
    939 }
    940 
    941 PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
    942 {
    943     if (!characters || !length)
    944         return empty();
    945 
    946     UChar* data;
    947     PassRefPtr<StringImpl> string = createUninitialized(length, data);
    948     memcpy(data, characters, length * sizeof(UChar));
    949     return string;
    950 }
    951 
    952 PassRefPtr<StringImpl> StringImpl::create(const char* characters, unsigned length)
    953 {
    954     if (!characters || !length)
    955         return empty();
    956 
    957     UChar* data;
    958     PassRefPtr<StringImpl> string = createUninitialized(length, data);
    959     for (unsigned i = 0; i != length; ++i) {
    960         unsigned char c = characters[i];
    961         data[i] = c;
    962     }
    963     return string;
    964 }
    965 
    966 PassRefPtr<StringImpl> StringImpl::create(const char* string)
    967 {
    968     if (!string)
    969         return empty();
    970     return create(string, strlen(string));
    971 }
    972 
    973937#if USE(JSC)
    974938PassRefPtr<StringImpl> StringImpl::create(const JSC::UString& str)
     
    1018982}
    1019983
    1020 StringImpl::SharedUChar* StringImpl::sharedBuffer()
    1021 {
    1022     if (m_length < minLengthToShare)
    1023         return 0;
    1024 
    1025     BufferOwnership ownership = bufferOwnership();
    1026 
    1027     if (ownership == BufferInternal)
    1028         return 0;
    1029 
    1030     if (ownership == BufferOwned) {
    1031         ASSERT(!m_sharedBuffer);
    1032         m_sharedBuffer = SharedUChar::create(new SharableUChar(const_cast<UChar*>(m_data))).releaseRef();
    1033         m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
    1034     }
    1035 
    1036     ASSERT(bufferOwnership() == BufferShared);
    1037     ASSERT(m_sharedBuffer);
    1038     return m_sharedBuffer;
    1039 }
    1040 
    1041984} // namespace WebCore
  • trunk/WebCore/platform/text/StringImpl.h

    r55825 r55878  
    5757enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive };
    5858
     59typedef OwnFastMallocPtr<const UChar> SharableUChar;
     60typedef CrossThreadRefCounted<SharableUChar> SharedUChar;
    5961typedef bool (*CharacterMatchFunctionPtr)(UChar);
    6062
     
    6466    friend struct UCharBufferTranslator;
    6567private:
    66     friend class ThreadGlobalData;
    67 
    6868    enum BufferOwnership {
    6969        BufferInternal,
     
    7272    };
    7373
    74     typedef OwnFastMallocPtr<const UChar> SharableUChar;
    75     typedef CrossThreadRefCounted<SharableUChar> SharedUChar;
    76 
    77     // Used to create the empty string (""), automatically hashes.
    78     StringImpl();
    79     // Create a StringImpl with internal storage (BufferInternal)
    80     StringImpl(unsigned length);
     74    // Used to construct static strings, which have an special refCount that can never hit zero.
     75    // This means that the static string will never be destroyed, which is important because
     76    // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
     77    enum StaticStringConstructType { ConstructStaticString };
     78    StringImpl(const UChar* characters, unsigned length, StaticStringConstructType)
     79        : m_data(characters)
     80        , m_sharedBuffer(0)
     81        , m_length(length)
     82        , m_refCountAndFlags(s_refCountFlagStatic | BufferInternal)
     83        , m_hash(0)
     84    {
     85        // Ensure that the hash is computed so that AtomicStringHash can call existingHash()
     86        // with impunity. The empty string is special because it is never entered into
     87        // AtomicString's HashKey, but still needs to compare correctly.
     88        hash();
     89    }
     90
     91    // Create a normal string with internal storage (BufferInternal)
     92    StringImpl(unsigned length)
     93        : m_data(reinterpret_cast<const UChar*>(this + 1))
     94        , m_sharedBuffer(0)
     95        , m_length(length)
     96        , m_refCountAndFlags(s_refCountIncrement | BufferInternal)
     97        , m_hash(0)
     98    {
     99        ASSERT(m_data);
     100        ASSERT(m_length);
     101    }
     102
    81103    // Create a StringImpl adopting ownership of the provided buffer (BufferOwned)
    82     StringImpl(const UChar*, unsigned length);
    83     // Create a StringImpl using a shared buffer (BufferShared)
    84     StringImpl(const UChar*, unsigned length, PassRefPtr<SharedUChar>);
     104    StringImpl(const UChar* characters, unsigned length)
     105        : m_data(characters)
     106        , m_sharedBuffer(0)
     107        , m_length(length)
     108        , m_refCountAndFlags(s_refCountIncrement | BufferOwned)
     109        , m_hash(0)
     110    {
     111        ASSERT(m_data);
     112        ASSERT(m_length);
     113    }
     114
     115    // Used to construct new strings sharing an existing SharedUChar (BufferShared)
     116    StringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
     117        : m_data(characters)
     118        , m_sharedBuffer(sharedBuffer.releaseRef())
     119        , m_length(length)
     120        , m_refCountAndFlags(s_refCountIncrement | BufferShared)
     121        , m_hash(0)
     122    {
     123        ASSERT(m_data);
     124        ASSERT(m_length);
     125    }
    85126
    86127    // For use only by AtomicString's XXXTranslator helpers.
    87     void setHash(unsigned hash) { ASSERT(!m_hash); m_hash = hash; }
    88    
     128    void setHash(unsigned hash)
     129    {
     130        ASSERT(!m_hash);
     131        ASSERT(hash == computeHash(m_data, m_length));
     132        m_hash = hash;
     133    }
     134
    89135public:
    90136    ~StringImpl();
     
    93139    static PassRefPtr<StringImpl> create(const char*, unsigned length);
    94140    static PassRefPtr<StringImpl> create(const char*);
    95     static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
    96 
    97     static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
    98 
    99     static PassRefPtr<StringImpl> createStrippingNullCharacters(const UChar*, unsigned length);
    100     static PassRefPtr<StringImpl> adopt(StringBuffer&);
    101     static PassRefPtr<StringImpl> adopt(Vector<UChar>&);
    102141#if USE(JSC)
    103142    static PassRefPtr<StringImpl> create(const JSC::UString&);
     
    105144#endif
    106145
     146    static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
     147    static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
     148    static PassRefPtr<StringImpl> createStrippingNullCharacters(const UChar*, unsigned length);
     149
     150    template<size_t inlineCapacity>
     151    static PassRefPtr<StringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
     152    {
     153        if (size_t size = vector.size()) {
     154            ASSERT(vector.data());
     155            return adoptRef(new StringImpl(vector.releaseBuffer(), size));
     156        }
     157        return empty();
     158    }
     159    static PassRefPtr<StringImpl> adopt(StringBuffer&);
     160
    107161    SharedUChar* sharedBuffer();
    108     const UChar* characters() { return m_data; }
     162    const UChar* characters() const { return m_data; }
    109163    unsigned length() { return m_length; }
    110164
     
    114168    void setInTable() { m_refCountAndFlags |= s_refCountFlagInTable; }
    115169
    116     unsigned hash() { if (m_hash == 0) m_hash = computeHash(m_data, m_length); return m_hash; }
     170// SYNC SYNC SYNC
     171// SYNC SYNC SYNC
     172// SYNC SYNC SYNC
     173// SYNC SYNC SYNC
     174// SYNC SYNC SYNC
     175
     176    unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; }
    117177    unsigned existingHash() const { ASSERT(m_hash); return m_hash; }
    118     inline static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); }
    119     inline static unsigned computeHash(const char* data) { return WTF::stringHash(data); }
     178    static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); }
     179    static unsigned computeHash(const char* data) { return WTF::stringHash(data); }
    120180
    121181    StringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; }
    122182    ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; }
    123183    ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic)) == s_refCountIncrement; }
     184
     185    static StringImpl* empty();
    124186
    125187    // Returns a StringImpl suitable for use on another thread.
     
    179241    PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*);
    180242
    181     static StringImpl* empty();
    182 
    183243    Vector<char> ascii();
    184244
     
    198258    static PassRefPtr<StringImpl> createStrippingNullCharactersSlowCase(const UChar*, unsigned length);
    199259   
    200     // The StringImpl struct and its data may be allocated within a single heap block.
    201     // In this case, the m_data pointer is an "internal buffer", and does not need to be deallocated.
    202260    BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); }
    203261
Note: See TracChangeset for help on using the changeset viewer.