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

2011-02-23 Oliver Hunt <[email protected]>

Reviewed by Geoffrey Garen.

Make WeakGCMap use new handle infrastructure
https://bugs.webkit.org/show_bug.cgi?id=55100

Remove old WeakGCMap implementation and move over to new handle
based logic.

This has a number of benefits, most notably it makes a WeakGCMap
always reflect the true state of the world by as all entries are
removed at the first gc cycle that makes them dead. This allows
us to get rid of code in a wide variety of objects where the only
purpose was to remove themselves from maps.

It also means that we no longer need to have special "unchecked"
versions of any functions on WeakGCMap. Alas in order to maintain
compatibility with the JSWeakObjectMapClear API it is still
necessary to have an api that resembles uncheckedRemove, this is
now deprecatedRemove and will be dealt with in a later patch.

In order to get correct semantics in WeakGCMap we need more
contextual information in the finalizer, so we've added an
abstract class based finaliser and a context parameter to the
calls.

The new an improved WeakGCMap also results in sigificantly more
churn in the weak handle lists so exposed some potential problems
during the post mark phase which have been rectified as well.

  • API/JSWeakObjectMapRefPrivate.cpp:
  • API/JSWeakObjectMapRefPrivate.h:
  • runtime/Heap.cpp: (JSC::Heap::globalObjectCount): (JSC::Heap::protectedGlobalObjectCount):
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData):
  • runtime/JSGlobalData.h:
  • runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::~JSGlobalObject): (JSC::JSGlobalObject::init):
  • runtime/WeakGCMap.h: (JSC::WeakGCMap::iterator::iterator): (JSC::WeakGCMap::iterator::get): (JSC::WeakGCMap::iterator::getSlot): (JSC::WeakGCMap::iterator::operator++): (JSC::WeakGCMap::iterator::operator==): (JSC::WeakGCMap::iterator::operator!=): (JSC::WeakGCMap::WeakGCMap): (JSC::WeakGCMap::isEmpty): (JSC::WeakGCMap::clear): (JSC::WeakGCMap::get): (JSC::WeakGCMap::getSlot): (JSC::WeakGCMap::set): (JSC::WeakGCMap::take): (JSC::WeakGCMap::size): (JSC::WeakGCMap::deprecatedRemove): (JSC::WeakGCMap::begin): (JSC::WeakGCMap::end): (JSC::WeakGCMap::~WeakGCMap): (JSC::WeakGCMap::finalize):
  • runtime/WeakGCPtr.h: (JSC::WeakGCPtr::WeakGCPtr): (JSC::WeakGCPtr::set):

2011-02-23 Oliver Hunt <[email protected]>

Reviewed by Geoffrey Garen.

Make WeakGCMap use new handle infrastructure
https://bugs.webkit.org/show_bug.cgi?id=55100

Update to new WeakGCMap APIs, this requires threading global
data to a few functions that did not need it in the past, but
also gets rid of a large number of destructors, as well as the
forgetDOMNode, etc APIs.

We can also drop the JSDebugWrapperSet as its only purpose was
to ensure that we retained correct semantics in the old WeakGCMap,
but happilly these semantics are now guaranteed by the map itself.

  • CMakeLists.txt:
  • GNUmakefile.am:
  • WebCore.gypi:
  • WebCore.pro:
  • WebCore.vcproj/WebCore.vcproj:
  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/JSDOMBinding.cpp: (WebCore::hasCachedDOMObjectWrapperUnchecked): (WebCore::cacheDOMObjectWrapper): (WebCore::hasCachedDOMNodeWrapperUnchecked): (WebCore::cacheDOMNodeWrapper): (WebCore::isObservableThroughDOM): (WebCore::markDOMNodesForDocument): (WebCore::takeWrappers): (WebCore::updateDOMNodeDocument): (WebCore::markDOMObjectWrapper): (WebCore::markDOMNodeWrapper): (WebCore::stringWrapperDestroyed): (WebCore::jsStringSlowCase):
  • bindings/js/JSDOMBinding.h:
  • bindings/js/JSDOMWrapper.cpp: (WebCore::DOMObject::~DOMObject):
  • bindings/js/JSDebugWrapperSet.cpp: Removed.
  • bindings/js/JSDebugWrapperSet.h: Removed.
  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/jsc/BridgeJSC.cpp: (JSC::Bindings::Instance::createRuntimeObject):
  • bridge/jsc/BridgeJSC.h:
  • bridge/runtime_object.cpp: (JSC::Bindings::RuntimeObject::~RuntimeObject):
  • bridge/runtime_root.cpp: (JSC::Bindings::RootObject::invalidate): (JSC::Bindings::RootObject::addRuntimeObject): (JSC::Bindings::RootObject::removeRuntimeObject):
  • bridge/runtime_root.h:
File:
1 edited

Legend:

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

    r77391 r79616  
    2727#define WeakGCMap_h
    2828
    29 #include "Heap.h"
     29#include "Handle.h"
     30#include "JSGlobalData.h"
    3031#include <wtf/HashMap.h>
    3132
    3233namespace JSC {
    3334
    34 class JSCell;
     35// A HashMap for GC'd values that removes entries when the associated value
     36// dies.
     37template<typename KeyType, typename MappedType> class WeakGCMap : private Finalizer {
     38    WTF_MAKE_FAST_ALLOCATED;
     39    WTF_MAKE_NONCOPYABLE(WeakGCMap);
    3540
    36 // A HashMap whose get() function returns emptyValue() for cells awaiting destruction.
    37 template<typename KeyType, typename MappedType>
    38 class WeakGCMap {
    39     WTF_MAKE_FAST_ALLOCATED;
    40     /*
    41     Invariants:
    42         * A value enters the WeakGCMap marked. (Guaranteed by set().)
    43         * A value that becomes unmarked leaves the WeakGCMap before being recycled. (Guaranteed by the value's destructor removing it from the WeakGCMap.)
    44         * A value that becomes unmarked leaves the WeakGCMap before becoming marked again. (Guaranteed by all destructors running before the mark phase begins.)
    45         * During the mark phase, all values in the WeakGCMap are valid. (Guaranteed by all destructors running before the mark phase begins.)
    46     */
     41    typedef HashMap<KeyType, HandleSlot> MapType;
     42    typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
     43    typedef typename MapType::iterator map_iterator;
    4744
    4845public:
    49     typedef typename HashMap<KeyType, DeprecatedPtr<MappedType> >::iterator iterator;
    50     typedef typename HashMap<KeyType, DeprecatedPtr<MappedType> >::const_iterator const_iterator;
     46
     47    struct iterator {
     48        iterator(map_iterator iter)
     49            : m_iterator(iter)
     50        {
     51        }
     52       
     53        std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(m_iterator->second)); }
     54        std::pair<KeyType, HandleSlot> getSlot() const { return *m_iterator; }
     55       
     56        iterator& operator++() { ++m_iterator; return *this; }
     57       
     58        // postfix ++ intentionally omitted
     59       
     60        // Comparison.
     61        bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
     62        bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
     63       
     64    private:
     65            map_iterator m_iterator;
     66    };
     67
     68    WeakGCMap()
     69    {
     70    }
     71
     72    bool isEmpty() { return m_map.isEmpty(); }
     73    void clear()
     74    {
     75        map_iterator end = m_map.end();
     76        for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr)
     77            HandleHeap::heapFor(ptr->second)->deallocate(ptr->second);
     78        m_map.clear();
     79    }
     80
     81    ExternalType get(const KeyType& key) const
     82    {
     83        return HandleTypes<MappedType>::getFromSlot(m_map.get(key));
     84    }
     85
     86    HandleSlot getSlot(const KeyType& key) const
     87    {
     88        return m_map.get(key);
     89    }
     90
     91    void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
     92    {
     93        pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
     94        HandleSlot slot = iter.first->second;
     95        if (iter.second) {
     96            slot = globalData.allocateGlobalHandle();
     97            iter.first->second = slot;
     98            HandleHeap::heapFor(slot)->makeWeak(slot, this, key);
     99        }
     100        HandleHeap::heapFor(slot)->writeBarrier(slot, value);
     101        *slot = value;
     102    }
     103
     104    ExternalType take(const KeyType& key)
     105    {
     106        HandleSlot slot = m_map.take(key);
     107        if (!slot)
     108            return HashTraits<ExternalType>::emptyValue();
     109        ExternalType result = HandleTypes<MappedType>::getFromSlot(slot);
     110        HandleHeap::heapFor(slot)->deallocate(slot);
     111        return result;
     112    }
     113
     114    size_t size() { return m_map.size(); }
     115
     116    bool deprecatedRemove(const KeyType& key, ExternalType value)
     117    {
     118        // This only exists in order to allow some semblance of correctness to
     119        // the JSWeakObjectMapClear API
     120        typename MapType::iterator iter = m_map.find(key);
     121        if (iter == m_map.end())
     122            return false;
     123        HandleSlot slot = iter->second;
     124        ExternalType inmap = HandleTypes<MappedType>::getFromSlot(slot);
     125        if (inmap && inmap != value)
     126            return false;
     127        m_map.remove(iter);
     128        HandleHeap::heapFor(slot)->deallocate(slot);
     129        return true;       
     130    }
     131
     132    iterator begin() { return iterator(m_map.begin()); }
     133    iterator end() { return iterator(m_map.end()); }
    51134   
    52     bool isEmpty() { return m_map.isEmpty(); }
    53     void clear() { m_map.clear(); }
     135    ~WeakGCMap()
     136    {
     137        clear();
     138    }
     139   
     140private:
     141    virtual void finalize(Handle<Unknown>, void* key)
     142    {
     143        HandleSlot slot = m_map.take(static_cast<KeyType>(key));
     144        ASSERT(slot);
     145        HandleHeap::heapFor(slot)->deallocate(slot);
     146    }
    54147
    55     MappedType* get(const KeyType&) const;
    56     pair<iterator, bool> set(const KeyType&, MappedType*);
    57     MappedType* take(const KeyType&);
    58 
    59     // These unchecked functions provide access to a value even if the value's
    60     // mark bit is not set. This is used, among other things, to retrieve values
    61     // during the GC mark phase, which begins by clearing all mark bits.
    62    
    63     size_t uncheckedSize() { return m_map.size(); }
    64 
    65     MappedType* uncheckedGet(const KeyType& key) const { return m_map.get(key).get(); }
    66     DeprecatedPtr<MappedType>* uncheckedGetSlot(const KeyType& key)
    67     {
    68         iterator iter = m_map.find(key);
    69         if (iter == m_map.end())
    70             return 0;
    71         return &iter->second;
    72     }
    73     bool uncheckedRemove(const KeyType&, MappedType*);
    74 
    75     iterator uncheckedBegin() { return m_map.begin(); }
    76     iterator uncheckedEnd() { return m_map.end(); }
    77 
    78     const_iterator uncheckedBegin() const { return m_map.begin(); }
    79     const_iterator uncheckedEnd() const { return m_map.end(); }
    80 
    81     bool isValid(iterator it) const { return Heap::isMarked(it->second.get()); }
    82     bool isValid(const_iterator it) const { return Heap::isMarked(it->second.get()); }
    83 
    84 private:
    85     HashMap<KeyType, DeprecatedPtr<MappedType> > m_map;
     148    MapType m_map;
    86149};
    87 
    88 template<typename KeyType, typename MappedType>
    89 inline MappedType* WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
    90 {
    91     MappedType* result = m_map.get(key).get();
    92     if (result == HashTraits<MappedType*>::emptyValue())
    93         return result;
    94     if (!Heap::isMarked(result))
    95         return HashTraits<MappedType*>::emptyValue();
    96     return result;
    97 }
    98 
    99 template<typename KeyType, typename MappedType>
    100 MappedType* WeakGCMap<KeyType, MappedType>::take(const KeyType& key)
    101 {
    102     MappedType* result = m_map.take(key).get();
    103     if (result == HashTraits<MappedType*>::emptyValue())
    104         return result;
    105     if (!Heap::isMarked(result))
    106         return HashTraits<MappedType*>::emptyValue();
    107     return result;
    108 }
    109 
    110 template<typename KeyType, typename MappedType>
    111 pair<typename WeakGCMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, MappedType* value)
    112 {
    113     Heap::setMarked(value); // If value is newly allocated, it's not marked, so mark it now.
    114     pair<iterator, bool> result = m_map.add(key, value);
    115     if (!result.second) { // pre-existing entry
    116         result.second = !Heap::isMarked(result.first->second.get());
    117         result.first->second = value;
    118     }
    119     return result;
    120 }
    121 
    122 template<typename KeyType, typename MappedType>
    123 bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, MappedType* value)
    124 {
    125     iterator it = m_map.find(key);
    126     if (it == m_map.end())
    127         return false;
    128     if (it->second.get() != value)
    129         return false;
    130     m_map.remove(it);
    131     return true;
    132 }
    133150
    134151} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.