Ignore:
Timestamp:
Feb 15, 2010, 2:37:43 PM (15 years ago)
Author:
[email protected]
Message:

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

Reviewed by Darin Adler.

JavaScriptCore:

StructureTransitionTable was effectively a smart pointer type,
one machine word in size and wholly contained as a member of
of Structure. It either pointed to an actual table, or could
be used to describe a single transtion entry without use of a
table.

This, however, worked by using a PtrAndFlags, which is not
compatible with the leaks tool. Since there is no clear way to
obtain another bit for 'free' here, and since there are bits
available up in Structure, merge this functionality back up into
Structure. Having this in a separate class was quite clean
from an enacapsulation perspective, but this solution doesn't
seem to bad - all table access is now intermediated through the
Structure::structureTransitionTableFoo methods, keeping the
optimization fairly well contained.

This was the last use of PtrAndFlags, so removing the file too.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/CodeBlock.h:
  • runtime/Structure.cpp:

(JSC::Structure::Structure):
(JSC::Structure::~Structure):
(JSC::Structure::addPropertyTransitionToExistingStructure):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::hasTransition):

  • runtime/Structure.h:

(JSC::Structure::):
(JSC::Structure::structureTransitionTableContains):
(JSC::Structure::structureTransitionTableGet):
(JSC::Structure::structureTransitionTableHasTransition):
(JSC::Structure::structureTransitionTableRemove):
(JSC::Structure::structureTransitionTableAdd):
(JSC::Structure::structureTransitionTable):
(JSC::Structure::setStructureTransitionTable):
(JSC::Structure::singleTransition):
(JSC::Structure::setSingleTransition):

  • runtime/StructureTransitionTable.h:
  • wtf/PtrAndFlags.h: Removed.

WebCore:

PtrAndFlags has now been removed; remove forwarding header.

  • ForwardingHeaders/wtf/PtrAndFlags.h: Removed.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/Structure.cpp

    r54265 r54798  
    8080static int comparePropertyMapEntryIndices(const void* a, const void* b);
    8181
     82inline void Structure::setTransitionTable(TransitionTable* table)
     83{
     84    ASSERT(m_isUsingSingleSlot);
     85#ifndef NDEBUG
     86    setSingleTransition(0);
     87#endif
     88    m_isUsingSingleSlot = false;
     89    m_transitions.m_table = table;
     90    // This implicitly clears the flag that indicates we're using a single transition
     91    ASSERT(!m_isUsingSingleSlot);
     92}
     93
     94// The contains and get methods accept imprecise matches, so if an unspecialised transition exists
     95// for the given key they will consider that transition to be a match.  If a specialised transition
     96// exists and it matches the provided specificValue, get will return the specific transition.
     97inline bool Structure::transitionTableContains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
     98{
     99    if (m_isUsingSingleSlot) {
     100        Structure* existingTransition = singleTransition();
     101        return existingTransition && existingTransition->m_nameInPrevious.get() == key.first
     102               && existingTransition->m_attributesInPrevious == key.second
     103               && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0);
     104    }
     105    TransitionTable::iterator find = transitionTable()->find(key);
     106    if (find == transitionTable()->end())
     107        return false;
     108
     109    return find->second.first || find->second.second->transitionedFor(specificValue);
     110}
     111
     112inline Structure* Structure::transitionTableGet(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
     113{
     114    if (m_isUsingSingleSlot) {
     115        Structure* existingTransition = singleTransition();
     116        if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first
     117            && existingTransition->m_attributesInPrevious == key.second
     118            && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0))
     119            return existingTransition;
     120        return 0;
     121    }
     122
     123    Transition transition = transitionTable()->get(key);
     124    if (transition.second && transition.second->transitionedFor(specificValue))
     125        return transition.second;
     126    return transition.first;
     127}
     128
     129inline bool Structure::transitionTableHasTransition(const StructureTransitionTableHash::Key& key) const
     130{
     131    if (m_isUsingSingleSlot) {
     132        Structure* transition = singleTransition();
     133        return transition && transition->m_nameInPrevious == key.first
     134        && transition->m_attributesInPrevious == key.second;
     135    }
     136    return transitionTable()->contains(key);
     137}
     138
     139inline void Structure::transitionTableRemove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
     140{
     141    if (m_isUsingSingleSlot) {
     142        ASSERT(transitionTableContains(key, specificValue));
     143        setSingleTransition(0);
     144        return;
     145    }
     146    TransitionTable::iterator find = transitionTable()->find(key);
     147    if (!specificValue)
     148        find->second.first = 0;
     149    else
     150        find->second.second = 0;
     151    if (!find->second.first && !find->second.second)
     152        transitionTable()->remove(find);
     153}
     154
     155inline void Structure::transitionTableAdd(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
     156{
     157    if (m_isUsingSingleSlot) {
     158        if (!singleTransition()) {
     159            setSingleTransition(structure);
     160            return;
     161        }
     162        Structure* existingTransition = singleTransition();
     163        TransitionTable* transitionTable = new TransitionTable;
     164        setTransitionTable(transitionTable);
     165        if (existingTransition)
     166            transitionTableAdd(std::make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
     167    }
     168    if (!specificValue) {
     169        TransitionTable::iterator find = transitionTable()->find(key);
     170        if (find == transitionTable()->end())
     171            transitionTable()->add(key, Transition(structure, 0));
     172        else
     173            find->second.first = structure;
     174    } else {
     175        // If we're adding a transition to a specific value, then there cannot be
     176        // an existing transition
     177        ASSERT(!transitionTable()->contains(key));
     178        transitionTable()->add(key, Transition(0, structure));
     179    }
     180}
     181
    82182void Structure::dumpStatistics()
    83183{
     
    137237    , m_specificFunctionThrashCount(0)
    138238    , m_anonymousSlotCount(anonymousSlotCount)
    139 {
     239    , m_isUsingSingleSlot(true)
     240{
     241    m_transitions.m_singleTransition = 0;
     242
    140243    ASSERT(m_prototype);
    141244    ASSERT(m_prototype.isObject() || m_prototype.isNull());
     
    160263    if (m_previous) {
    161264        ASSERT(m_nameInPrevious);
    162         m_previous->table.remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
     265        m_previous->transitionTableRemove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
    163266
    164267    }
     
    177280        fastFree(m_propertyTable);
    178281    }
     282
     283    if (!m_isUsingSingleSlot)
     284        delete transitionTable();
    179285
    180286#ifndef NDEBUG
     
    341447    ASSERT(structure->typeInfo().type() == ObjectType);
    342448
    343     if (Structure* existingTransition = structure->table.get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
     449    if (Structure* existingTransition = structure->transitionTableGet(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
    344450        ASSERT(existingTransition->m_offset != noOffset);
    345451        offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount;
     
    406512    transition->m_offset = offset - structure->m_anonymousSlotCount;
    407513    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
    408     structure->table.add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
     514    structure->transitionTableAdd(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
    409515    return transition.release();
    410516}
     
    853959bool Structure::hasTransition(UString::Rep* rep, unsigned attributes)
    854960{
    855     return table.hasTransition(make_pair(rep, attributes));
     961    return transitionTableHasTransition(make_pair(rep, attributes));
    856962}
    857963
Note: See TracChangeset for help on using the changeset viewer.