Ignore:
Timestamp:
Feb 22, 2011, 1:49:59 PM (14 years ago)
Author:
[email protected]
Message:

Bug 54988 - Re-create StructureTransitionTable class, encapsulate transition table

Reviewed by Sam Weinig.

The Structure class keeps a table of transitions to derived Structure types. Since
this table commonly contains a single entry we employ an optimization where instead
of holding a map, we may hold a pointer directly to a single instance of the mapped
type. We use an additional bit of data to flag whether the pointer is currently
pointing to a table of transitions, or a singleton transition. Previously we had
commonly used a pattern of storing data in the low bits of pointers, but had moved
away from this since it causes false leaks to be reported by the leaks tool. However
in this case, the entries in the map are weak links - this pointer will never be
responsible for keeping an object alive. As such we can use this approach provided
that the bit is set when a table is not in use (otherwise the table would appear to
be leaked).

Additionally, the transition table currently allows two entries to exist for a given
key - one specialized to a particular value, and one not specialized. This is
unnecessary, wasteful, and a little inconsistent. (If you create an entry for a
specialized value, then a non-specialized entry, both will exist. If you create an
entry for a non-specialized value, then try to create a specialized entry, only a
non-specialized form will be allowed.)

This shows a small progression on v8.

(JSC::JSObject::putDirectInternal):

  • runtime/Structure.cpp:

(JSC::StructureTransitionTable::contains):
(JSC::StructureTransitionTable::get):
(JSC::StructureTransitionTable::remove):
(JSC::StructureTransitionTable::add):
(JSC::Structure::dumpStatistics):
(JSC::Structure::Structure):
(JSC::Structure::~Structure):
(JSC::Structure::addPropertyTransitionToExistingStructure):
(JSC::Structure::addPropertyTransition):

  • runtime/Structure.h:

(JSC::Structure::get):

  • runtime/StructureTransitionTable.h:

(JSC::StructureTransitionTable::Hash::hash):
(JSC::StructureTransitionTable::Hash::equal):
(JSC::StructureTransitionTable::HashTraits::emptyValue):
(JSC::StructureTransitionTable::HashTraits::constructDeletedValue):
(JSC::StructureTransitionTable::HashTraits::isDeletedValue):
(JSC::StructureTransitionTable::StructureTransitionTable):
(JSC::StructureTransitionTable::~StructureTransitionTable):
(JSC::StructureTransitionTable::isUsingSingleSlot):
(JSC::StructureTransitionTable::map):
(JSC::StructureTransitionTable::setMap):
(JSC::StructureTransitionTable::singleTransition):
(JSC::StructureTransitionTable::setSingleTransition):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r79132 r79355  
    116116            return get(propertyName.impl(), attributes, specificValue);
    117117        }
    118         bool transitionedFor(const JSCell* specificValue)
    119         {
    120             return m_specificValueInPrevious == specificValue;
    121         }
    122         bool hasTransition(StringImpl*, unsigned attributes);
    123         bool hasTransition(const Identifier& propertyName, unsigned attributes)
    124         {
    125             return hasTransition(propertyName.impl(), attributes);
    126         }
    127118
    128119        bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
     
    191182        }
    192183
    193         typedef std::pair<Structure*, Structure*> Transition;
    194         typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
    195 
    196         inline bool transitionTableContains(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
    197         inline void transitionTableRemove(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
    198         inline void transitionTableAdd(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue);
    199         inline bool transitionTableHasTransition(const StructureTransitionTableHash::Key& key) const;
    200         inline Structure* transitionTableGet(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const;
    201 
    202         TransitionTable* transitionTable() const { ASSERT(!m_isUsingSingleSlot); return m_transitions.m_table; }
    203         inline void setTransitionTable(TransitionTable* table);
    204         Structure* singleTransition() const { ASSERT(m_isUsingSingleSlot); return m_transitions.m_singleTransition; }
    205         void setSingleTransition(Structure* structure) { ASSERT(m_isUsingSingleSlot); m_transitions.m_singleTransition = structure; }
    206        
    207184        bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
    208185
     
    226203        const ClassInfo* m_classInfo;
    227204
    228         // 'm_isUsingSingleSlot' indicates whether we are using the single transition optimisation.
    229         union {
    230             TransitionTable* m_table;
    231             Structure* m_singleTransition;
    232         } m_transitions;
     205        StructureTransitionTable m_transitionTable;
    233206
    234207        WeakGCPtr<JSPropertyNameIterator> m_enumerationCache;
     
    255228        unsigned m_specificFunctionThrashCount : 2;
    256229        unsigned m_anonymousSlotCount : 5;
    257         unsigned m_isUsingSingleSlot : 1;
    258         // 4 free bits
     230        // 5 free bits
    259231    };
    260232
Note: See TracChangeset for help on using the changeset viewer.