Ignore:
Timestamp:
Apr 18, 2008, 12:46:13 PM (17 years ago)
Author:
[email protected]
Message:

Reviewed by Darin.

Fix leaks during plugin tests (which actually excercise background JS), and potential
PAC brokenness that was not reported, but very likely.

The leaks shadowed a bigger problem with Identifier destruction. Identifier::remove involves
an IdentifierTable lookup, which is now a per-thread instance. Since garbage collection can
currently happen on a different thread than allocation, a wrong table was used.

No measurable change on SunSpider total, ~1% variation on individual tests.

  • kjs/ustring.cpp: (KJS::): (KJS::UString::Rep::create): (KJS::UString::Rep::destroy):
  • kjs/ustring.h: Replaced isIdentifier with a pointer to IdentifierTable, so that destruction can be done correctly. Took one bit from reportedCost, to avoid making UString::Rep larger (performance effect was measurable on SunSpider).
  • kjs/identifier.cpp: (KJS::IdentifierTable::IdentifierTable): (KJS::IdentifierTable::~IdentifierTable): (KJS::IdentifierTable::add): (KJS::IdentifierTable::remove): Make IdentifierTable a real class. Its destructor needs to zero out outstanding references, because some identifiers may briefly outlive it during thread destruction, and we don't want them to use their stale pointers.

(KJS::LiteralIdentifierTable):
(KJS::Identifier::add):
Now that LiteralIdentifierTable is per-thread and can be destroyed not just during application
shutdown, it is not appropriate to simply bump refcount for strings that get there; changed
the table to hold RefPtrs.

(KJS::CStringTranslator::translate):
(KJS::UCharBufferTranslator::translate):
(KJS::Identifier::addSlowCase):
(KJS::Identifier::remove):

  • kjs/identifier.h: (KJS::Identifier::add): Use and update UString::Rep::identifierTable as appropriate. Updating it is now done in IdentifierTable::add, not in translators.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/identifier.cpp

    r31944 r32222  
    5353namespace KJS {
    5454
    55 typedef HashSet<UString::Rep*> IdentifierTable;
    56 typedef HashMap<const char*, UString::Rep*, PtrHash<const char*> > LiteralIdentifierTable;
     55class IdentifierTable {
     56public:
     57    ~IdentifierTable()
     58    {
     59        HashSet<UString::Rep*>::iterator end = m_table.end();
     60        for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter)
     61            (*iter)->identifierTable = 0;
     62    }
     63   
     64    std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value)
     65    {
     66        std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add(value);
     67        (*result.first)->identifierTable = this;
     68        return result;
     69    }
     70
     71    template<typename U, typename V>
     72    std::pair<HashSet<UString::Rep*>::iterator, bool> add(U value)
     73    {
     74        std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add<U, V>(value);
     75        (*result.first)->identifierTable = this;
     76        return result;
     77    }
     78
     79    void remove(UString::Rep* r) { m_table.remove(r); }
     80
     81private:
     82    HashSet<UString::Rep*> m_table;
     83};
     84
     85typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable;
    5786
    5887static inline IdentifierTable& identifierTable()
     
    138167       
    139168        UString::Rep *r = UString::Rep::create(d, static_cast<int>(length)).releaseRef();
    140         r->isIdentifier = true;
    141169        r->rc = 0;
    142170        r->_hash = hash;
     
    166194    UString::Rep* addedString = *identifierTable().add<const char*, CStringTranslator>(c).first;
    167195    literalTableLocalRef.add(c, addedString);
    168     addedString->ref();
    169196
    170197    return addedString;
     
    195222       
    196223        UString::Rep *r = UString::Rep::create(d, buf.length).releaseRef();
    197         r->isIdentifier = true;
    198224        r->rc = 0;
    199225        r->_hash = hash;
     
    216242PassRefPtr<UString::Rep> Identifier::addSlowCase(UString::Rep *r)
    217243{
    218     ASSERT(!r->isIdentifier);
     244    ASSERT(!r->identifierTable);
    219245
    220246    if (r->len == 0) {
     
    223249    }
    224250
    225     UString::Rep *result = *identifierTable().add(r).first;
    226     if (result == r)
    227         r->isIdentifier = true;
    228     return result;
     251    return *identifierTable().add(r).first;
    229252}
    230253
    231254void Identifier::remove(UString::Rep *r)
    232255{
    233     identifierTable().remove(r);
     256    r->identifierTable->remove(r);
    234257}
    235258
Note: See TracChangeset for help on using the changeset viewer.