]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/StructureTransitionTable.h
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / runtime / StructureTransitionTable.h
index 154304963a8cf12cc8d3d9d6d515f5c73680c9b0..adebad28480c24db39a5015da6cdad4add0747d3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #define StructureTransitionTable_h
 
 #include "UString.h"
+#include "WeakGCMap.h"
 #include <wtf/HashFunctions.h>
-#include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
+#include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
 
 namespace JSC {
 
-    class Structure;
+class Structure;
 
-    struct StructureTransitionTableHash {
-        typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
+class StructureTransitionTable {
+    static const intptr_t UsingSingleSlotFlag = 1;
+
+    struct Hash {
+        typedef std::pair<RefPtr<StringImpl>, 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)
@@ -51,10 +55,10 @@ namespace JSC {
         static const bool safeToCompareToEmptyOrDeleted = true;
     };
 
-    struct StructureTransitionTableHashTraits {
-        typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
+    struct HashTraits {
+        typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits;
         typedef WTF::GenericHashTraits<unsigned> SecondTraits;
-        typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType;
+        typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
 
         static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
         static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
@@ -65,7 +69,104 @@ namespace JSC {
         static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
     };
 
-    typedef HashMap<StructureTransitionTableHash::Key, Structure*, StructureTransitionTableHash, StructureTransitionTableHashTraits> StructureTransitionTable;
+    struct WeakGCMapFinalizerCallback {
+        static void* finalizerContextFor(Hash::Key)
+        {
+            return 0;
+        }
+
+        static inline Hash::Key keyForFinalizer(void* context, Structure* structure)
+        {
+            return keyForWeakGCMapFinalizer(context, structure);
+        }
+    };
+
+    typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap;
+
+    static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
+
+public:
+    StructureTransitionTable()
+        : m_data(UsingSingleSlotFlag)
+    {
+    }
+
+    ~StructureTransitionTable()
+    {
+        if (!isUsingSingleSlot())
+            delete map();
+        else
+            clearSingleTransition();
+    }
+
+    inline void add(JSGlobalData&, Structure*);
+    inline void remove(Structure*);
+    inline bool contains(StringImpl* rep, unsigned attributes) const;
+    inline Structure* get(StringImpl* rep, unsigned attributes) const;
+
+private:
+    bool isUsingSingleSlot() const
+    {
+        return m_data & UsingSingleSlotFlag;
+    }
+
+    TransitionMap* map() const
+    {
+        ASSERT(!isUsingSingleSlot());
+        return reinterpret_cast<TransitionMap*>(m_data);
+    }
+
+    HandleSlot slot() const
+    {
+        ASSERT(isUsingSingleSlot());
+        return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag);
+    }
+
+    void setMap(TransitionMap* map)
+    {
+        ASSERT(isUsingSingleSlot());
+        
+        if (HandleSlot slot = this->slot())
+            HandleHeap::heapFor(slot)->deallocate(slot);
+
+        // This implicitly clears the flag that indicates we're using a single transition
+        m_data = reinterpret_cast<intptr_t>(map);
+
+        ASSERT(!isUsingSingleSlot());
+    }
+
+    Structure* singleTransition() const
+    {
+        ASSERT(isUsingSingleSlot());
+        if (HandleSlot slot = this->slot()) {
+            if (*slot)
+                return reinterpret_cast<Structure*>(slot->asCell());
+        }
+        return 0;
+    }
+    
+    void clearSingleTransition()
+    {
+        ASSERT(isUsingSingleSlot());
+        if (HandleSlot slot = this->slot())
+            HandleHeap::heapFor(slot)->deallocate(slot);
+    }
+    
+    void setSingleTransition(JSGlobalData& globalData, Structure* structure)
+    {
+        ASSERT(isUsingSingleSlot());
+        HandleSlot slot = this->slot();
+        if (!slot) {
+            slot = globalData.allocateGlobalHandle();
+            HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0);
+            m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag;
+        }
+        HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure));
+        *slot = reinterpret_cast<JSCell*>(structure);
+    }
+
+    intptr_t m_data;
+};
 
 } // namespace JSC