Changeset 48264 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Sep 10, 2009, 1:01:57 PM (16 years ago)
Author:
[email protected]
Message:

Refactor StructureTransitionTable and Structure to unify handling of the single slot optimization
https://bugs.webkit.org/show_bug.cgi?id=29141

Reviewed by Geoff Garen

Make StructureTransitionTable encapsulate the single transition slot optimization.

Location:
trunk/JavaScriptCore/runtime
Files:
3 edited

Legend:

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

    r47605 r48264  
    131131    , m_isPinnedPropertyTable(false)
    132132    , m_hasGetterSetterProperties(false)
    133     , m_usingSingleTransitionSlot(true)
    134133    , m_attributesInPrevious(0)
    135134{
    136135    ASSERT(m_prototype);
    137136    ASSERT(m_prototype.isObject() || m_prototype.isNull());
    138 
    139     m_transitions.singleTransition = 0;
    140137
    141138#ifndef NDEBUG
     
    156153Structure::~Structure()
    157154{
    158     if (m_previous) {
    159         if (m_previous->m_usingSingleTransitionSlot) {
    160             m_previous->m_transitions.singleTransition = 0;
    161         } else {
    162             ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious));
    163             m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
    164         }
    165     }
     155    if (m_previous)
     156        m_previous->table.remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
    166157
    167158    if (m_cachedPropertyNameArrayData)
    168159        m_cachedPropertyNameArrayData->setCachedStructure(0);
    169 
    170     if (!m_usingSingleTransitionSlot)
    171         delete m_transitions.table;
    172160
    173161    if (m_propertyTable) {
     
    382370    ASSERT(structure->typeInfo().type() == ObjectType);
    383371
    384     if (structure->m_usingSingleTransitionSlot) {
    385         Structure* existingTransition = structure->m_transitions.singleTransition;
    386         if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep()
    387             && existingTransition->m_attributesInPrevious == attributes
    388             && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0)) {
    389 
    390             ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset);
    391             offset = structure->m_transitions.singleTransition->m_offset;
    392             return existingTransition;
    393         }
    394     } else {
    395         if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
    396             ASSERT(existingTransition->m_offset != noOffset);
    397             offset = existingTransition->m_offset;
    398             return existingTransition;
    399         }
     372    if (Structure* existingTransition = structure->table.get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
     373        ASSERT(existingTransition->m_offset != noOffset);
     374        offset = existingTransition->m_offset;
     375        return existingTransition;
    400376    }
    401377
     
    448424    transition->m_offset = offset;
    449425
    450     if (structure->m_usingSingleTransitionSlot) {
    451         if (!structure->m_transitions.singleTransition) {
    452             structure->m_transitions.singleTransition = transition.get();
    453             return transition.release();
    454         }
    455 
    456         Structure* existingTransition = structure->m_transitions.singleTransition;
    457         structure->m_usingSingleTransitionSlot = false;
    458         StructureTransitionTable* transitionTable = new StructureTransitionTable;
    459         structure->m_transitions.table = transitionTable;
    460         transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
    461     }
    462     structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
     426    structure->table.add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
    463427    return transition.release();
    464428}
     
    559523size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
    560524{
    561     ASSERT(!m_transitions.singleTransition);
    562 
    563525    materializePropertyMapIfNecessary();
    564526
     
    573535size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
    574536{
    575     ASSERT(!m_transitions.singleTransition);
    576537    ASSERT(m_isDictionary);
    577538
     
    830791bool Structure::hasTransition(UString::Rep* rep, unsigned attributes)
    831792{
    832     if (m_usingSingleTransitionSlot) {
    833         return m_transitions.singleTransition
    834             && m_transitions.singleTransition->m_nameInPrevious == rep
    835             && m_transitions.singleTransition->m_attributesInPrevious == attributes;
    836     }
    837     return m_transitions.table->hasTransition(make_pair(rep, attributes));
     793    return table.hasTransition(make_pair(rep, attributes));
    838794}
    839795
  • trunk/JavaScriptCore/runtime/Structure.h

    r48207 r48264  
    5353    public:
    5454        friend class JIT;
     55        friend class StructureTransitionTable;
    5556        static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo)
    5657        {
     
    175176        JSCell* m_specificValueInPrevious;
    176177
    177         union {
    178             Structure* singleTransition;
    179             StructureTransitionTable* table;
    180         } m_transitions;
     178        StructureTransitionTable table;
    181179
    182180        RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
     
    190188        bool m_isPinnedPropertyTable : 1;
    191189        bool m_hasGetterSetterProperties : 1;
    192         bool m_usingSingleTransitionSlot : 1;
    193190        unsigned m_attributesInPrevious : 7;
    194191    };
     
    241238    bool StructureTransitionTable::contains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
    242239    {
    243         TransitionTable::iterator find = m_table.find(key);
    244         if (find == m_table.end())
     240        if (usingSingleTransitionSlot()) {
     241            Structure* existingTransition = singleTransition();
     242            return existingTransition && existingTransition->m_nameInPrevious.get() == key.first
     243                   && existingTransition->m_attributesInPrevious == key.second
     244                   && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0);
     245        }
     246        TransitionTable::iterator find = table()->find(key);
     247        if (find == table()->end())
    245248            return false;
    246249
     
    250253    Structure* StructureTransitionTable::get(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
    251254    {
    252         Transition transition = m_table.get(key);
     255        if (usingSingleTransitionSlot()) {
     256            Structure* existingTransition = singleTransition();
     257            if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first
     258                && existingTransition->m_attributesInPrevious == key.second
     259                && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0))
     260                return existingTransition;
     261            return 0;
     262        }
     263
     264        Transition transition = table()->get(key);
    253265        if (transition.second && transition.second->transitionedFor(specificValue))
    254266            return transition.second;
    255267        return transition.first;
    256268    }
     269
     270    bool StructureTransitionTable::hasTransition(const StructureTransitionTableHash::Key& key) const
     271    {
     272        if (usingSingleTransitionSlot()) {
     273            Structure* transition = singleTransition();
     274            return transition && transition->m_nameInPrevious == key.first
     275            && transition->m_attributesInPrevious == key.second;
     276        }
     277        return table()->contains(key);
     278    }
     279   
     280    void StructureTransitionTable::reifySingleTransition()
     281    {
     282        ASSERT(usingSingleTransitionSlot());
     283        Structure* existingTransition = singleTransition();
     284        ASSERT(existingTransition);
     285        TransitionTable* transitionTable = new TransitionTable;
     286        setTransitionTable(transitionTable);
     287        add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
     288    }
    257289} // namespace JSC
    258290
  • trunk/JavaScriptCore/runtime/StructureTransitionTable.h

    r47605 r48264  
    3131#include <wtf/HashMap.h>
    3232#include <wtf/HashTraits.h>
     33#include <wtf/PtrAndFlags.h>
    3334#include <wtf/RefPtr.h>
    3435
     
    7071        typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
    7172    public:
     73        StructureTransitionTable() {
     74            m_transitions.m_singleTransition.set(0);
     75            m_transitions.m_singleTransition.setFlag(0);
     76        }
     77
     78        ~StructureTransitionTable() {
     79            if (!usingSingleTransitionSlot())
     80                delete table();
     81        }
     82
    7283        // The contains and get methods accept imprecise matches, so if an unspecialised transition exists
    7384        // for the given key they will consider that transition to be a match.  If a specialised transition
     
    7586        inline bool contains(const StructureTransitionTableHash::Key&, JSCell* specificValue);
    7687        inline Structure* get(const StructureTransitionTableHash::Key&, JSCell* specificValue) const;
    77         bool hasTransition(const StructureTransitionTableHash::Key& key)
    78         {
    79             return m_table.contains(key);
    80         }
     88        inline bool hasTransition(const StructureTransitionTableHash::Key& key) const;
    8189        void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
    8290        {
    83             TransitionTable::iterator find = m_table.find(key);
     91            if (usingSingleTransitionSlot()) {
     92                ASSERT(contains(key, specificValue));
     93                setSingleTransition(0);
     94                return;
     95            }
     96            TransitionTable::iterator find = table()->find(key);
    8497            if (!specificValue)
    8598                find->second.first = 0;
     
    87100                find->second.second = 0;
    88101            if (!find->second.first && !find->second.second)
    89                 m_table.remove(find);
     102                table()->remove(find);
    90103        }
    91104        void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
    92105        {
     106            if (usingSingleTransitionSlot()) {
     107                if (!singleTransition()) {
     108                    setSingleTransition(structure);
     109                    return;
     110                }
     111                reifySingleTransition();
     112            }
    93113            if (!specificValue) {
    94                 TransitionTable::iterator find = m_table.find(key);
    95                 if (find == m_table.end())
    96                     m_table.add(key, Transition(structure, 0));
     114                TransitionTable::iterator find = table()->find(key);
     115                if (find == table()->end())
     116                    table()->add(key, Transition(structure, 0));
    97117                else
    98118                    find->second.first = structure;
     
    100120                // If we're adding a transition to a specific value, then there cannot be
    101121                // an existing transition
    102                 ASSERT(!m_table.contains(key));
    103                 m_table.add(key, Transition(0, structure));
     122                ASSERT(!table()->contains(key));
     123                table()->add(key, Transition(0, structure));
    104124            }
    105 
    106125        }
    107126    private:
    108         TransitionTable m_table;
     127        TransitionTable* table() const { ASSERT(!usingSingleTransitionSlot()); return m_transitions.m_table; }
     128        Structure* singleTransition() const {
     129            ASSERT(usingSingleTransitionSlot());
     130            return m_transitions.m_singleTransition.get();
     131        }
     132        bool usingSingleTransitionSlot() const { return m_transitions.m_singleTransition.isFlagSet(0); }
     133        void setSingleTransition(Structure* structure)
     134        {
     135            ASSERT(usingSingleTransitionSlot());
     136            m_transitions.m_singleTransition.set(structure);
     137        }
     138
     139        void setTransitionTable(TransitionTable* table)
     140        {
     141            ASSERT(usingSingleTransitionSlot());
     142#ifndef NDEBUG
     143            setSingleTransition(0);
     144#endif
     145            m_transitions.m_table = table;
     146            // This implicitly clears the flag that indicates we're using a single transition
     147            ASSERT(!usingSingleTransitionSlot());
     148        }
     149        inline void reifySingleTransition();
     150
     151        // Last bit indicates whether we are using the single transition optimisation
     152        union {
     153            TransitionTable* m_table;
     154            PtrAndFlagsBase<Structure, bool> m_singleTransition;
     155        } m_transitions;
    109156    };
    110157
Note: See TracChangeset for help on using the changeset viewer.