Ignore:
Timestamp:
May 3, 2010, 4:03:37 PM (15 years ago)
Author:
[email protected]
Message:

Rolling out r58114 - this introduced memory leaks of
AtomicStrings then workers terminated.

Reviewed by NOBODY (reverting previous commit).

(JSC::ThunkHelpers::stringImplDataOffset):

  • runtime/Identifier.cpp:

(JSC::IdentifierTable::~IdentifierTable):
(JSC::IdentifierTable::add):
(JSC::IdentifierCStringTranslator::hash):
(JSC::IdentifierCStringTranslator::equal):
(JSC::IdentifierCStringTranslator::translate):
(JSC::Identifier::add):
(JSC::IdentifierUCharBufferTranslator::hash):
(JSC::IdentifierUCharBufferTranslator::equal):
(JSC::IdentifierUCharBufferTranslator::translate):
(JSC::Identifier::addSlowCase):

  • runtime/Identifier.h:
  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData):

  • runtime/JSGlobalData.h:
  • wtf/WTFThreadData.cpp:

(WTF::WTFThreadData::WTFThreadData):
(WTF::WTFThreadData::~WTFThreadData):

  • wtf/WTFThreadData.h:

(JSC::IdentifierTable::remove):
(JSC::IdentifierTable::literalTable):
(WTF::WTFThreadData::atomicStringTable):

  • wtf/text/AtomicString.cpp:

(WebCore::AtomicStringTable::create):
(WebCore::AtomicStringTable::table):
(WebCore::AtomicStringTable::destroy):
(WebCore::stringTable):
(WebCore::CStringTranslator::hash):
(WebCore::CStringTranslator::equal):
(WebCore::CStringTranslator::translate):
(WebCore::operator==):
(WebCore::AtomicString::add):
(WebCore::equal):
(WebCore::UCharBufferTranslator::hash):
(WebCore::UCharBufferTranslator::equal):
(WebCore::UCharBufferTranslator::translate):
(WebCore::HashAndCharactersTranslator::hash):
(WebCore::HashAndCharactersTranslator::equal):
(WebCore::HashAndCharactersTranslator::translate):
(WebCore::AtomicString::find):
(WebCore::AtomicString::remove):

  • wtf/text/AtomicStringTable.h: Removed.
  • wtf/text/StringImpl.cpp:

(WebCore::StringImpl::~StringImpl):

  • wtf/text/StringImpl.h:

(WebCore::StringImpl::inTable):
(WebCore::StringImpl::setInTable):
(WebCore::equal):

  • wtf/text/StringImplBase.h:

(WTF::StringImplBase::StringImplBase):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/wtf/text/AtomicString.cpp

    r58179 r58712  
    3232#include <wtf/Threading.h>
    3333#include <wtf/WTFThreadData.h>
    34 #include <wtf/text/AtomicStringTable.h>
    3534
    3635namespace WebCore {
    3736
    38 static inline AtomicStringTable& table()
    39 {
    40     return wtfThreadData().atomicStringTable();
    41 }
     37class AtomicStringTable {
     38public:
     39    static AtomicStringTable* create()
     40    {
     41        AtomicStringTable* table = new AtomicStringTable;
     42
     43        WTFThreadData& data = wtfThreadData();
     44        data.m_atomicStringTable = table;
     45        data.m_atomicStringTableDestructor = AtomicStringTable::destroy;
     46
     47        return table;
     48    }
     49
     50    HashSet<StringImpl*>& table()
     51    {
     52        return m_table;
     53    }
     54
     55private:
     56    static void destroy(AtomicStringTable* table)
     57    {
     58        delete table;
     59    }
     60
     61    HashSet<StringImpl*> m_table;
     62};
     63
     64static inline HashSet<StringImpl*>& stringTable()
     65{
     66    // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor).
     67    AtomicStringTable* table = wtfThreadData().atomicStringTable();
     68    if (UNLIKELY(!table))
     69        table = AtomicStringTable::create();
     70    return table->table();
     71}
     72
     73struct CStringTranslator {
     74    static unsigned hash(const char* c)
     75    {
     76        return StringImpl::computeHash(c);
     77    }
     78
     79    static bool equal(StringImpl* r, const char* s)
     80    {
     81        int length = r->length();
     82        const UChar* d = r->characters();
     83        for (int i = 0; i != length; ++i) {
     84            unsigned char c = s[i];
     85            if (d[i] != c)
     86                return false;
     87        }
     88        return s[length] == 0;
     89    }
     90
     91    static void translate(StringImpl*& location, const char* const& c, unsigned hash)
     92    {
     93        location = StringImpl::create(c).releaseRef();
     94        location->setHash(hash);
     95        location->setInTable();
     96    }
     97};
    4298
    4399bool operator==(const AtomicString& a, const char* b)
     
    48104    if ((!impl || !impl->characters()) || !b)
    49105        return false;
    50     return ::equal(impl, b);
     106    return CStringTranslator::equal(impl, b);
    51107}
    52108
     
    56112        return 0;
    57113    if (!*c)
    58         return StringImpl::empty();
    59     return table().add(c);
    60 }
     114        return StringImpl::empty();   
     115    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<const char*, CStringTranslator>(c);
     116    if (!addResult.second)
     117        return *addResult.first;
     118    return adoptRef(*addResult.first);
     119}
     120
     121struct UCharBuffer {
     122    const UChar* s;
     123    unsigned length;
     124};
     125
     126static inline bool equal(StringImpl* string, const UChar* characters, unsigned length)
     127{
     128    if (string->length() != length)
     129        return false;
     130
     131    // FIXME: perhaps we should have a more abstract macro that indicates when
     132    // going 4 bytes at a time is unsafe
     133#if CPU(ARM) || CPU(SH4)
     134    const UChar* stringCharacters = string->characters();
     135    for (unsigned i = 0; i != length; ++i) {
     136        if (*stringCharacters++ != *characters++)
     137            return false;
     138    }
     139    return true;
     140#else
     141    /* Do it 4-bytes-at-a-time on architectures where it's safe */
     142
     143    const uint32_t* stringCharacters = reinterpret_cast<const uint32_t*>(string->characters());
     144    const uint32_t* bufferCharacters = reinterpret_cast<const uint32_t*>(characters);
     145
     146    unsigned halfLength = length >> 1;
     147    for (unsigned i = 0; i != halfLength; ++i) {
     148        if (*stringCharacters++ != *bufferCharacters++)
     149            return false;
     150    }
     151
     152    if (length & 1 &&  *reinterpret_cast<const uint16_t*>(stringCharacters) != *reinterpret_cast<const uint16_t*>(bufferCharacters))
     153        return false;
     154
     155    return true;
     156#endif
     157}
     158
     159struct UCharBufferTranslator {
     160    static unsigned hash(const UCharBuffer& buf)
     161    {
     162        return StringImpl::computeHash(buf.s, buf.length);
     163    }
     164
     165    static bool equal(StringImpl* const& str, const UCharBuffer& buf)
     166    {
     167        return WebCore::equal(str, buf.s, buf.length);
     168    }
     169
     170    static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash)
     171    {
     172        location = StringImpl::create(buf.s, buf.length).releaseRef();
     173        location->setHash(hash);
     174        location->setInTable();
     175    }
     176};
     177
     178struct HashAndCharacters {
     179    unsigned hash;
     180    const UChar* characters;
     181    unsigned length;
     182};
     183
     184struct HashAndCharactersTranslator {
     185    static unsigned hash(const HashAndCharacters& buffer)
     186    {
     187        ASSERT(buffer.hash == StringImpl::computeHash(buffer.characters, buffer.length));
     188        return buffer.hash;
     189    }
     190
     191    static bool equal(StringImpl* const& string, const HashAndCharacters& buffer)
     192    {
     193        return WebCore::equal(string, buffer.characters, buffer.length);
     194    }
     195
     196    static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash)
     197    {
     198        location = StringImpl::create(buffer.characters, buffer.length).releaseRef();
     199        location->setHash(hash);
     200        location->setInTable();
     201    }
     202};
    61203
    62204PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length)
     
    68210        return StringImpl::empty();
    69211   
    70     return table().add(s, length);
     212    UCharBuffer buf = { s, length };
     213    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf);
     214
     215    // If the string is newly-translated, then we need to adopt it.
     216    // The boolean in the pair tells us if that is so.
     217    return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
    71218}
    72219
     
    78225    if (length == 0)
    79226        return StringImpl::empty();
    80 
    81     return table().add(s, length, existingHash);
     227   
     228    HashAndCharacters buffer = { existingHash, s, length };
     229    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
     230    if (!addResult.second)
     231        return *addResult.first;
     232    return adoptRef(*addResult.first);
    82233}
    83234
     
    87238        return 0;
    88239
    89     unsigned length = 0;
     240    int length = 0;
    90241    while (s[length] != UChar(0))
    91242        length++;
     
    94245        return StringImpl::empty();
    95246
    96     return table().add(s, length);
     247    UCharBuffer buf = {s, length};
     248    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf);
     249
     250    // If the string is newly-translated, then we need to adopt it.
     251    // The boolean in the pair tells us if that is so.
     252    return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
    97253}
    98254
    99255PassRefPtr<StringImpl> AtomicString::add(StringImpl* r)
    100256{
    101     if (!r || r->isAtomic())
     257    if (!r || r->inTable())
    102258        return r;
    103259
    104     // The singleton empty string is atomic.
    105     ASSERT(r->length());
     260    if (r->length() == 0)
     261        return StringImpl::empty();
    106262   
    107     return table().add(r);
     263    StringImpl* result = *stringTable().add(r).first;
     264    if (result == r)
     265        r->setInTable();
     266    return result;
    108267}
    109268
     
    115274    if (length == 0)
    116275        return static_cast<AtomicStringImpl*>(StringImpl::empty());
    117    
    118     return static_cast<AtomicStringImpl*>(table().find(s, length, existingHash));
     276
     277    HashAndCharacters buffer = { existingHash, s, length };
     278    HashSet<StringImpl*>::iterator iterator = stringTable().find<HashAndCharacters, HashAndCharactersTranslator>(buffer);
     279    if (iterator == stringTable().end())
     280        return 0;
     281    return static_cast<AtomicStringImpl*>(*iterator);
    119282}
    120283
    121284void AtomicString::remove(StringImpl* r)
    122285{
    123     table().remove(r);
     286    stringTable().remove(r);
    124287}
    125288   
Note: See TracChangeset for help on using the changeset viewer.