2 * Copyright (C) 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
30 #include "JSGlobalData.h"
31 #include <wtf/HashMap.h>
35 // A HashMap for GC'd values that removes entries when the associated value
37 template <typename KeyType
, typename MappedType
> struct DefaultWeakGCMapFinalizerCallback
{
38 static void* finalizerContextFor(KeyType key
)
40 return reinterpret_cast<void*>(key
);
43 static KeyType
keyForFinalizer(void* context
, typename HandleTypes
<MappedType
>::ExternalType
)
45 return reinterpret_cast<KeyType
>(context
);
49 template<typename KeyType
, typename MappedType
, typename FinalizerCallback
= DefaultWeakGCMapFinalizerCallback
<KeyType
, MappedType
>, typename HashArg
= typename DefaultHash
<KeyType
>::Hash
, typename KeyTraitsArg
= HashTraits
<KeyType
> >
50 class WeakGCMap
: private WeakHandleOwner
{
51 WTF_MAKE_FAST_ALLOCATED
;
52 WTF_MAKE_NONCOPYABLE(WeakGCMap
);
54 typedef HashMap
<KeyType
, HandleSlot
, HashArg
, KeyTraitsArg
> MapType
;
55 typedef typename HandleTypes
<MappedType
>::ExternalType ExternalType
;
56 typedef typename
MapType::iterator map_iterator
;
61 friend class WeakGCMap
;
62 iterator(map_iterator iter
)
67 std::pair
<KeyType
, ExternalType
> get() const { return std::make_pair(m_iterator
->first
, HandleTypes
<MappedType
>::getFromSlot(m_iterator
->second
)); }
68 std::pair
<KeyType
, HandleSlot
> getSlot() const { return *m_iterator
; }
70 iterator
& operator++() { ++m_iterator
; return *this; }
72 // postfix ++ intentionally omitted
75 bool operator==(const iterator
& other
) const { return m_iterator
== other
.m_iterator
; }
76 bool operator!=(const iterator
& other
) const { return m_iterator
!= other
.m_iterator
; }
79 map_iterator m_iterator
;
86 bool isEmpty() { return m_map
.isEmpty(); }
89 map_iterator end
= m_map
.end();
90 for (map_iterator ptr
= m_map
.begin(); ptr
!= end
; ++ptr
)
91 HandleHeap::heapFor(ptr
->second
)->deallocate(ptr
->second
);
95 bool contains(const KeyType
& key
) const
97 return m_map
.contains(key
);
100 iterator
find(const KeyType
& key
)
102 return m_map
.find(key
);
105 void remove(iterator iter
)
107 ASSERT(iter
.m_iterator
!= m_map
.end());
108 HandleSlot slot
= iter
.m_iterator
->second
;
110 HandleHeap::heapFor(slot
)->deallocate(slot
);
111 m_map
.remove(iter
.m_iterator
);
114 ExternalType
get(const KeyType
& key
) const
116 return HandleTypes
<MappedType
>::getFromSlot(m_map
.get(key
));
119 HandleSlot
getSlot(const KeyType
& key
) const
121 return m_map
.get(key
);
124 pair
<iterator
, bool> add(JSGlobalData
& globalData
, const KeyType
& key
, ExternalType value
)
126 pair
<typename
MapType::iterator
, bool> iter
= m_map
.add(key
, 0);
128 HandleSlot slot
= globalData
.allocateGlobalHandle();
129 iter
.first
->second
= slot
;
130 HandleHeap::heapFor(slot
)->makeWeak(slot
, this, FinalizerCallback::finalizerContextFor(key
));
131 HandleHeap::heapFor(slot
)->writeBarrier(slot
, value
);
137 void set(iterator iter
, ExternalType value
)
139 HandleSlot slot
= iter
.m_iterator
->second
;
141 HandleHeap::heapFor(slot
)->writeBarrier(slot
, value
);
145 void set(JSGlobalData
& globalData
, const KeyType
& key
, ExternalType value
)
147 pair
<typename
MapType::iterator
, bool> iter
= m_map
.add(key
, 0);
148 HandleSlot slot
= iter
.first
->second
;
150 slot
= globalData
.allocateGlobalHandle();
151 HandleHeap::heapFor(slot
)->makeWeak(slot
, this, key
);
152 iter
.first
->second
= slot
;
154 HandleHeap::heapFor(slot
)->writeBarrier(slot
, value
);
158 ExternalType
take(const KeyType
& key
)
160 HandleSlot slot
= m_map
.take(key
);
162 return HashTraits
<ExternalType
>::emptyValue();
163 ExternalType result
= HandleTypes
<MappedType
>::getFromSlot(slot
);
164 HandleHeap::heapFor(slot
)->deallocate(slot
);
168 size_t size() { return m_map
.size(); }
170 iterator
begin() { return iterator(m_map
.begin()); }
171 iterator
end() { return iterator(m_map
.end()); }
179 virtual void finalize(Handle
<Unknown
> handle
, void* context
)
181 HandleSlot slot
= m_map
.take(FinalizerCallback::keyForFinalizer(context
, HandleTypes
<MappedType
>::getFromSlot(handle
.slot())));
183 HandleHeap::heapFor(slot
)->deallocate(slot
);
191 #endif // WeakGCMap_h