]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/WeakGCMap.h
JavaScriptCore-1218.34.tar.gz
[apple/javascriptcore.git] / runtime / WeakGCMap.h
index 39a91c5fa59adb605ae37351eaec1723395b1987..f741fa4c4c3e0fa60a5154a873fc8624edfde060 100644 (file)
 #ifndef WeakGCMap_h
 #define WeakGCMap_h
 
-#include "Collector.h"
+#include <heap/Weak.h>
+#include <heap/WeakInlines.h>
 #include <wtf/HashMap.h>
 
 namespace JSC {
 
-class JSCell;
+// A HashMap with Weak<JSCell> values, which automatically removes values once they're garbage collected.
 
-// A HashMap whose get() function returns emptyValue() for cells awaiting destruction.
-template<typename KeyType, typename MappedType>
-class WeakGCMap : public FastAllocBase {
-    /*
-    Invariants:
-        * A value enters the WeakGCMap marked. (Guaranteed by set().)
-        * A value that becomes unmarked leaves the WeakGCMap before being recycled. (Guaranteed by the value's destructor removing it from the WeakGCMap.)
-        * A value that becomes unmarked leaves the WeakGCMap before becoming marked again. (Guaranteed by all destructors running before the mark phase begins.)
-        * During the mark phase, all values in the WeakGCMap are valid. (Guaranteed by all destructors running before the mark phase begins.)
-    */
+template<typename KeyArg, typename RawMappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
+    typename KeyTraitsArg = HashTraits<KeyArg> >
+class WeakGCMap : public HashMap<KeyArg, Weak<RawMappedArg>, HashArg, KeyTraitsArg> {
+    typedef Weak<RawMappedArg> MappedType;
+    typedef HashMap<KeyArg, MappedType, HashArg, KeyTraitsArg> Base;
+    typedef WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg> Self;
+    typedef HashTraits<MappedType> MappedTraits;
+    typedef typename MappedTraits::PassInType MappedPassInType;
 
 public:
-    typedef typename HashMap<KeyType, MappedType>::iterator iterator;
-    typedef typename HashMap<KeyType, MappedType>::const_iterator const_iterator;
-    
-    bool isEmpty() { return m_map.isEmpty(); }
+    typedef typename Base::KeyType KeyType;
+    typedef typename Base::AddResult AddResult;
+    typedef typename Base::iterator iterator;
+    typedef typename Base::const_iterator const_iterator;
+    using Base::begin;
+    using Base::end;
+    using Base::size;
+    using Base::remove;
+
+    WeakGCMap()
+        : m_gcThreshold(minGCThreshold)
+    {
+    }
 
-    MappedType get(const KeyType& key) const;
-    pair<iterator, bool> set(const KeyType&, const MappedType&); 
-    MappedType take(const KeyType& key);
+    AddResult set(const KeyType& key, MappedPassInType value)
+    {
+        gcMapIfNeeded();
+        return Base::set(key, value);
+    }
 
-    // These unchecked functions provide access to a value even if the value's
-    // mark bit is not set. This is used, among other things, to retrieve values
-    // during the GC mark phase, which begins by clearing all mark bits.
+    AddResult add(const KeyType& key, MappedPassInType value)
+    {
+        gcMapIfNeeded();
+        AddResult addResult = Base::add(key, nullptr);
+        if (!addResult.iterator->value) { // New value or found a zombie value.
+            addResult.isNewEntry = true;
+            addResult.iterator->value = value;
+        }
+        return addResult;
+    }
 
-    MappedType uncheckedGet(const KeyType& key) const { return m_map.get(key); }
-    bool uncheckedRemove(const KeyType&, const MappedType&);
+    iterator find(const KeyType& key)
+    {
+        iterator it = Base::find(key);
+        iterator end = Base::end();
+        if (it != end && !it->value) // Found a zombie value.
+            return end;
+        return it;
+    }
 
-    iterator uncheckedBegin() { return m_map.begin(); }
-    iterator uncheckedEnd() { return m_map.end(); }
+    const_iterator find(const KeyType& key) const
+    {
+        return const_cast<Self*>(this)->find(key);
+    }
 
-    const_iterator uncheckedBegin() const { return m_map.begin(); }
-    const_iterator uncheckedEnd() const { return m_map.end(); }
+    bool contains(const KeyType& key) const
+    {
+        return find(key) != end();
+    }
 
 private:
-    HashMap<KeyType, MappedType> m_map;
-};
+    static const int minGCThreshold = 3;
+
+    void gcMap()
+    {
+        Vector<KeyType, 4> zombies;
+        iterator end = this->end();
+        for (iterator it = begin(); it != end; ++it) {
+            if (!it->value)
+                zombies.append(it->key);
+        }
+        for (size_t i = 0; i < zombies.size(); ++i)
+            remove(zombies[i]);
+    }
+
+    void gcMapIfNeeded()
+    {
+        if (size() < m_gcThreshold)
+            return;
 
-template<typename KeyType, typename MappedType>
-inline MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
-{
-    MappedType result = m_map.get(key);
-    if (result == HashTraits<MappedType>::emptyValue())
-        return result;
-    if (!Heap::isCellMarked(result))
-        return HashTraits<MappedType>::emptyValue();
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-MappedType WeakGCMap<KeyType, MappedType>::take(const KeyType& key)
-{
-    MappedType result = m_map.take(key);
-    if (result == HashTraits<MappedType>::emptyValue())
-        return result;
-    if (!Heap::isCellMarked(result))
-        return HashTraits<MappedType>::emptyValue();
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-pair<typename HashMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, const MappedType& value)
-{
-    Heap::markCell(value); // If value is newly allocated, it's not marked, so mark it now.
-    pair<iterator, bool> result = m_map.add(key, value);
-    if (!result.second) { // pre-existing entry
-        result.second = !Heap::isCellMarked(result.first->second);
-        result.first->second = value;
+        gcMap();
+        m_gcThreshold = std::max(minGCThreshold, size() * 2 - 1);
     }
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, const MappedType& value)
-{
-    iterator it = m_map.find(key);
-    if (it == m_map.end())
-        return false;
-    if (it->second != value)
-        return false;
-    m_map.remove(it);
-    return true;
-}
+
+    int m_gcThreshold;
+};
+
+template<typename KeyArg, typename RawMappedArg, typename HashArg, typename KeyTraitsArg>
+const int WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg>::minGCThreshold;
 
 } // namespace JSC