Commit ca0b5b5e authored by Omer Katz's avatar Omer Katz Committed by Commit Bot

heap: Additional concurrent marking tests

Adding tests for remaining heap collection types.

Also refactor existing tests to use a template that gets the collection
type. This reduces most of the boilerplate.
Since interfaces of existing collection slightly differ, using *Adapter
classes to wrap missing methods.

Bug: 986235
Change-Id: I2717fbebe9396caf7e25309b8b285f698347c9c2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1962855
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Reviewed-by: default avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#727961}
parent 7dc9d73d
...@@ -31,238 +31,216 @@ class CollectionWrapper : public GarbageCollected<CollectionWrapper<T>> { ...@@ -31,238 +31,216 @@ class CollectionWrapper : public GarbageCollected<CollectionWrapper<T>> {
}; };
// ============================================================================= // =============================================================================
// Tests that expose data races when modifying collections ================ // Tests that expose data races when modifying collections =====================
// ============================================================================= // =============================================================================
TEST_F(ConcurrentMarkingTest, AddToHashMap) { template <typename C>
void AddToCollection() {
constexpr int kIterations = 100;
IncrementalMarkingTestDriver driver(ThreadState::Current()); IncrementalMarkingTestDriver driver(ThreadState::Current());
using Map = HeapHashMap<Member<IntegerObject>, Member<IntegerObject>>; Persistent<CollectionWrapper<C>> persistent =
Persistent<CollectionWrapper<Map>> persistent = MakeGarbageCollected<CollectionWrapper<C>>();
MakeGarbageCollected<CollectionWrapper<Map>>(); C* collection = persistent->GetCollection();
Map* map = persistent->GetCollection();
driver.Start(); driver.Start();
for (int i = 0; i < 100; ++i) { for (int i = 0; i < kIterations; ++i) {
driver.SingleConcurrentStep(); driver.SingleConcurrentStep();
for (int j = 0; j < 100; ++j) { for (int j = 0; j < kIterations; ++j) {
int num = 100 * i + j; int num = kIterations * i + j;
map->insert(MakeGarbageCollected<IntegerObject>(num), collection->insert(MakeGarbageCollected<IntegerObject>(num));
MakeGarbageCollected<IntegerObject>(num));
} }
} }
driver.FinishSteps(); driver.FinishSteps();
driver.FinishGC(); driver.FinishGC();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromHashMap) { template <typename C>
void RemoveFromCollection() {
constexpr int kIterations = 100;
IncrementalMarkingTestDriver driver(ThreadState::Current()); IncrementalMarkingTestDriver driver(ThreadState::Current());
using Map = HeapHashMap<Member<IntegerObject>, Member<IntegerObject>>; Persistent<CollectionWrapper<C>> persistent =
Persistent<CollectionWrapper<Map>> persistent = MakeGarbageCollected<CollectionWrapper<C>>();
MakeGarbageCollected<CollectionWrapper<Map>>(); C* collection = persistent->GetCollection();
Map* map = persistent->GetCollection(); for (int i = 0; i < (kIterations * kIterations); ++i) {
for (int i = 0; i < 10000; ++i) { collection->insert(MakeGarbageCollected<IntegerObject>(i));
map->insert(MakeGarbageCollected<IntegerObject>(i),
MakeGarbageCollected<IntegerObject>(i));
} }
driver.Start(); driver.Start();
for (int i = 0; i < 100; ++i) { for (int i = 0; i < kIterations; ++i) {
driver.SingleConcurrentStep(); driver.SingleConcurrentStep();
for (int j = 0; j < 100; ++j) { for (int j = 0; j < kIterations; ++j) {
map->erase(map->begin()); collection->erase(collection->begin());
} }
} }
driver.FinishSteps(); driver.FinishSteps();
driver.FinishGC(); driver.FinishGC();
} }
TEST_F(ConcurrentMarkingTest, SwapHashMaps) { template <typename C>
void SwapCollections() {
constexpr int kIterations = 10;
IncrementalMarkingTestDriver driver(ThreadState::Current()); IncrementalMarkingTestDriver driver(ThreadState::Current());
using Map = HeapHashMap<Member<IntegerObject>, Member<IntegerObject>>; Persistent<CollectionWrapper<C>> persistent =
Persistent<CollectionWrapper<Map>> persistent = MakeGarbageCollected<CollectionWrapper<C>>();
MakeGarbageCollected<CollectionWrapper<Map>>(); C* collection = persistent->GetCollection();
Map* map = persistent->GetCollection();
driver.Start(); driver.Start();
for (int i = 0; i < 100; ++i) { for (int i = 0; i < (kIterations * kIterations); ++i) {
Map new_map; C* new_collection = MakeGarbageCollected<C>();
for (int j = 0; j < 10 * i; ++j) { for (int j = 0; j < kIterations * i; ++j) {
new_map.insert(MakeGarbageCollected<IntegerObject>(j), new_collection->insert(MakeGarbageCollected<IntegerObject>(j));
MakeGarbageCollected<IntegerObject>(j));
} }
driver.SingleConcurrentStep(); driver.SingleConcurrentStep();
map->swap(new_map); collection->swap(*new_collection);
} }
driver.FinishSteps(); driver.FinishSteps();
driver.FinishGC(); driver.FinishGC();
} }
TEST_F(ConcurrentMarkingTest, AddToHashSet) { // HeapHashMap
IncrementalMarkingTestDriver driver(ThreadState::Current());
using Set = HeapHashSet<Member<IntegerObject>>; template <typename T>
Persistent<CollectionWrapper<Set>> persistent = class HeapHashMapAdapter : public HeapHashMap<T, T> {
MakeGarbageCollected<CollectionWrapper<Set>>(); public:
Set* set = persistent->GetCollection(); template <typename U>
driver.Start(); ALWAYS_INLINE void insert(U* u) {
for (int i = 0; i < 100; ++i) { HeapHashMap<T, T>::insert(u, u);
driver.SingleConcurrentStep();
for (int j = 0; j < 100; ++j) {
int num = 100 * i + j;
set->insert(MakeGarbageCollected<IntegerObject>(num));
}
} }
driver.FinishSteps(); };
driver.FinishGC();
TEST_F(ConcurrentMarkingTest, AddToHashMap) {
AddToCollection<HeapHashMapAdapter<Member<IntegerObject>>>();
}
TEST_F(ConcurrentMarkingTest, RemoveFromHashMap) {
RemoveFromCollection<HeapHashMapAdapter<Member<IntegerObject>>>();
}
TEST_F(ConcurrentMarkingTest, SwapHashMaps) {
SwapCollections<HeapHashMapAdapter<Member<IntegerObject>>>();
}
// HeapHashSet
TEST_F(ConcurrentMarkingTest, AddToHashSet) {
AddToCollection<HeapHashSet<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromHashSet) { TEST_F(ConcurrentMarkingTest, RemoveFromHashSet) {
IncrementalMarkingTestDriver driver(ThreadState::Current()); RemoveFromCollection<HeapHashSet<Member<IntegerObject>>>();
using Set = HeapHashSet<Member<IntegerObject>>;
Persistent<CollectionWrapper<Set>> persistent =
MakeGarbageCollected<CollectionWrapper<Set>>();
Set* set = persistent->GetCollection();
for (int i = 0; i < 10000; ++i) {
set->insert(MakeGarbageCollected<IntegerObject>(i));
}
driver.Start();
for (int i = 0; i < 100; ++i) {
driver.SingleConcurrentStep();
for (int j = 0; j < 100; ++j) {
set->erase(set->begin());
}
}
driver.FinishSteps();
driver.FinishGC();
} }
TEST_F(ConcurrentMarkingTest, SwapHashSets) { TEST_F(ConcurrentMarkingTest, SwapHashSets) {
IncrementalMarkingTestDriver driver(ThreadState::Current()); SwapCollections<HeapHashSet<Member<IntegerObject>>>();
using Set = HeapHashSet<Member<IntegerObject>>; }
Persistent<CollectionWrapper<Set>> persistent =
MakeGarbageCollected<CollectionWrapper<Set>>(); // HeapLinkedHashSet
Set* set = persistent->GetCollection(); template <typename T>
driver.Start(); class HeapLinkedHashSetAdapter : public HeapLinkedHashSet<T> {
for (int i = 0; i < 100; ++i) { public:
Set new_set; ALWAYS_INLINE void swap(HeapLinkedHashSetAdapter<T>& other) {
for (int j = 0; j < 10 * i; ++j) { HeapLinkedHashSet<T>::Swap(other);
new_set.insert(MakeGarbageCollected<IntegerObject>(j));
}
driver.SingleConcurrentStep();
set->swap(new_set);
} }
driver.FinishSteps(); };
driver.FinishGC();
TEST_F(ConcurrentMarkingTest, AddToLinkedHashSet) {
AddToCollection<HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, AddToVector) { TEST_F(ConcurrentMarkingTest, RemoveFromLinkedHashSet) {
IncrementalMarkingTestDriver driver(ThreadState::Current()); RemoveFromCollection<HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
using V = HeapVector<Member<IntegerObject>>; }
Persistent<CollectionWrapper<V>> persistent =
MakeGarbageCollected<CollectionWrapper<V>>(); TEST_F(ConcurrentMarkingTest, SwapLinkedHashSets) {
V* vector = persistent->GetCollection(); SwapCollections<HeapLinkedHashSetAdapter<Member<IntegerObject>>>();
driver.Start(); }
for (int i = 0; i < 100; ++i) {
driver.SingleConcurrentStep(); // HeapListHashSet
for (int j = 0; j < 100; ++j) {
int num = 100 * i + j; template <typename T>
vector->push_back(MakeGarbageCollected<IntegerObject>(num)); class HeapListHashSetAdapter : public HeapListHashSet<T> {
} public:
ALWAYS_INLINE void swap(HeapListHashSetAdapter<T>& other) {
HeapListHashSet<T>::Swap(other);
} }
driver.FinishSteps(); };
driver.FinishGC();
TEST_F(ConcurrentMarkingTest, AddToListHashSet) {
AddToCollection<HeapListHashSetAdapter<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromVector) { TEST_F(ConcurrentMarkingTest, RemoveFromListHashSet) {
IncrementalMarkingTestDriver driver(ThreadState::Current()); RemoveFromCollection<HeapListHashSetAdapter<Member<IntegerObject>>>();
using V = HeapVector<Member<IntegerObject>>; }
Persistent<CollectionWrapper<V>> persistent =
MakeGarbageCollected<CollectionWrapper<V>>(); TEST_F(ConcurrentMarkingTest, SwapListHashSets) {
V* vector = persistent->GetCollection(); SwapCollections<HeapListHashSetAdapter<Member<IntegerObject>>>();
for (int i = 0; i < 10000; ++i) { }
vector->push_back(MakeGarbageCollected<IntegerObject>(i));
// HeapHashCountedSet
TEST_F(ConcurrentMarkingTest, AddToHashCountedSet) {
AddToCollection<HeapHashCountedSet<Member<IntegerObject>>>();
}
TEST_F(ConcurrentMarkingTest, RemoveFromHashCountedSet) {
RemoveFromCollection<HeapHashCountedSet<Member<IntegerObject>>>();
}
TEST_F(ConcurrentMarkingTest, SwapHashCountedSets) {
SwapCollections<HeapHashCountedSet<Member<IntegerObject>>>();
}
// HeapVector
template <typename T>
class HeapVectorAdapter : public HeapVector<T> {
public:
template <typename U>
ALWAYS_INLINE void insert(U* u) {
HeapVector<T>::push_back(u);
} }
driver.Start(); ALWAYS_INLINE void erase(typename HeapVector<T>::iterator) {
for (int i = 0; i < 100; ++i) { HeapVector<T>::pop_back();
driver.SingleConcurrentStep();
for (int j = 0; j < 100; ++j) {
vector->pop_back();
}
} }
driver.FinishSteps(); };
driver.FinishGC();
TEST_F(ConcurrentMarkingTest, AddToVector) {
AddToCollection<HeapVectorAdapter<Member<IntegerObject>>>();
}
TEST_F(ConcurrentMarkingTest, RemoveFromVector) {
RemoveFromCollection<HeapVectorAdapter<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, SwapVectors) { TEST_F(ConcurrentMarkingTest, SwapVectors) {
IncrementalMarkingTestDriver driver(ThreadState::Current()); SwapCollections<HeapVectorAdapter<Member<IntegerObject>>>();
using V = HeapVector<Member<IntegerObject>>;
Persistent<CollectionWrapper<V>> persistent =
MakeGarbageCollected<CollectionWrapper<V>>();
V* vector = persistent->GetCollection();
driver.Start();
for (int i = 0; i < 100; ++i) {
V new_vector;
for (int j = 0; j < 10 * i; ++j) {
new_vector.push_back(MakeGarbageCollected<IntegerObject>(j));
}
driver.SingleConcurrentStep();
vector->swap(new_vector);
}
driver.FinishSteps();
driver.FinishGC();
} }
TEST_F(ConcurrentMarkingTest, AddToDeque) { // HeapDeque
IncrementalMarkingTestDriver driver(ThreadState::Current());
using D = HeapDeque<Member<IntegerObject>>; template <typename T>
Persistent<CollectionWrapper<D>> persistent = class HeapDequeAdapter : public HeapDeque<T> {
MakeGarbageCollected<CollectionWrapper<D>>(); public:
D* deque = persistent->GetCollection(); template <typename U>
driver.Start(); ALWAYS_INLINE void insert(U* u) {
for (int i = 0; i < 100; ++i) { HeapDeque<T>::push_back(u);
driver.SingleConcurrentStep();
for (int j = 0; j < 100; ++j) {
int num = 100 * i + j;
deque->push_back(MakeGarbageCollected<IntegerObject>(num));
}
} }
driver.FinishSteps(); ALWAYS_INLINE void erase(typename HeapDeque<T>::iterator) {
driver.FinishGC(); HeapDeque<T>::pop_back();
}
ALWAYS_INLINE void swap(HeapDequeAdapter<T>& other) {
HeapDeque<T>::Swap(other);
}
};
TEST_F(ConcurrentMarkingTest, AddToDeque) {
AddToCollection<HeapDequeAdapter<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromDeque) { TEST_F(ConcurrentMarkingTest, RemoveFromDeque) {
IncrementalMarkingTestDriver driver(ThreadState::Current()); RemoveFromCollection<HeapDequeAdapter<Member<IntegerObject>>>();
using D = HeapDeque<Member<IntegerObject>>;
Persistent<CollectionWrapper<D>> persistent =
MakeGarbageCollected<CollectionWrapper<D>>();
D* deque = persistent->GetCollection();
for (int i = 0; i < 10000; ++i) {
deque->push_back(MakeGarbageCollected<IntegerObject>(i));
}
driver.Start();
for (int i = 0; i < 100; ++i) {
driver.SingleConcurrentStep();
for (int j = 0; j < 100; ++j) {
deque->pop_back();
}
}
driver.FinishSteps();
driver.FinishGC();
} }
TEST_F(ConcurrentMarkingTest, SwapDeque) { TEST_F(ConcurrentMarkingTest, SwapDeques) {
IncrementalMarkingTestDriver driver(ThreadState::Current()); SwapCollections<HeapDequeAdapter<Member<IntegerObject>>>();
using D = HeapDeque<Member<IntegerObject>>;
Persistent<CollectionWrapper<D>> persistent =
MakeGarbageCollected<CollectionWrapper<D>>();
D* deque = persistent->GetCollection();
driver.Start();
for (int i = 0; i < 100; ++i) {
D new_deque;
for (int j = 0; j < 10 * i; ++j) {
new_deque.push_back(MakeGarbageCollected<IntegerObject>(j));
}
driver.SingleConcurrentStep();
deque->Swap(new_deque);
}
driver.FinishSteps();
driver.FinishGC();
} }
} // namespace concurrent_marking_test } // namespace concurrent_marking_test
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment