]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/WeakGCMap.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / WeakGCMap.h
index 5ad1c62a3e97298d24047f649878d197259e22f6..16d3d44000437853fb83da2ab1830303319b4b9e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef WeakGCMap_h
 #define WeakGCMap_h
 
-#include "Handle.h"
-#include "JSGlobalData.h"
+#include "Weak.h"
+#include "WeakInlines.h"
 #include <wtf/HashMap.h>
 
 namespace JSC {
 
-// A HashMap for GC'd values that removes entries when the associated value
-// dies.
-template <typename KeyType, typename MappedType> struct DefaultWeakGCMapFinalizerCallback {
-    static void* finalizerContextFor(KeyType key)
-    {
-        return reinterpret_cast<void*>(key);
-    }
-
-    static KeyType keyForFinalizer(void* context, typename HandleTypes<MappedType>::ExternalType)
-    {
-        return reinterpret_cast<KeyType>(context);
-    }
-};
+// A HashMap with Weak<JSCell> values, which automatically removes values once they're garbage collected.
 
-template<typename KeyType, typename MappedType, typename FinalizerCallback = DefaultWeakGCMapFinalizerCallback<KeyType, MappedType>, typename HashArg = typename DefaultHash<KeyType>::Hash, typename KeyTraitsArg = HashTraits<KeyType> >
-class WeakGCMap : private WeakHandleOwner {
+template<typename KeyArg, typename ValueArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
+    typename KeyTraitsArg = HashTraits<KeyArg>>
+class WeakGCMap {
     WTF_MAKE_FAST_ALLOCATED;
-    WTF_MAKE_NONCOPYABLE(WeakGCMap);
-
-    typedef HashMap<KeyType, HandleSlot, HashArg, KeyTraitsArg> MapType;
-    typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
-    typedef typename MapType::iterator map_iterator;
+    typedef Weak<ValueArg> ValueType;
+    typedef HashMap<KeyArg, ValueType, HashArg, KeyTraitsArg> HashMapType;
 
 public:
+    typedef typename HashMapType::KeyType KeyType;
+    typedef typename HashMapType::AddResult AddResult;
+    typedef typename HashMapType::iterator iterator;
+    typedef typename HashMapType::const_iterator const_iterator;
 
-    struct iterator {
-        friend class WeakGCMap;
-        iterator(map_iterator iter)
-            : m_iterator(iter)
-        {
-        }
-        
-        std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(m_iterator->second)); }
-        std::pair<KeyType, HandleSlot> getSlot() const { return *m_iterator; }
-        
-        iterator& operator++() { ++m_iterator; return *this; }
-        
-        // postfix ++ intentionally omitted
-        
-        // Comparison.
-        bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
-        bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
-        
-    private:
-        map_iterator m_iterator;
-    };
-
-    WeakGCMap()
-    {
-    }
+    explicit WeakGCMap(VM&);
+    ~WeakGCMap();
 
-    bool isEmpty() { return m_map.isEmpty(); }
-    void clear()
+    ValueArg* get(const KeyType& key) const
     {
-        map_iterator end = m_map.end();
-        for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr)
-            HandleHeap::heapFor(ptr->second)->deallocate(ptr->second);
-        m_map.clear();
+        return m_map.get(key);
     }
 
-    bool contains(const KeyType& key) const
+    AddResult set(const KeyType& key, ValueType value)
     {
-        return m_map.contains(key);
+        return m_map.set(key, WTF::move(value));
     }
 
-    iterator find(const KeyType& key)
+    bool remove(const KeyType& key)
     {
-        return m_map.find(key);
+        return m_map.remove(key);
     }
 
-    void remove(iterator iter)
+    void clear()
     {
-        ASSERT(iter.m_iterator != m_map.end());
-        HandleSlot slot = iter.m_iterator->second;
-        ASSERT(slot);
-        HandleHeap::heapFor(slot)->deallocate(slot);
-        m_map.remove(iter.m_iterator);
+        m_map.clear();
     }
 
-    ExternalType get(const KeyType& key) const
+    bool isEmpty() const
     {
-        return HandleTypes<MappedType>::getFromSlot(m_map.get(key));
+        const_iterator it = m_map.begin();
+        const_iterator end = m_map.end();
+        while (it != end) {
+            if (it->value)
+                return true;
+        }
+        return false;
     }
 
-    HandleSlot getSlot(const KeyType& key) const
+    iterator find(const KeyType& key)
     {
-        return m_map.get(key);
+        iterator it = m_map.find(key);
+        iterator end = m_map.end();
+        if (it != end && !it->value) // Found a zombie value.
+            return end;
+        return it;
     }
 
-    pair<iterator, bool> add(JSGlobalData& globalData, const KeyType& key, ExternalType value)
-    {
-        pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
-        if (iter.second) {
-            HandleSlot slot = globalData.allocateGlobalHandle();
-            iter.first->second = slot;
-            HandleHeap::heapFor(slot)->makeWeak(slot, this, FinalizerCallback::finalizerContextFor(key));
-            HandleHeap::heapFor(slot)->writeBarrier(slot, value);
-            *slot = value;
-        }
-        return iter;
-    }
-    
-    void set(iterator iter, ExternalType value)
+    const_iterator find(const KeyType& key) const
     {
-        HandleSlot slot = iter.m_iterator->second;
-        ASSERT(slot);
-        HandleHeap::heapFor(slot)->writeBarrier(slot, value);
-        *slot = value;
+        return const_cast<WeakGCMap*>(this)->find(key);
     }
 
-    void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
+    template<typename Functor>
+    void forEach(Functor functor)
     {
-        pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
-        HandleSlot slot = iter.first->second;
-        if (iter.second) {
-            slot = globalData.allocateGlobalHandle();
-            HandleHeap::heapFor(slot)->makeWeak(slot, this, key);
-            iter.first->second = slot;
+        for (auto& pair : m_map) {
+            if (pair.value)
+                functor(pair.key, pair.value.get());
         }
-        HandleHeap::heapFor(slot)->writeBarrier(slot, value);
-        *slot = value;
     }
 
-    ExternalType take(const KeyType& key)
+    bool contains(const KeyType& key) const
     {
-        HandleSlot slot = m_map.take(key);
-        if (!slot)
-            return HashTraits<ExternalType>::emptyValue();
-        ExternalType result = HandleTypes<MappedType>::getFromSlot(slot);
-        HandleHeap::heapFor(slot)->deallocate(slot);
-        return result;
+        return find(key) != m_map.end();
     }
 
-    size_t size() { return m_map.size(); }
+    void pruneStaleEntries();
 
-    iterator begin() { return iterator(m_map.begin()); }
-    iterator end() { return iterator(m_map.end()); }
-    
-    ~WeakGCMap()
-    {
-        clear();
-    }
-    
 private:
-    virtual void finalize(Handle<Unknown> handle, void* context)
-    {
-        HandleSlot slot = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot())));
-        ASSERT(slot);
-        HandleHeap::heapFor(slot)->deallocate(slot);
-    }
-
-    MapType m_map;
+    HashMapType m_map;
+    VM& m_vm;
 };
 
 } // namespace JSC