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.h

    r54696 r54798  
    180180            return m_offset == noOffset ? 0 : m_offset + 1;
    181181        }
     182
     183        typedef std::pair<Structure*, Structure*> Transition;
     184        typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
     185
     186        inline bool transitionTableContains(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
     187        inline void transitionTableRemove(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
     188        inline void transitionTableAdd(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue);
     189        inline bool transitionTableHasTransition(const StructureTransitionTableHash::Key& key) const;
     190        inline Structure* transitionTableGet(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const;
     191
     192        TransitionTable* transitionTable() const { ASSERT(!m_isUsingSingleSlot); return m_transitions.m_table; }
     193        inline void setTransitionTable(TransitionTable* table);
     194        Structure* singleTransition() const { ASSERT(m_isUsingSingleSlot); return m_transitions.m_singleTransition; }
     195        void setSingleTransition(Structure* structure) { ASSERT(m_isUsingSingleSlot); m_transitions.m_singleTransition = structure; }
    182196       
    183197        bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
     
    200214        JSCell* m_specificValueInPrevious;
    201215
    202         StructureTransitionTable table;
     216        // 'm_isUsingSingleSlot' indicates whether we are using the single transition optimisation.
     217        union {
     218            TransitionTable* m_table;
     219            Structure* m_singleTransition;
     220        } m_transitions;
    203221
    204222        WeakGCPtr<JSPropertyNameIterator> m_enumerationCache;
     
    225243        unsigned m_specificFunctionThrashCount : 2;
    226244        unsigned m_anonymousSlotCount : 5;
    227         // 5 free bits
     245        unsigned m_isUsingSingleSlot : 1;
     246        // 4 free bits
    228247    };
    229248
     
    272291        }
    273292    }
    274    
    275     bool StructureTransitionTable::contains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
    276     {
    277         if (usingSingleTransitionSlot()) {
    278             Structure* existingTransition = singleTransition();
    279             return existingTransition && existingTransition->m_nameInPrevious.get() == key.first
    280                    && existingTransition->m_attributesInPrevious == key.second
    281                    && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0);
    282         }
    283         TransitionTable::iterator find = table()->find(key);
    284         if (find == table()->end())
    285             return false;
    286 
    287         return find->second.first || find->second.second->transitionedFor(specificValue);
    288     }
    289 
    290     Structure* StructureTransitionTable::get(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
    291     {
    292         if (usingSingleTransitionSlot()) {
    293             Structure* existingTransition = singleTransition();
    294             if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first
    295                 && existingTransition->m_attributesInPrevious == key.second
    296                 && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0))
    297                 return existingTransition;
    298             return 0;
    299         }
    300 
    301         Transition transition = table()->get(key);
    302         if (transition.second && transition.second->transitionedFor(specificValue))
    303             return transition.second;
    304         return transition.first;
    305     }
    306 
    307     bool StructureTransitionTable::hasTransition(const StructureTransitionTableHash::Key& key) const
    308     {
    309         if (usingSingleTransitionSlot()) {
    310             Structure* transition = singleTransition();
    311             return transition && transition->m_nameInPrevious == key.first
    312             && transition->m_attributesInPrevious == key.second;
    313         }
    314         return table()->contains(key);
    315     }
    316    
    317     void StructureTransitionTable::reifySingleTransition()
    318     {
    319         ASSERT(usingSingleTransitionSlot());
    320         Structure* existingTransition = singleTransition();
    321         TransitionTable* transitionTable = new TransitionTable;
    322         setTransitionTable(transitionTable);
    323         if (existingTransition)
    324             add(std::make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
    325     }
     293
    326294} // namespace JSC
    327295
Note: See TracChangeset for help on using the changeset viewer.