]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/StructureTransitionTable.h
JavaScriptCore-584.tar.gz
[apple/javascriptcore.git] / runtime / StructureTransitionTable.h
index 5b4f4e63221b83043fd78e7cd167e723cdced22a..320dbddc9a41eb627c60ccde75459ecd086df777 100644 (file)
@@ -30,6 +30,8 @@
 #include <wtf/HashFunctions.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
+#include <wtf/PtrAndFlags.h>
+#include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
 
 namespace JSC {
@@ -40,7 +42,7 @@ namespace JSC {
         typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
         static unsigned hash(const Key& p)
         {
-            return p.first->computedHash();
+            return p.first->existingHash();
         }
 
         static bool equal(const Key& a, const Key& b)
@@ -69,43 +71,93 @@ namespace JSC {
         typedef std::pair<Structure*, Structure*> Transition;
         typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
     public:
+        StructureTransitionTable() {
+            m_transitions.m_singleTransition.set(0);
+            m_transitions.m_singleTransition.setFlag(usingSingleSlot);
+        }
+
+        ~StructureTransitionTable() {
+            if (!usingSingleTransitionSlot())
+                delete table();
+        }
+
         // The contains and get methods accept imprecise matches, so if an unspecialised transition exists
         // for the given key they will consider that transition to be a match.  If a specialised transition
         // exists and it matches the provided specificValue, get will return the specific transition.
         inline bool contains(const StructureTransitionTableHash::Key&, JSCell* specificValue);
         inline Structure* get(const StructureTransitionTableHash::Key&, JSCell* specificValue) const;
-        bool hasTransition(const StructureTransitionTableHash::Key& key)
-        {
-            return m_table.contains(key);
-        }
+        inline bool hasTransition(const StructureTransitionTableHash::Key& key) const;
         void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
         {
-            TransitionTable::iterator find = m_table.find(key);
+            if (usingSingleTransitionSlot()) {
+                ASSERT(contains(key, specificValue));
+                setSingleTransition(0);
+                return;
+            }
+            TransitionTable::iterator find = table()->find(key);
             if (!specificValue)
                 find->second.first = 0;
             else
                 find->second.second = 0;
             if (!find->second.first && !find->second.second)
-                m_table.remove(find);
+                table()->remove(find);
         }
         void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
         {
+            if (usingSingleTransitionSlot()) {
+                if (!singleTransition()) {
+                    setSingleTransition(structure);
+                    return;
+                }
+                reifySingleTransition();
+            }
             if (!specificValue) {
-                TransitionTable::iterator find = m_table.find(key);
-                if (find == m_table.end())
-                    m_table.add(key, Transition(structure, 0));
+                TransitionTable::iterator find = table()->find(key);
+                if (find == table()->end())
+                    table()->add(key, Transition(structure, 0));
                 else
                     find->second.first = structure;
             } else {
                 // If we're adding a transition to a specific value, then there cannot be
                 // an existing transition
-                ASSERT(!m_table.contains(key));
-                m_table.add(key, Transition(0, structure));
+                ASSERT(!table()->contains(key));
+                table()->add(key, Transition(0, structure));
             }
-
         }
+
     private:
-        TransitionTable m_table;
+        TransitionTable* table() const { ASSERT(!usingSingleTransitionSlot()); return m_transitions.m_table; }
+        Structure* singleTransition() const {
+            ASSERT(usingSingleTransitionSlot());
+            return m_transitions.m_singleTransition.get();
+        }
+        bool usingSingleTransitionSlot() const { return m_transitions.m_singleTransition.isFlagSet(usingSingleSlot); }
+        void setSingleTransition(Structure* structure)
+        { 
+            ASSERT(usingSingleTransitionSlot());
+            m_transitions.m_singleTransition.set(structure);
+        }
+
+        void setTransitionTable(TransitionTable* table)
+        {
+            ASSERT(usingSingleTransitionSlot());
+#ifndef NDEBUG
+            setSingleTransition(0);
+#endif
+            m_transitions.m_table = table;
+            // This implicitly clears the flag that indicates we're using a single transition
+            ASSERT(!usingSingleTransitionSlot());
+        }
+        inline void reifySingleTransition();
+
+        enum UsingSingleSlot {
+            usingSingleSlot
+        };
+        // Last bit indicates whether we are using the single transition optimisation
+        union {
+            TransitionTable* m_table;
+            PtrAndFlagsBase<Structure, UsingSingleSlot> m_singleTransition;
+        } m_transitions;
     };
 
 } // namespace JSC