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

Unified Diff: Source/heap/HeapTest.cpp

Issue 223373002: Create HeapLinkedHashSet and LinkedHashSet, ordered heap-friendly hash sets. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Remove inadvertent changes Created 6 years, 9 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/heap/HeapTest.cpp
diff --git a/Source/heap/HeapTest.cpp b/Source/heap/HeapTest.cpp
index f1bbe104fdfd41094719fef93bc9a15c7321083e..fc56a36b83aeb6ca79f52e01d38efc46c1dc6f78 100644
--- a/Source/heap/HeapTest.cpp
+++ b/Source/heap/HeapTest.cpp
@@ -38,6 +38,7 @@
#include "heap/Visitor.h"
#include "wtf/HashTraits.h"
+#include "wtf/LinkedHashSet.h"
#include <gtest/gtest.h>
@@ -300,9 +301,39 @@ private:
int m_x;
};
+class OffHeapInt : public RefCounted<OffHeapInt> {
+public:
+ static RefPtr<OffHeapInt> create(int x)
+ {
+ return adoptRef(new OffHeapInt(x));
+ }
+
+ virtual ~OffHeapInt()
+ {
+ ++s_destructorCalls;
+ }
+
+ static int s_destructorCalls;
+ static void trace(Visitor*) { }
Mads Ager (chromium) 2014/04/03 09:24:35 This is off heap, why do you need a trace method (
Erik Corry 2014/04/10 10:47:37 Done.
+
+ int value() const { return m_x; }
+
+ bool operator==(const OffHeapInt& other) const { return other.value() == value(); }
+
+ unsigned hash() { return IntHash<int>::hash(m_x); }
+
+protected:
+ OffHeapInt(int x) : m_x(x) { }
+
+private:
+ OffHeapInt();
+ int m_x;
+};
+
USED_FROM_MULTIPLE_THREADS(IntWrapper);
int IntWrapper::s_destructorCalls = 0;
+int OffHeapInt::s_destructorCalls = 0;
class ThreadedTesterBase {
protected:
@@ -1882,15 +1913,65 @@ class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
public:
static OffHeapContainer* create() { return new OffHeapContainer(); }
+ static const int iterations = 300;
+ static const int deadWrappers = 2400;
+
OffHeapContainer()
{
- m_deque1.append(ShouldBeTraced(IntWrapper::create(1)));
- m_vector1.append(ShouldBeTraced(IntWrapper::create(2)));
- m_deque2.append(IntWrapper::create(3));
- m_vector2.append(IntWrapper::create(4));
- m_hashSet.add(IntWrapper::create(5));
- m_hashMap.add(this, IntWrapper::create(6));
- m_listHashSet.add(IntWrapper::create(7));
+ for (int i = 0; i < iterations; i++) {
+ m_deque1.append(ShouldBeTraced(IntWrapper::create(i)));
+ m_vector1.append(ShouldBeTraced(IntWrapper::create(i)));
+ m_deque2.append(IntWrapper::create(i));
+ m_vector2.append(IntWrapper::create(i));
+ m_hashSet.add(IntWrapper::create(i));
+ m_hashMap.add(i + 103, IntWrapper::create(i));
+ m_listHashSet.add(IntWrapper::create(i));
+ m_linkedHashSet.add(IntWrapper::create(i));
+ }
+
+ Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin());
+ Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin());
+ Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin());
+ Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin());
+ HashSet<Member<IntWrapper> >::iterator setIterator(m_hashSet.begin());
+ HashMap<int, Member<IntWrapper> >::iterator mapIterator(m_hashMap.begin());
+ ListHashSet<Member<IntWrapper> >::iterator listSetIterator(m_listHashSet.begin());
+ LinkedHashSet<Member<IntWrapper> >::iterator linkedSetIterator(m_linkedHashSet.begin());
+
+ for (int i = 0; i < iterations; i++) {
+ EXPECT_EQ(i, m_vector1[i].m_wrapper->value());
+ EXPECT_EQ(i, m_vector2[i]->value());
+ EXPECT_EQ(i, d1Iterator->m_wrapper->value());
+ EXPECT_EQ(i, v1Iterator->m_wrapper->value());
+ EXPECT_EQ(i, d2Iterator->get()->value());
+ EXPECT_EQ(i, v2Iterator->get()->value());
+ EXPECT_EQ(i, linkedSetIterator->get()->value());
+ int value = setIterator->get()->value();
+ EXPECT_LE(0, value);
+ EXPECT_GT(iterations, value);
+ value = listSetIterator->get()->value();
+ EXPECT_LE(0, value);
+ EXPECT_GT(iterations, value);
+ value = mapIterator->value.get()->value();
+ EXPECT_LE(0, value);
+ EXPECT_GT(iterations, value);
+ ++d1Iterator;
+ ++v1Iterator;
+ ++d2Iterator;
+ ++v2Iterator;
+ ++setIterator;
+ ++mapIterator;
+ ++listSetIterator;
+ ++linkedSetIterator;
+ }
+ EXPECT_EQ(d1Iterator, m_deque1.end());
+ EXPECT_EQ(v1Iterator, m_vector1.end());
+ EXPECT_EQ(d2Iterator, m_deque2.end());
+ EXPECT_EQ(v2Iterator, m_vector2.end());
+ EXPECT_EQ(setIterator, m_hashSet.end());
+ EXPECT_EQ(mapIterator, m_hashMap.end());
+ EXPECT_EQ(listSetIterator, m_listHashSet.end());
+ EXPECT_EQ(linkedSetIterator, m_linkedHashSet.end());
}
void trace(Visitor* visitor)
@@ -1902,6 +1983,7 @@ public:
visitor->trace(m_hashSet);
visitor->trace(m_hashMap);
visitor->trace(m_listHashSet);
+ visitor->trace(m_linkedHashSet);
}
Deque<ShouldBeTraced> m_deque1;
@@ -1909,11 +1991,11 @@ public:
Deque<Member<IntWrapper> > m_deque2;
Vector<Member<IntWrapper> > m_vector2;
HashSet<Member<IntWrapper> > m_hashSet;
- HashMap<void*, Member<IntWrapper> > m_hashMap;
+ HashMap<int, Member<IntWrapper> > m_hashMap;
ListHashSet<Member<IntWrapper> > m_listHashSet;
+ LinkedHashSet<Member<IntWrapper> > m_linkedHashSet;
};
-
// These class definitions test compile-time asserts with transition
// types. They are therefore unused in test code and just need to
// compile. This is intentional; do not delete the A and B classes below.
@@ -2277,6 +2359,126 @@ TEST(HeapTest, HeapWeakCollectionSimple)
EXPECT_EQ(2u, weakSet->size());
}
+template<typename Set>
+void linkedSetHelper(bool strong)
+{
+ HeapStats initialHeapStats;
+ clearOutOldGarbage(&initialHeapStats);
+ IntWrapper::s_destructorCalls = 0;
+
+ typedef const Set& ConstSet;
Mads Ager (chromium) 2014/04/03 09:24:35 Remove the typedef for a type you are using only o
Erik Corry 2014/04/10 10:47:37 Done.
+
+ PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
+
+ Persistent<Set> set = new Set();
+ Persistent<Set> setX = new Set();
Mads Ager (chromium) 2014/04/03 09:24:35 What does the X mean? If it is just a random other
Erik Corry 2014/04/10 10:47:37 Done.
+
+ ConstSet cSet = *set.get();
Mads Ager (chromium) 2014/04/03 09:24:35 cSet -> constSetReference
Erik Corry 2014/04/10 10:47:37 constSet
+
+ keepNumbersAlive.append(IntWrapper::create(2));
+ keepNumbersAlive.append(IntWrapper::create(103));
+ keepNumbersAlive.append(IntWrapper::create(10));
+
+ set->add(IntWrapper::create(0));
+ set->add(keepNumbersAlive[0]);
+ set->add(keepNumbersAlive[1]);
+ set->add(keepNumbersAlive[2]);
+
+ setX->clear();
+ setX->add(IntWrapper::create(42));
+ setX->clear();
+
+ EXPECT_EQ(4u, set->size());
+ typename Set::iterator it(set->begin());
+ typename Set::reverse_iterator reverse(set->rbegin());
+ typename Set::const_iterator cit(cSet.begin());
+ typename Set::const_reverse_iterator creverse(cSet.rbegin());
+
+ EXPECT_EQ(0, (*it)->value());
+ EXPECT_EQ(0, (*cit)->value());
+ ++it;
+ ++cit;
+ EXPECT_EQ(2, (*it)->value());
+ EXPECT_EQ(2, (*cit)->value());
+ --it;
+ --cit;
+ EXPECT_EQ(0, (*it)->value());
+ EXPECT_EQ(0, (*cit)->value());
+ ++it;
+ ++cit;
+ ++it;
+ ++cit;
+ EXPECT_EQ(103, (*it)->value());
+ EXPECT_EQ(103, (*cit)->value());
+ ++it;
+ ++cit;
+ EXPECT_EQ(10, (*it)->value());
+ EXPECT_EQ(10, (*cit)->value());
+ ++it;
+ ++cit;
+
+ EXPECT_EQ(10, (*reverse)->value());
+ EXPECT_EQ(10, (*creverse)->value());
+ ++reverse;
+ ++creverse;
+ EXPECT_EQ(103, (*reverse)->value());
+ EXPECT_EQ(103, (*creverse)->value());
+ --reverse;
+ --creverse;
+ EXPECT_EQ(10, (*reverse)->value());
+ EXPECT_EQ(10, (*creverse)->value());
+ ++reverse;
+ ++creverse;
+ ++reverse;
+ ++creverse;
+ EXPECT_EQ(2, (*reverse)->value());
+ EXPECT_EQ(2, (*creverse)->value());
+ ++reverse;
+ ++creverse;
+ EXPECT_EQ(0, (*reverse)->value());
+ EXPECT_EQ(0, (*creverse)->value());
+ ++reverse;
+ ++creverse;
+
+ EXPECT_EQ(set->end(), it);
+ EXPECT_EQ(cSet.end(), cit);
+ EXPECT_EQ(set->rend(), reverse);
+ EXPECT_EQ(cSet.rend(), creverse);
+
+ typename Set::iterator iX(setX->begin());
+ EXPECT_EQ(setX->end(), iX);
+
+ if (strong)
+ set->remove(keepNumbersAlive[0]);
+
+ keepNumbersAlive[0] = nullptr;
+
+ Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
+
+ EXPECT_EQ(2u + (strong ? 1u : 0u), set->size());
+
+ EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls);
+
+ typename Set::iterator i2(set->begin());
+ if (strong) {
+ EXPECT_EQ(0, (*i2)->value());
+ ++i2;
+ EXPECT_NE(set->end(), i2);
+ }
+ EXPECT_EQ(103, (*i2)->value());
+ ++i2;
+ EXPECT_NE(set->end(), i2);
+ EXPECT_EQ(10, (*i2)->value());
+ ++i2;
+ EXPECT_EQ(set->end(), i2);
+}
+
+TEST(HeapTest, HeapWeakLinkedHashSet)
+{
+ linkedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true);
+ linkedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false);
+}
+
class ThingWithDestructor {
public:
ThingWithDestructor()
@@ -2903,7 +3105,7 @@ TEST(HeapTest, VisitOffHeapCollections)
EXPECT_EQ(0, IntWrapper::s_destructorCalls);
container = nullptr;
Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
- EXPECT_EQ(7, IntWrapper::s_destructorCalls);
+ EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls);
}
TEST(HeapTest, PersistentHeapCollectionTypes)

Powered by Google App Engine
This is Rietveld 408576698