Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Unified Diff: Source/platform/heap/Heap.h

Issue 223373002: Create HeapLinkedHashSet and LinkedHashSet, ordered heap-friendly hash sets. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Review feedback and many more tests Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/platform/heap/Heap.h
diff --git a/Source/platform/heap/Heap.h b/Source/platform/heap/Heap.h
index d28cac06c23c38209c4bfe9e030d5e477a8aaa0f..21e08e7e5f62ebc415cf5c7431af3162248d4aec 100644
--- a/Source/platform/heap/Heap.h
+++ b/Source/platform/heap/Heap.h
@@ -37,6 +37,7 @@
#include "platform/heap/Visitor.h"
#include "wtf/Assertions.h"
+#include "wtf/LinkedHashSet.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassRefPtr.h"
@@ -1285,7 +1286,7 @@ public:
template<typename T, typename Traits>
static void trace(Visitor* visitor, T& t)
{
- CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, false, T, Traits>::mark(visitor, t);
+ CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, WeakPointersActWeak, T, Traits>::mark(visitor, t);
}
template<typename T>
@@ -1313,6 +1314,9 @@ public:
return hasDeadMember(visitor, t.key) || hasDeadMember(visitor, t.value);
}
+ template<typename T>
+ static bool hasDeadMember(Visitor*, const WTF::LinkedHashSetNode<T>&);
+
static void registerWeakMembers(Visitor* visitor, const void* closure, const void* object, WeakPointerCallback callback)
{
visitor->registerWeakMembers(closure, object, callback);
@@ -1380,6 +1384,12 @@ template<
typename TraitsArg = HashTraits<ValueArg> >
class HeapHashSet : public HashSet<ValueArg, HashArg, TraitsArg, HeapAllocator> { };
+template<
+ typename ValueArg,
+ typename HashArg = typename DefaultHash<ValueArg>::Hash,
+ typename TraitsArg = HashTraits<ValueArg> >
+class HeapLinkedHashSet : public LinkedHashSet<ValueArg, HashArg, TraitsArg, HeapAllocator> { };
+
template<typename T, size_t inlineCapacity = 0>
class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
public:
@@ -1414,6 +1424,12 @@ public:
};
template<typename T>
+bool HeapAllocator::hasDeadMember(Visitor* visitor, const WTF::LinkedHashSetNode<T>& t)
+{
+ return hasDeadMember(visitor, t.m_value);
+}
+
+template<typename T>
struct ThreadingTrait<Member<T> > {
static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
};
@@ -1502,6 +1518,19 @@ const GCInfo GCInfoTrait<HashSet<T, U, V, HeapAllocator> >::info = {
false, // HashSet needs no finalizer.
};
+template<typename T, typename U, typename V>
+struct GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator> > {
+ static const GCInfo* get() { return &info; }
+ static const GCInfo info;
+};
+
+template<typename T, typename U, typename V>
+const GCInfo GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator> >::info = {
+ TraceTrait<LinkedHashSet<T, U, V, HeapAllocator> >::trace,
+ LinkedHashSet<T, U, V, HeapAllocator>::finalize,
+ true, // Needs finalization. The anchor needs to unlink itself from the chain.
+};
+
template<typename T>
struct GCInfoTrait<Vector<T, 0, HeapAllocator> > {
static const GCInfo* get() { return &info; }
@@ -1558,7 +1587,7 @@ const GCInfo GCInfoTrait<HeapHashTableBacking<Table> >::info = {
Table::ValueTraits::needsDestruction,
};
-template<bool markWeakMembersStrongly, typename T, typename Traits>
+template<typename T, typename Traits>
struct BaseVisitVectorBackingTrait {
static void mark(WebCore::Visitor* visitor, void* self)
{
@@ -1575,11 +1604,11 @@ struct BaseVisitVectorBackingTrait {
// elements to mark.
size_t length = header->payloadSize() / sizeof(T);
for (size_t i = 0; i < length; i++)
- CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, markWeakMembersStrongly, T, Traits>::mark(visitor, array[i]);
+ CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, WeakPointersActStrong, T, Traits>::mark(visitor, array[i]);
}
};
-template<bool markWeakMembersStrongly, typename Table>
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Table>
struct BaseVisitHashTableBackingTrait {
typedef typename Table::ValueType Value;
typedef typename Table::ValueTraits Traits;
@@ -1590,83 +1619,106 @@ struct BaseVisitHashTableBackingTrait {
size_t length = header->payloadSize() / sizeof(Value);
for (size_t i = 0; i < length; i++) {
if (!WTF::HashTableHelper<Value, typename Table::ExtractorType, typename Table::KeyTraitsType>::isEmptyOrDeletedBucket(array[i]))
- CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, markWeakMembersStrongly, Value, Traits>::mark(visitor, array[i]);
+ CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, strongify, Value, Traits>::mark(visitor, array[i]);
}
}
};
-template<bool markWeakMembersStrongly, typename Key, typename Value, typename Traits>
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Value, typename Traits>
struct BaseVisitKeyValuePairTrait {
static void mark(WebCore::Visitor* visitor, WTF::KeyValuePair<Key, Value>& self)
{
- ASSERT(WTF::ShouldBeTraced<Traits>::value || (Traits::isWeak && markWeakMembersStrongly));
- CollectionBackingTraceTrait<WTF::ShouldBeTraced<typename Traits::KeyTraits>::value, Traits::KeyTraits::isWeak, markWeakMembersStrongly, Key, typename Traits::KeyTraits>::mark(visitor, self.key);
- CollectionBackingTraceTrait<WTF::ShouldBeTraced<typename Traits::ValueTraits>::value, Traits::ValueTraits::isWeak, markWeakMembersStrongly, Value, typename Traits::ValueTraits>::mark(visitor, self.value);
+ ASSERT(WTF::ShouldBeTraced<Traits>::value || (Traits::isWeak && strongify == WeakPointersActStrong));
+ CollectionBackingTraceTrait<WTF::ShouldBeTraced<typename Traits::KeyTraits>::value, Traits::KeyTraits::isWeak, strongify, Key, typename Traits::KeyTraits>::mark(visitor, self.key);
+ CollectionBackingTraceTrait<WTF::ShouldBeTraced<typename Traits::ValueTraits>::value, Traits::ValueTraits::isWeak, strongify, Value, typename Traits::ValueTraits>::mark(visitor, self.value);
+ }
+};
+
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Traits>
+struct BaseVisitLinkedNodeTrait {
+ static void mark(WebCore::Visitor* visitor, WTF::LinkedHashSetNode<Value>& self)
+ {
+ ASSERT(WTF::ShouldBeTraced<Traits>::value || (Traits::isWeak && strongify == WeakPointersActStrong));
+ CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, strongify, Value, Traits>::mark(visitor, self.m_value);
}
};
-// FFX - Things that don't need marking and have no weak pointers.
-template<bool markWeakMembersStrongly, typename T, typename U>
-struct CollectionBackingTraceTrait<false, false, markWeakMembersStrongly, T, U> {
+// Catch-all for things that don't need marking and have no weak pointers. We
+// do nothing, even if WeakPointersActStrong.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename U>
+struct CollectionBackingTraceTrait<false, false, strongify, T, U> {
static void mark(Visitor*, const T&) { }
static void mark(Visitor*, const void*) { }
};
-// FTF - Things that don't need marking. They have weak pointers, but we are
-// not marking weak pointers in this object in this GC.
+// Catch-all for things that don't need marking. They have weak pointers, but
+// we are not marking weak pointers in this object in this GC.
template<typename T, typename U>
-struct CollectionBackingTraceTrait<false, true, false, T, U> {
+struct CollectionBackingTraceTrait<false, true, WeakPointersActWeak, T, U> {
static void mark(Visitor*, const T&) { }
static void mark(Visitor*, const void*) { }
};
-// For each type that we understand we have the FTT case and the TXX case. The
-// FTT case is where we would not normally need to mark it, but it has weak
-// pointers, and we are marking them as strong. The TXX case is the regular
-// case for things that need marking.
+// For each type that we understand we have the strongified case and the
+// needsMarking case. The strongified case is where we would not normally need
+// to mark it, but it has weak pointers, and we are marking them as strong
+// because there is a live iterator that would be disturbed if the collection
+// were subject to weak processing right now. The needsMarking case is the
+// case for things that need marking, which may also be strongified (eg. for
+// a map pair that has a key that is weak and a value that needs marking).
-// FTT (vector)
-template<typename T, typename Traits>
-struct CollectionBackingTraceTrait<false, true, true, HeapVectorBacking<T, Traits>, void> : public BaseVisitVectorBackingTrait<true, T, Traits> {
+// The body is the same for most objects, but there are two template
+// specializations because there is no way to express needsMarking || (isWeak
+// && WeakPointersActStrong) in a single specialization.
+
+// Hash table that would not normally need marking, but strongified.
+template<typename Table>
+struct CollectionBackingTraceTrait<false, true, WeakPointersActStrong, HeapHashTableBacking<Table>, void> : public BaseVisitHashTableBackingTrait<WeakPointersActStrong, Table> {
};
-// TXX (vector)
-template<bool isWeak, bool markWeakMembersStrongly, typename T, typename Traits>
-struct CollectionBackingTraceTrait<true, isWeak, markWeakMembersStrongly, HeapVectorBacking<T, Traits>, void> : public BaseVisitVectorBackingTrait<markWeakMembersStrongly, T, Traits> {
+// Hash table that needs marking, optionally also strongified.
+template<bool isWeak, ShouldWeakPointersBeMarkedStrongly strongify, typename Table>
+struct CollectionBackingTraceTrait<true, isWeak, strongify, HeapHashTableBacking<Table>, void> : public BaseVisitHashTableBackingTrait<strongify, Table> {
};
-// FTT (hash table)
-template<typename Table>
-struct CollectionBackingTraceTrait<false, true, true, HeapHashTableBacking<Table>, void> : public BaseVisitHashTableBackingTrait<true, Table> {
+// Key-value pair that would not normally need marking, but strongified.
+template<typename Key, typename Value, typename Traits>
+struct CollectionBackingTraceTrait<false, true, WeakPointersActStrong, WTF::KeyValuePair<Key, Value>, Traits> : public BaseVisitKeyValuePairTrait<WeakPointersActStrong, Key, Value, Traits> {
};
-// TXX (hash table)
-template<bool isWeak, bool markWeakMembersStrongly, typename Table>
-struct CollectionBackingTraceTrait<true, isWeak, markWeakMembersStrongly, HeapHashTableBacking<Table>, void> : public BaseVisitHashTableBackingTrait<markWeakMembersStrongly, Table> {
+// Key value pair that needs marking, optionally also strongified.
+template<bool isWeak, ShouldWeakPointersBeMarkedStrongly strongify, typename Key, typename Value, typename Traits>
+struct CollectionBackingTraceTrait<true, isWeak, strongify, WTF::KeyValuePair<Key, Value>, Traits> : public BaseVisitKeyValuePairTrait<strongify, Key, Value, Traits> {
};
-// FTT (key value pair)
-template<typename Key, typename Value, typename Traits>
-struct CollectionBackingTraceTrait<false, true, true, WTF::KeyValuePair<Key, Value>, Traits> : public BaseVisitKeyValuePairTrait<true, Key, Value, Traits> {
+// List hash set node that would not normally need marking, but strongified.
+template<typename Value, typename Traits>
+struct CollectionBackingTraceTrait<false, true, WeakPointersActStrong, WTF::LinkedHashSetNode<Value>, Traits> : public BaseVisitLinkedNodeTrait<WeakPointersActStrong, Value, Traits> {
};
-// TXX (key value pair)
-template<bool isWeak, bool markWeakMembersStrongly, typename Key, typename Value, typename Traits>
-struct CollectionBackingTraceTrait<true, isWeak, markWeakMembersStrongly, WTF::KeyValuePair<Key, Value>, Traits> : public BaseVisitKeyValuePairTrait<markWeakMembersStrongly, Key, Value, Traits> {
+// List hash set node that needs marking, optionally also strongified.
+template<bool isWeak, ShouldWeakPointersBeMarkedStrongly strongify, typename Value, typename Traits>
+struct CollectionBackingTraceTrait<true, isWeak, strongify, WTF::LinkedHashSetNode<Value>, Traits> : public BaseVisitLinkedNodeTrait<strongify, Value, Traits> {
};
-// TFX (member)
-template<bool markWeakMembersStrongly, typename T, typename Traits>
-struct CollectionBackingTraceTrait<true, false, markWeakMembersStrongly, Member<T>, Traits> {
+// Vector backing that needs marking. We don't support weak members in vectors,
+// so we don't need a strongified variant here.
+template<bool isWeak, ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
+struct CollectionBackingTraceTrait<true, isWeak, strongify, HeapVectorBacking<T, Traits>, void> : public BaseVisitVectorBackingTrait<T, Traits> {
+};
+
+// Member always needs marking, never weak.
+template<ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
+struct CollectionBackingTraceTrait<true, false, strongify, Member<T>, Traits> {
static void mark(WebCore::Visitor* visitor, Member<T> self)
{
visitor->mark(self.get());
}
};
-// FTT (weak member)
+// Weak member never has needsMarking, always weak, strongified case.
template<typename T, typename Traits>
-struct CollectionBackingTraceTrait<false, true, true, WeakMember<T>, Traits> {
+struct CollectionBackingTraceTrait<false, true, WeakPointersActStrong, WeakMember<T>, Traits> {
static void mark(WebCore::Visitor* visitor, WeakMember<T> self)
{
// This can mark weak members as if they were strong. The reason we
@@ -1680,9 +1732,12 @@ struct CollectionBackingTraceTrait<false, true, true, WeakMember<T>, Traits> {
// Catch-all for things that have a way to trace. For things that contain weak
// pointers they will generally be visited weakly even if
-// markWeakMembersStrongly is true. This is what you want.
-template<bool isWeak, bool markWeakMembersStrongly, typename T, typename Traits>
-struct CollectionBackingTraceTrait<true, isWeak, markWeakMembersStrongly, T, Traits> {
+// WeakPointersActStrong. This is a deliberate choice: We currently don't
+// strongify weak members that are embedded in larger structures, they are just
+// zeroed during weak processing without the whole structure being
+// removed from the collection.
+template<bool isWeak, ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
+struct CollectionBackingTraceTrait<true, isWeak, strongify, T, Traits> {
static void mark(WebCore::Visitor* visitor, T& t)
{
TraceTrait<T>::trace(visitor, &t);
@@ -1696,7 +1751,7 @@ struct TraceTrait<HeapVectorBacking<T, Traits> > {
{
COMPILE_ASSERT(!Traits::isWeak, WeDontSupportWeaknessInHeapVectors);
if (WTF::ShouldBeTraced<Traits>::value)
- CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, false, false, HeapVectorBacking<T, Traits>, void>::mark(visitor, self);
+ CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, false, WeakPointersActWeak, HeapVectorBacking<T, Traits>, void>::mark(visitor, self);
}
static void mark(Visitor* visitor, const Backing* backing)
{
@@ -1723,7 +1778,7 @@ struct TraceTrait<HeapHashTableBacking<Table> > {
static void trace(WebCore::Visitor* visitor, void* self)
{
if (WTF::ShouldBeTraced<Traits>::value || Traits::isWeak)
- CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, true, Backing, void>::mark(visitor, self);
+ CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::isWeak, WeakPointersActStrong, Backing, void>::mark(visitor, self);
}
static void mark(Visitor* visitor, const Backing* backing)
{
@@ -1760,6 +1815,8 @@ template<typename T, typename U, typename V, typename W, typename X>
struct GCInfoTrait<HeapHashMap<T, U, V, W, X> > : public GCInfoTrait<HashMap<T, U, V, W, X, HeapAllocator> > { };
template<typename T, typename U, typename V>
struct GCInfoTrait<HeapHashSet<T, U, V> > : public GCInfoTrait<HashSet<T, U, V, HeapAllocator> > { };
+template<typename T, typename U, typename V>
+struct GCInfoTrait<HeapLinkedHashSet<T, U, V> > : public GCInfoTrait<LinkedHashSet<T, U, V, HeapAllocator> > { };
template<typename T, size_t inlineCapacity>
struct GCInfoTrait<HeapVector<T, inlineCapacity> > : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator> > { };

Powered by Google App Engine
This is Rietveld 408576698